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).
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.
Currently, our legacy app checks for each potential filter in a separate if statement and then runs custom code. And since cyclomatic complexity just isn't my thing, 30 almost identical if
statements bug me.
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.)
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.
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.
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. 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. This will allow your LocateFilter(string filterName) method be really simple and straightforward.
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.