CSharp · Console
using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Reflection;
using FluentAssertions;
class Program
{
static void Main()
{
//Arrange
var filters = new List<ExpressionFilter>{new ExpressionFilter{PropertyName = "CountryOfOrigin", Comparison = Comparison.Contains, Value = "Fr"}, };
var car = new Car{CountryOfOrigin = "France", };
//Act
var expressionTree = Test<Car>(filters[0]);
Func<Car, bool> anonymousFunc = expressionTree.Compile();
//Assert
anonymousFunc(car).Should().BeTrue();
Console.WriteLine("Passed");
}
static Expression<Func<T, bool>> Test<T>(ExpressionFilter filter)
{
ParameterExpression param = Expression.Parameter(typeof (T), "t");
var exp = ExpressionRetriever.GetExpression<T>(param, filter);
return Expression.Lambda<Func<T, bool>>(exp, param);
}
}
public class Car
{
public string Model
{
get;
set;
}
public string Make
{
get;
set;
}
public string CountryOfOrigin
{
get;
set;
}
public string CountryOfProduction
{
get;
set;
}
public int MaxMilesPerHour
{
get;
set;
}
public int NumberOfSeats
{
get;
set;
}
public int MilesPerGallon
{
get;
set;
}
public double WeightInKg
{
get;
set;
}
public decimal BasePrice
{
get;
set;
}
public decimal FullPrice
{
get;
set;
}
}
public static class ExpressionRetriever
{
private static MethodInfo containsMethod = typeof (string).GetMethod("Contains", new Type[]{typeof (string)});
private static MethodInfo startsWithMethod = typeof (string).GetMethod("StartsWith", new Type[]{typeof (string), typeof (StringComparison)});
private static MethodInfo endsWithMethod = typeof (string).GetMethod("EndsWith", new Type[]{typeof (string)});
public static Expression GetExpression<T>(this ParameterExpression param, ExpressionFilter filter)
{
MemberExpression member = Expression.Property(param, filter.PropertyName);
ConstantExpression constant = Expression.Constant(filter.Value);
switch (filter.Comparison)
{
case Comparison.Equal:
return Expression.Equal(member, constant);
case Comparison.GreaterThan:
return Expression.GreaterThan(member, constant);
case Comparison.GreaterThanOrEqual:
return Expression.GreaterThanOrEqual(member, constant);
case Comparison.LessThan:
return Expression.LessThan(member, constant);
case Comparison.LessThanOrEqual:
return Expression.LessThanOrEqual(member, constant);
case Comparison.NotEqual:
return Expression.NotEqual(member, constant);
case Comparison.Contains:
return Expression.Call(member, containsMethod, constant);
case Comparison.StartsWith:
return Expression.Call(member, startsWithMethod, constant, Expression.Constant(StringComparison.InvariantCultureIgnoreCase));
case Comparison.EndsWith:
return Expression.Call(member, endsWithMethod, constant);
default:
return null;
}
}
}
public class ExpressionFilter
{
public string PropertyName
{
get;
set;
}
public object Value
{
get;
set;
}
public Comparison Comparison
{
get;
set;
}
}
public enum Comparison
{
Equal,
LessThan,
LessThanOrEqual,
GreaterThan,
GreaterThanOrEqual,
NotEqual,
Contains, //for strings
StartsWith, //for strings
EndsWith //for strings
}