Search code examples
c#.net-3.5subsonic

Combining multiple SubSonic.Where filters


Is it possible to combine multiple filters in Subsonic 2.1 to a shorter piece of code?

    SubSonic.Where filterTaal = new SubSonic.Where();
        filterTaal.ColumnName = Pagina.Columns.Taal;
        filterTaal.Comparison = SubSonic.Comparison.Equals;
        filterTaal.ParameterValue = taal;

    SubSonic.Where filterKey = new SubSonic.Where();
        filterKey.ColumnName = Pagina.Columns.PaginaKey;
        filterKey.Comparison = SubSonic.Comparison.Equals;
        filterKey.ParameterValue = paginaKey;

        PaginaCollection paginaCollection = new PaginaCollection()
            .Where(filterTaal)
            .Where(filterKey) 
            .Load();

It seems to me that above code can be shorter?


Solution

  • You could write your own extension method and use ExpressionTrees. Result will be something like this:

    PaginaCollection paginaCollection = new PaginaCollection()
        .SlimWhere(x => x[paginaColumns.PaginaKey] == paginaKey)
        .SlimWhere(x => x[paginaColumns.Taal] == taal)
        .Load();
    

    The extension method will be smth. like this:

    public static PaginaCollector SlimWhere(this PaginaCollector paginaCollector, Expression<Func<WhereDummy, bool>> expression)
    {
        var mainExpression = expression.Body as BinaryExpression;
        SubSonic.Where result = ParseFilter(mainExpression);
    
        switch (mainExpression.NodeType)
        {
            case ExpressionType.Equal:        
                result.Comparison = Comparison.Equals;
                break;
    
            ...
    
            default:
                throw new NotImplementedException();
        }
    
        return paginaCollector.Where(result);
    }
    

    And the helper methods will be:

    private static SubSonic.Where ParseFilter(BinaryExpression expression)
    {
        var columnNameMethod = (MethodCallExpression)expression.Left;
        var columnNameExpression = columnNameMethod.Arguments[0];
    
        var parameterValueExpression = expression.Right;
    
        string columnName = GetValue<string>(columnNameExpression);
        object parameterValue = GetValue<object>(parameterValueExpression);
    
        Where result = CreateWheteFilterDummy(columnName, parameterValue);
    
        return result;
    }
    
    private static Where CreateWheteFilterDummy(string columnName, object parameterValue)
    {
        SubSonic.Where result = new Where();
        result.ColumnName = columnName;
        result.ParameterValue = parameterValue;
        return result;
    }
    
    private static T GetValue<T>(Expression columnNameExpression)
    {
        var columnNameObjectMember = Expression.Convert(columnNameExpression, typeof(T));
        var columnNameGetter = Expression.Lambda<Func<T>>(columnNameObjectMember);
        return columnNameGetter.Compile()();
    }
    

    WhereDummy is a dummy class only to provide more readable syntax, because .SlimWhere(paginaColumns.PaginaKey == paginaKey) is not so understandable.

    public class WhereDummy
    {
        public string this[string columnname]
        {
            get
            {
                return columnname;
            }
        }
    }