如何在C#
中将此Lambda转换为表达式树var FieldName="SomeDynamicField";
var param = "SomeParam"
//Lambda to beCreated
x=>x.FieldName!=null && x.FieldName.ToLower().Contains(param )
到目前为止我已尝试过这个
private static Expression GetPropertyExpression(PropertyInfo prop, ParameterExpression paramExpr, ConstantExpression valueExpr) {
var memberAcc = Expression.MakeMemberAccess(paramExpr, prop);
Console.WriteLine(memberAcc);
var containsMember = typeof(string).GetMethod("Contains");
var toLower= typeof(String).GetMethod("ToLower",new [] {typeof(string)});
var ttt=Expression.Call(memberAcc,containsMember, valueExpr);
return Expression.Call(memberAcc,containsMember, valueExpr);
}
答案 0 :(得分:1)
你可以稍微轻松一点。您可以使用Contains
方法,而不是使用有趣地不支持将StringComparison
作为参数传递的IndexOf
方法。
你可以像这样实现它:
public static Expression<Func<T, bool>> ContainsValue<T>(string fieldName, string val) {
var type = typeof(T);
var member = Expression.Parameter(type, "param");
var memberExpression = Expression.PropertyOrField( member, fieldName);
var targetMethod = memberExpression.Type.GetMethod( "IndexOf", new Type[] { typeof(string), typeof(StringComparison) } );
var methodCallExpression = Expression.Call( memberExpression, targetMethod, Expression.Constant(val), Expression.Constant( StringComparison.CurrentCultureIgnoreCase ) );
return Expression.Lambda<Func<T, bool>>(
Expression.AndAlso(
Expression.NotEqual(memberExpression, Expression.Constant(null)),
Expression.GreaterThanOrEqual( methodCallExpression, Expression.Constant(0) )
),
member
);
}
这里的诀窍是我将IndexOf
方法与值为0的GreaterThanOrEqual
调用结合起来。
这最终给出了表达式
之后的测试类((param.Parameter != null) AndAlso (param.Parameter.IndexOf("test", CurrentCultureIgnoreCase) >= 0))
例如,你可以在dotnetfiddle找到,但我也在下面添加了完整的代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
public class Program
{
public static Expression<Func<T, bool>> ContainsValue<T>(string fieldName, string val) {
var type = typeof(T);
var member = Expression.Parameter(type, "param");
var memberExpression = Expression.PropertyOrField( member, fieldName);
var targetMethod = memberExpression.Type.GetMethod( "IndexOf", new Type[] { typeof(string), typeof(StringComparison) } );
var methodCallExpression = Expression.Call( memberExpression, targetMethod, Expression.Constant(val), Expression.Constant( StringComparison.CurrentCultureIgnoreCase ) );
return Expression.Lambda<Func<T, bool>>(
Expression.AndAlso(
Expression.NotEqual(memberExpression, Expression.Constant(null)),
Expression.GreaterThanOrEqual( methodCallExpression, Expression.Constant(0) )
),
member
);
}
public static void Main()
{
var items = new List<Test>() {
new Test() { Parameter = "Alpha" },
new Test(),
new Test() { Parameter = "Test" },
new Test() { Parameter = "test" },
new Test() { Parameter = "TEST" },
new Test() { Parameter = "Contains test" }
};
var expr = ContainsValue<Test>("Parameter", "test");
// you can see the body here
Console.WriteLine( expr.Body );
// and the result
var results = items.Where( expr.Compile() ).Select(t => t.Parameter).ToList();
Console.WriteLine( "Results: {0}", string.Join( ",", results ));
Console.WriteLine( "Total results: {0}", results.Count );
}
public class Test {
public string Parameter { get;set; }
}
}
输出:
((param.Parameter != null) AndAlso (param.Parameter.IndexOf("test", CurrentCultureIgnoreCase) >= 0))
Results: Test,test,TEST,Contains test
Total results: 4