从Object创建Dynamic Func

我有一个标准对象,其中我将每个属性转换为func,如果它的值不为null。

public class TestClassCriteria { public bool? ColumnA { get; set; } public bool? ColumnB { get; set; } } 

这是我到目前为止所做的,但我很确定我没有正确定义lambda。 这就是我想要实现的目标。 funcs.Add(x => x.ColumnA == criteria.ColumnA)

 var properties = criteria.GetType().GetProperties(); var funcs = new List<Func>(); foreach (var property in properties) { var propertyName = property.Name; funcs.Add(x => x.GetType().GetProperty(propertyName).Name == criteria.GetType().GetProperty(propertyName).Name); } 

它没有崩溃或导致任何错误,它只是不起作用。

您将提供的任何帮助将不胜感激。

你想要这样的东西吗?

  static List> GetCriteriaFunctions() { var criteriaFunctions = new List>(); // searching for nullable properties of criteria var criteriaProperties = typeof(TCriteria) .GetProperties() .Where(p => p.PropertyType.IsGenericType && p.PropertyType.GetGenericTypeDefinition() == typeof(Nullable<>)); foreach (var property in criteriaProperties) { // this is entity parameter var entityParameterExpression = Expression.Parameter(typeof(TEntity)); // this is criteria parameter var criteriaParameterExpression = Expression.Parameter(typeof(TCriteria)); // this is criteria property access: "criteria.SomeProperty" var criteriaPropertyExpression = Expression.Property(criteriaParameterExpression, property); // this is testing for equality between criteria property and entity property; // note, that criteria property should be converted first; // also, this code makes assumption, that entity and criteria properties have the same names var testingForEqualityExpression = Expression.Equal( Expression.Convert(criteriaPropertyExpression, property.PropertyType.GetGenericArguments()[0]), Expression.Property(entityParameterExpression, property.Name)); // criteria.SomeProperty == null ? true : ((EntityPropertyType)criteria.SomeProperty == entity.SomeProperty) var body = Expression.Condition( Expression.Equal(criteriaPropertyExpression, Expression.Constant(null)), Expression.Constant(true), testingForEqualityExpression); // let's compile lambda to method var criteriaFunction = Expression.Lambda>(body, entityParameterExpression, criteriaParameterExpression).Compile(); criteriaFunctions.Add(criteriaFunction); } return criteriaFunctions; } 

样本实体和样本标准:

 class CustomerCriteria { public int? Age { get; set; } public bool? IsNew { get; set; } } class Customer { public string Name { get; set; } public int Age { get; set; } public bool IsNew { get; set; } } 

用法:

  var criteriaFunctions = GetCriteriaFunctions(); var customer1 = new Customer { Name = "John", Age = 35, IsNew = false }; var customer2 = new Customer { Name = "Mary", Age = 27, IsNew = true }; var criteria1 = new CustomerCriteria { Age = 35 }; var criteria2 = new CustomerCriteria { IsNew = true }; Console.WriteLine("Is match: {0}", criteriaFunctions.All(f => f(customer1, criteria1))); Console.WriteLine("Is match: {0}", criteriaFunctions.All(f => f(customer2, criteria1))); Console.WriteLine("Is match: {0}", criteriaFunctions.All(f => f(customer1, criteria2))); Console.WriteLine("Is match: {0}", criteriaFunctions.All(f => f(customer2, criteria2))); 

此代码使用强类型成员访问而不是动态代码,因此,您可以缓存每对“实体 – 标准”的标准列表,并且测试实例forms匹配更快。

您当前的表达式是比较属性名称,但我想您要比较属性值:

 var funcs = new List>(); foreach (var property in criteria.GetType().GetProperties()) { funcs.Add(x => x.GetType().GetProperty(property.Name).GetValue(x, null) == property.GetValue(criteria, null)); } 

但是,你确定需要这样做吗? 可能有更好的方法来重构代码,这样您就不需要使用reflection来比较两个不相关的对象上碰巧具有相同名称的属性。