从属性名称的字符串创建表达式?

我正在尝试基于一些JSON创建查询,我目前将JSON解析为一组规则,每个规则包含字段的名称,比较的类型(=,> etc)和要比较的值。

我遇到的问题是从规则到IQueryable对象,我猜我需要使用reflection并以某种方式构建表达式树,但我不确定正确的方法……

假设我有:

public class Order : BaseEntity { public int OrderID{ get; set; } } 

而我的规则是:

 public class Rule { public string field { get; set; } public Operations op { get; set; } public string data { get; set; } } 

运行它我得到:

 field = "OrderID" op = "eq" data = "123" 

我有方法用签名解析它:

 public IQueryable FilterObjectSet(IQueryable inputQuery) where T : class 

作为这种方法的一部分,我想做:

 inputQuery = inputQuery.Where(o => propertyInfo.Name == rule1.data); 

这不起作用,因为它基本上只生成sql“OrderID”=“123”,这显然是错误的,我需要它从inputQuery获取与propertyInfo.Name同名的列名,并以这种方式构建查询。 ..

希望有道理吗? 有什么建议?

编辑:我想我要问的是转换一个字符串(因为我可以简单地从规则构建一个)到一个表达式,也许使用动态LINQ?

像这样的东西:

 public static IQueryable FilterObjectSet(IQueryable inputQuery, Rule rule) where T : class { var par = Expression.Parameter(typeof(T)); var prop = Expression.PropertyOrField(par, rule.field); var propType = prop.Member.MemberType == System.Reflection.MemberTypes.Field ? ((FieldInfo)prop.Member).FieldType : ((PropertyInfo)prop.Member).PropertyType); // I convert the data that is a string to the "correct" type here object data2 = Convert.ChangeType(rule.data, propType, CultureInfo.InvariantCulture); var eq = Expression.Equal(prop, Expression.Constant(data2)); var lambda = Expression.Lambda>(eq, par); return inputQuery.Where(lambda); } 

如果您需要一些解释,可以询问。 请注意,这不适用于具有特殊隐式转换的类型(如具有string隐式转换的MyString类型)。 这是因为Convert.ChangeType仅使用IConvertible接口。

data空处理可能是应该处理的其他内容。

请注意,我不确定Expression.PropertyOrField是由各种IQueryable引擎(LINQ-to-SQL和EF)处理的。 我只用AsQueryable()引擎测试了它。 如果他们不“接受”它,则必须将其拆分为Expression.PropertyExpression.Field具体取决于rule.field

一个几乎等效的版本,不使用Expression.PropertyOrField

 public static IQueryable FilterObjectSet(IQueryable inputQuery, Rule rule) where T : class { Type type = typeof(T); var par = Expression.Parameter(type); Type fieldPropertyType; Expression fieldPropertyExpression; FieldInfo fieldInfo = type.GetField(rule.field); if (fieldInfo == null) { PropertyInfo propertyInfo = type.GetProperty(rule.field); if (propertyInfo == null) { throw new Exception(); } fieldPropertyType = propertyInfo.PropertyType; fieldPropertyExpression = Expression.Property(par, propertyInfo); } else { fieldPropertyType = fieldInfo.FieldType; fieldPropertyExpression = Expression.Field(par, fieldInfo); } object data2 = Convert.ChangeType(rule.data, fieldPropertyType); var eq = Expression.Equal(fieldPropertyExpression, Expression.Constant(data2)); var lambda = Expression.Lambda>(eq, par); return inputQuery.Where(lambda); } 

最后我使用了我在Guthrie博客上找到的Dynamic Linq库:

http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspx

使用这个我能够正确解析并使用我在规则中构建的参数