I created a method GetArticlePriceDefinedInErpPricePolicyAsync
, previously I had 4 versions of this method which was not good for maintance, one change caused editing 4 methods which were actually same, and it was bad concept since I would keep identical code x4.
The reason why I would like to write this method as generic is because there are 4 different classes that are using this method (webShopArticles
can be 4 different classes).
Purpose of this method is to receive list of some Dto’s and to return modified prices.
And solution to this could be to create this method as a generic so I could have only one method in my app instead of 4 same methods.
It would be much more easy to maintain the app etc.
Here is my code:
public async Task<List<T>> GetArticlePriceDefinedInErpPricePolicyAsync<T>(List<T> webShopArticles, Guid? externalCompanyId, CancellationToken cancellationToken)
{
var externalArticleIds = webShopArticles
.Where(x => GetPropertyValue<Guid?>(x, "ErpArticleId").HasValue)
.Select(x => GetPropertyValue<Guid>(x, "ErpArticleId"))
.ToArray();
var pricePolicyItems = new List<PricesRelatedToPricePolicy>();
var articlesFromPricePolicy = await _dbContext.ErpPricePolicyItems
.Where(x => externalArticleIds.Contains(GetPropertyValue<Guid>(x, "ExternalArticleId")))
.Select(x => new PricesRelatedToPricePolicy
{
Id = x.Id,
ErpArticleId = GetPropertyValue<Guid>(x, "ExternalArticleId"),
Priority = x.Priority,
PolicyTypeEnum = x.PolicyType,
Price = x.Price,
Discount1 = x.Discount1,
Discount2 = x.Discount2,
Discount3 = x.Discount3
})
.ToArrayAsync(cancellationToken);
pricePolicyItems.AddRange(articlesFromPricePolicy);
if (!pricePolicyItems.Any())
return webShopArticles;
ArticleMatching(webShopArticles, articlesFromPricePolicy);
return webShopArticles;
}
private List<T> ArticleMatching<T>(List<T> articles, PricesRelatedToPricePolicy[] articlesDefinedInPricesPolicy) where T : IErpPricePolicySyncProps
{
if (articlesDefinedInPricesPolicy[0] == null)
return articles;
foreach (var item in articles.Where(x => !x.MatchedPP.HasValue && x.ExternalSytemArticleId.HasValue))
{
var articleDefinedInPolicyPrice = articlesDefinedInPricesPolicy
.Where(x => x.ExternalSytemArticleId.HasValue && (x.ExternalSytemArticleId == item.ExternalSytemArticleId))
.FirstOrDefault();
item.Price = CalculateArticlePriceBasedOnPricePolicy(articleDefinedInPolicyPrice, item);
item.MatchedPP = articlesDefinedInPricesPolicy.Any(x => item.ExternalSytemArticleId.HasValue && x.ExternalSytemArticleId.Value == item.ExternalSytemArticleId.Value);
}
return articles;
}
But I am getting this error:
Error CS0314 The type ‘T’ cannot be used as type parameter ‘T’ in the generic type or method ‘PricePolicyCalculationService.ArticleMatching(List, PricesRelatedToPricePolicy[])’. There is no boxing conversion or type parameter conversion from ‘T’ to ‘Common.Dtos.Interfaces.IErpPricePolicySyncProps’.
IErpPricePolicySyncProps is interface that inheriting classes that will use this generic method
public interface IErpPricePolicySyncProps
{
public Guid? ErpArticleId { get; set; }
public Guid? ErpCategoryId { get; set; }
public Guid? ErpSubCategoryId { get; set; }
public Guid? ErpBrandId { get; set; }
public decimal Price { get; set; }
public bool? MatchedPP { get; set; }
}
Thanks in advance,
Cheers
>Solution :
The ArticleMatching
method expects the object you pass in to implement the IErpPricePolicySyncProps
interface. If you look at it, it will be something like this:
public void ArticleMatching<T>(List<T> articles, ...)
where T : IErpPricePolicySyncProps
So to fix this, you also need to mark your method in the same way:
public async Task<List<T>> GetArticlePriceDefinedInErpPricePolicyAsync<T>(List<T> webShopArticles, Guid? externalCompanyId, CancellationToken cancellationToken)
where T : IErpPricePolicySyncProps
{
...
}