这几天因业务需要,在使用第三方的ORM查询数据库时,已知一些字符串的过滤条件,需要实现query.Where(p=>p.Age.ToString().Contains("2"))这样的查询操作,虽然可以用拼接sql语句的方式去实现该功能,但是会破坏程序的扩展性,所以想实现用字符串转换成Lambda的表达式。具体实现如下:
class Program
{
static void Main(string[] args)
{
var exp = GetToString<Person>("Age", 12);
Console.WriteLine("Hello World!");
Console.ReadKey();
}
public static Expression<Func<T, bool>> GetToString<T>(string propertyName, object propertyValue)
{
ParameterExpression parameter = Expression.Parameter(typeof(T), "p");
MemberExpression member = Expression.PropertyOrField(parameter, propertyName);
//拼接ToString
MethodInfo methodToString = member.Type.GetMethod("ToString", new Type[] { });
MethodCallExpression methodCall = Expression.Call(member, methodToString);
//拼接Contains
MethodInfo methodContains = typeof(string).GetMethod("Contains", new[] { typeof(string) });
ConstantExpression constant = Expression.Constant(propertyValue.ToString(), typeof(string));
MethodCallExpression methodCallContains = Expression.Call(methodCall, methodContains, constant);
return Expression.Lambda<Func<T, bool>>(methodCallContains, parameter);
}
}
public class Person
{
public int Age { get; set; }
public string Name { get; set; }
}
实现上述代码时有需要注意几个地方:

1. 在获取ToString方法时,我这里调用的方法不需要传参,但是依然要写"new Type[]{}",不然会报Ambiguous match found.(找不到明确的匹配项,而且这种写法也不行:“new []{}”)
2. 在获取Contains方法时,Contains方法的参数必须是字符串,所以propertyValue要ToString()
Expression很强大,有兴趣的可以研究研究!
