简体   繁体   English

模式根据字符串列表返回对象?

[英]Pattern to return objects based on a list of strings?

This is killing me because I feel like I've seen something around before, but my searches are coming up empty and I don't have various patterns committed to memory (yet). 这让我很伤心,因为我觉得我以前见过的东西,但是我的搜索结果是空的,我还没有承诺记忆的各种模式(还)。

The Situation 情况

I have a search grid that allows users to filter based on multiple attributes. 我有一个搜索网格,允许用户根据多个属性进行过滤。 The filters that users would like are passed in via a NameValueCollection and parsed out. 用户想要的过滤器通过NameValueCollection传递并解析出来。

Currently, our legacy app checks for each potential filter in a separate if statement and then runs custom code. 目前,我们的遗留应用程序会在单独的if语句中检查每个可能的过滤器,然后运行自定义代码。 And since cyclomatic complexity just isn't my thing, 30 almost identical if statements bug me. 因为圈复杂度不是我的事,30个几乎相同的if语句会让我烦恼。

Towards a Better Way 走向更好的方式

Rather than continuing to check each item in a hard-coded way, I've re-written the parser so that now I can quickly obtain a list of all filters that will be applied. 我没有继续以硬编码方式检查每个项目,而是重新编写了解析器,现在我可以快速获取将要应用的所有过滤器的列表。 I'm also refactoring the filters themselves into their own classes. 我也将过滤器本身重构为自己的类。

So, I have a list of filters in string form ("Name", "BirthDate", etc.) and a bunch of classes ( NameFilter , BirthDateFilter , etc.) 所以,我有一个字符串形式的过滤器列表(“名称”,“BirthDate”等)和一堆类( NameFilterBirthDateFilter等)

The Question 问题

What is a good, standard way to take a list of strings representing filter names and turn it into a list of those filter objects themselves? 获取表示过滤器名称的字符串列表并将其转换为这些过滤器对象本身的列表的标准方法是什么?

I suppose I could do some sort of FilterLocator with a LocateFilter(string filterName) method, but that seems like it would lead to one long switch statement and seems kind of blech. 我想我可以使用FilterLocator LocateFilter(string filterName)方法做一些FilterLocator ,但这似乎会导致一个很长的switch语句,看起来有点粗糙。

I get the sense this is heading towards some sort of IoC/DI solution, but that I don't know enough about either to fully realize it yet. 我明白这是朝着某种IoC / DI解决方案的方向发展,但我还不知道要么完全实现它。

Thanks for your thoughts! 谢谢你的想法!

Use a dictionary where the key is your filter name, and the value is your filter object. 使用字典,其中键是您的过滤器名称,值是您的过滤器对象。

Rather than hard coding this dictionary, create a custom attribute that gives each filter object a filter name. 不是硬编码这个字典,而是创建一个自定义属性,为每个过滤器对象提供一个过滤器名称。 Then, use reflection to find those objects and create a static dictionary that can be used later. 然后,使用反射来查找这些对象并创建可以在以后使用的静态字典。 This way, there is no hard coding of the individual filter mappings at all. 这样,根本没有对各个过滤器映射进行硬编码。

Here's a sample set up for this: 以下是为此设置的示例:

[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
public class FilterNameAttribute : Attribute
{
    public FilterNameAttribute(string filterName)
    {
        FilterName = filterName;
    }

    public string FilterName { get; private set; }
}

[FilterName("MyFilterName")]
public class MyFilter
{
    //Do whatever you want here
}

public static class FilterHelper
{
    static Dictionary<string, Type> _filterTypesDict;

    static FilterHelper()
    {
        var assembly = Assembly.GetExecutingAssembly();

        _filterTypesDict = assembly.GetTypes()
            .Select(type => new { type, attrib = (FilterNameAttribute)type.GetCustomAttributes(typeof(FilterNameAttribute), false).FirstOrDefault() })
            .Where(x => x.attrib != null)
            .ToDictionary(x => x.attrib.FilterName, x => x.type);
    }

    public static Type GetFilterType(string filterName)
    {
        Type filterType;

        if (!_filterTypesDict.TryGetValue(filterName, out filterType))
        {
            throw new Exception("Unknown Filter Name.");
        }

        return filterType;
    }

    public static object GetFilter(string filterName)
    {
        return Activator.CreateInstance(GetFilterType(filterName));
    }
}

Like in the comments I would definitely create a dictionary for your filters. 就像在评论中我肯定会为您的过滤器创建一个字典。 Also with that I would create a base class for each filter with Name property and Apply method. 另外,我将使用Name属性和Apply方法为每个过滤器创建一个基类。 And when your application starts up you can gather filter classes with reflection by the base filter class and populate the dictionary of filters using Name property as the key (or you can just use the name of the filter class), this way you don't even need to build up the dictionary manually, every time you add a filter class it will automatically appear int the dictionary. 当您的应用程序启动时,您可以通过基本过滤器类收集带有反射的过滤器类,并使用Name属性作为键填充过滤器字典(或者您可以只使用过滤器类的名称),这样您就不会甚至需要手动建立字典,每次添加过滤器类时它都会自动出现在字典中。 This will allow your LocateFilter(string filterName) method be really simple and straightforward. 这将允许您的LocateFilter(string filterName)方法非常简单明了。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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