简体   繁体   中英

C#: How to convert string into class to use in an "is" operation?

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;
                }
            }

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM