这让我很伤心,因为我觉得我之前已经看过一些东西,但我的搜索结果是空的,我还没有承诺记忆的各种模式(还)。
我有一个搜索网格,允许用户根据多个属性进行过滤。用户想要的过滤器通过NameValueCollection
传入并解析出来。
目前,我们的旧版应用程序会在单独的if语句中检查每个可能的过滤器,然后运行自定义代码。由于圈复杂度不是我的事,30个几乎相同的if
语句让我感到烦恼。
我没有继续以硬编码的方式检查每个项目,而是重新编写了解析器,以便现在我可以快速获取将要应用的所有过滤器的列表。我也将过滤器本身重构为自己的类。
所以,我有一个字符串形式的过滤器列表("名称"," BirthDate"等)和一堆类(NameFilter
,{{ 1}}等等。)
获取表示过滤器名称的字符串列表并将其转换为这些过滤器对象本身的列表有什么好的标准方法?
我想我可以使用BirthDateFilter
方法进行某种FilterLocator
,但这似乎会导致一个很长的切换声明,并且看起来有点像。
我明白这是朝着某种IoC / DI解决方案的方向发展,但我还不知道要么完全实现它。
感谢您的想法!
答案 0 :(得分:2)
使用字典,其中键是您的过滤器名称,值是您的过滤器对象。
创建一个自定义属性,为每个过滤器对象提供过滤器名称,而不是对此字典进行硬编码。然后,使用反射来查找这些对象并创建可以在以后使用的静态字典。这样,根本没有对各个过滤器映射进行硬编码。
以下是为此设置的示例:
[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));
}
}
答案 1 :(得分:1)
在评论中,我肯定会为您的过滤器创建一个字典。另外,我将使用名称属性和应用方法为每个过滤器创建基类。当您的应用程序启动时,您可以通过基本过滤器类收集带有反射的过滤器类,并使用名称属性作为键填充过滤器字典(或者您可以使用过滤器类的名称)这样你甚至不需要手动建立字典,每次添加过滤器类时它都会自动出现在字典中。这将允许您的LocateFilter(string filterName)方法非常简单明了。