How To Use Filter Pattern With Generic Lambda Expression

Written by mirambek-nagashbekov | Published 2020/09/10
Tech Story Tags: design-patterns | csharp | coding | programming | wpf | code-quality | filter-pattern | linq

TLDR The filter and pipeline patterns can be optimized with code reduction using lambda expression(shortcuts for anonymous method) as concrete filter condition. To demonstrate concept, the sample WPF UI application was created. The next section will describes view model usage filter pattern. In MVVM the one of responsibilities of the view model is to handle user interaction and data changes. In our case the filter condition value changes should be passed to business layer to apply filters on given data collection. In this sample application, the only one EmployeeTypeselected property filter is demonstrated.via the TL;DR App

The filter and pipeline patterns can be optimized with code reduction using lambda expression(shortcuts for anonymous method) as concrete filter condition. To demonstrate concept, the sample WPF UI application was created. Here is Source code

Pipeline and filter pattern

Traditionally filter pattern interface is implemented for every new filter. Instead of implementing interface for every filter condition, the generic lambda expression can be used as input to filters pipeline. As result, there will be less code. The following is class diagram:
ConditionAggregator is pipeline class where it stores collection of Condition<T>. Filter<T> owns ConditionAggregator or Condition<T> to apply filter conditions on data collection. When Filter<T> apply function is called, ICondition<T> check method is executed.  ConditionAggregator<T> has event OnFilterChanged. It is triggered when the collection or condition value is changed at view model classes.  The next section will describes view model usage filter pattern.

Using the code

Usage in View Model
MVVM framework explanation can be read in this link. In MVVM  the one of responsibilities of the view model is to handle user interaction and data changes. In our case the filter condition value changes should be passed to business layer to apply filters on given data collection. The condition value changes in view model will trigger ConditionAggregator<T> OnFilterChanged event where filter apply method is subscribed. The following is class diagram of view model:
Employee entity class is created to contain employee information. The generic T type of filter design pattern will be replaced with Employee class. EmployeeList holds list of employee data and Filters to apply. The class constructor receives condition list and passes to filter list.
public EmployeeList(IEmployeesRepository repository, ConditionAggregator<employee> conditionAggregator)
        {
            this.repository = repository;
            this.filters = new ConcreteFilter<employee>(conditionAggregator);
            conditionAggregator.OnFilterChanged += this.FilterList;
            _ = initAsync();
        }
FilterList method is subscribed to OnFilterChanged event to apply filters on data when condition or value changed event occurs.
private void FilterList()
{
    this.Employees = this.filters.Apply(this.employeesFullList);
}
EmployeesViewModel is connected to UI. In this sample application, the only one EmployeeTypeselected property filter is demonstrated but the many filters can be passed to ConditionAggregator. The following code snippet is constructor method where Filter condition is registered.
     public EmployeesViewModel(IEmployeesRepository repository)
        {
            this.repository = repository;
            Condition&lt;employee&gt; filterEmployee = new Condition&lt;employee&gt;((e) =&gt; e.employeeCode == this.EmployeeTypeSelected);
            this.conditionAggregator = new ConditionAggregator&lt;employee&gt;(new List&lt;condition&lt;employee&gt;&gt; { filterEmployee });
            this.EmployeeList = new EmployeeList(repository, this.conditionAggregator);            
        }  
&lt;/condition&lt;employee&gt;&lt;/employee&gt;&lt;/employee&gt;&lt;/employee&gt;
The condition is given as lambda expression. It can be as many as necessary since ConditionAggregator constructor accepts the List of filter conditions. The primary goal of code reduction of creating specific filter condition class is achieved.

Architecture of sample application

WPF.Demo.DataFilter project is WPF UI view. It has one grid and one combobox to filter. WPF.Demo.DataFilter.ViewModels project handles data and filter changes and reloads data for UI update. WPF.Demo.DataFilter.Common project is full implementation of Filter and pipeline patterns. WPF.Demo.DataFilter.DAL loads simple json file as data store.
This is main UI:

Published by HackerNoon on 2020/09/10