C# 创建动态表达式树
如何将这个Lambda转换为C中的表达式树# 到目前为止我已经试过了C# 创建动态表达式树,c#,asp.net,.net,linq,lambda,C#,Asp.net,.net,Linq,Lambda,如何将这个Lambda转换为C中的表达式树# 到目前为止我已经试过了 private static Expression GetPropertyExpression(PropertyInfo prop, ParameterExpression paramExpr, ConstantExpression valueExpr) { var memberAcc = Expression.MakeMemberAccess(paramExpr, prop); Console.Write
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);
}
你可以自己稍微简单一点。您可以使用
IndexOf
方法,而不是使用Contains
方法,该方法不支持作为参数传递的StringComparison
您可以这样实现它:
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
);
}
您可以在上找到一个示例,但我也在下面添加了完整的代码
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; }
}
}
到目前为止你尝试了什么?你被困在哪里了?我一直在尝试编写此代码来筛选任何列表。它可以在大写的私有静态表达式GetPropertyExpression(PropertyInfo-prop,ParameterExpression-ParameterExpr,ConstantExpression-valueExpr){var memberAcc=Expression.MakeMemberAccess(ParameterExpr,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,valuexpr);return Expression.Call(memberAcc,containsMember,valuexpr);}请将代码添加到问题中,而不是在注释中,至少在那里你可以用一种好的方式格式化它(使用你问题下的链接)谢谢Icepickle,我希望它能用于具有常见数据类型的类,如字符串、小数、双精度等。目前,它工作得很好,但在字符串字段上only@EmmanuelOgoma这当然是可能的,因为有许多不同的表达方式。然而,他们没有包含方法,例如,还有很多事情要做。根据您希望在以后如何组合表达式,这可能是相当多的工作;)这个lambda可以工作,但我不知道如何创建它的表达式。注意名为x=>x.FieldName的Tostring方法=null&&x.FieldName.Tostring().ToLower().Contains(param)@EmmanuelOgoma我认为您将其简化了一点,但当然,从您的问题来看,很难了解您的上下文。或者我认为它很复杂:)如果你愿意,我们可以考虑你的要求
((param.Parameter != null) AndAlso (param.Parameter.IndexOf("test", CurrentCultureIgnoreCase) >= 0))
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