Description
When designing an application you must think about the scalability of the application itself and of the modules you are creating. The example below show how I designed a simple filtering system and took advantage of the interface power.
For the filtering system i created an interface that is inherited both by a filter type and a collection of filters. In this way it doesn’t matter to the end user if he has one item or a collection, he will make a validation in the same way.
public interface IFilter<T> { bool Pass(T element); } public class Filter<T> : IFilter<T> { Predicate<T> filterFunction { get; set; } public Filter(Predicate<T> filterFunction) { this.filterFunction = filterFunction; } public bool Pass(T obj) { return filterFunction.Invoke(obj); } } public class FilterGroup<T> : IFilter<T> { private List<IFilter<T>> Filters { get; set; } public FilterGroup() { this.Filters = new List<IFilter<T>>(); } public FilterGroup(params IFilter<T>[] filters) { this.Filters = filters.ToList(); } private void Add(IFilter<T> filter) { this.Filters.Add(filter); } public bool Pass(T element) { return this.Filters.All(x => x.Pass(element)); } }
Now let’s test this functionality. Define a base class Person and then define the following filters:
- A simple filter
- A filter group that combines 2 filters
- A mixed filter that combines 1 filter and 1 filter group
public class Person { public string Name { get; set; } public string City { get; set; } public int Age { get; set; } public Person(string name, int age, string city) { this.Name = name; this.Age = age; this.City = city; } } this.Persons = new List<Person> { new Person("John", 21, "New York"), new Person("John", 22, "Sydney"), new Person("Bob", 18, "Cairo"), new Person("Morgan", 18, "Fukushima"), new Person("Kayla", 18, "Beirut"), new Person("Mark", 50, "Mumbai") }; IFilter<Person> filterAgeUnder50 = new Filter<Person>((p) => p.Age < 50); IFilter<Person> filterNameNotJohn = new Filter<Person>(p => p.Name != "John"); IFilter<Person> filterCombined = new FilterGroup<Person>(filterAgeUnder50, filterNameNotJohn); IFilter<Person> filterNotInCairo = new Filter<Person>(p => p.City != "Cairo"); IFilter<Person> filterNested = new FilterGroup<Person>(filterCombined, filterNotInCairo); filteredPersons1 = Persons.Where(p => filterAgeUnder50.Pass(p)) .ToList(); filteredPersons2 = Persons.Where(p => filterNameNotJohn.Pass(p)) .ToList(); filterPerson3 = Persons.Where(p => filterCombined.Pass(p)) .ToList(); filterPerson4 = Persons.Where(p => filterNested.Pass(p)) .ToList();