Assume that predicate.Or dynamically generates a sql where clause based on a list of strings. Is there a way to refactor this so that I don't have to hard code the case statements? Is there a way to move away from switch statement and refactor into a simpler/elegant foreach?
//contentTypes will ALWAYS have members that are the string class name of some classes in our project
//ex List<string> contentTypes = new List<string>{"News", "Photos", "Video", "Product"}
foreach (string t in contentTypes)
{
switch (t)
{
case "News":
predicate = predicate.Or(ci => ci is News);
break;
case "Photos":
predicate = predicate.Or(ci => ci is Photos);
break;
case "Video":
predicate = predicate.Or(ci => ci is Video);
break;
case "Product":
predicate = predicate.Or(ci => ci is Product);
break;
}
}
CodePudding user response:
You can definitely make it cleaner:
foreach (string t in contentTypes)
{
Expression<Func<ContentItem, bool>> typePredicate = t switch
{
nameof(News) => ci is News,
nameof(Product) => ci is Photos,
nameof(Video) => ci is Video,
nameof(Product) => ci is Product,
_ => throw new InvalidOperationException($"Unexpected content type: '{t}'")
};
predicate = predicate.Or(typePredicate);
}
Another option would be to create a Dictionary<string, Expression<Func<ContentItem, bool>>
and then just use:
foreach (string t in contentTypes)
{
predicate = predicate.Or(typePredicates[t]);
}
(Use TryGetValue
if you want a clearer exception than the KeyNotFoundException
you'll get from the indexer.)
If you have a lot of types to add, you could create a helper method to make the dictionary creation pretty seamless. But I would stick to being explicit about which types you do want to support.