System.Object上的LINQ(仅在运行时使用反射知道的类型)

时间:2010-08-16 06:43:34

标签: linq reflection

我有一个类似的要求,其中我在ADO.NET实体模型中有3个主要实体...我正在构建一个框架,其中基于传入的XML根元素我必须使用反射创建特定实体的实例并设置其属性..

但是当涉及到子实体时......我无法在其上使用LINQ查询,因为在设计时不知道该类型。 PropertyInfo.GetValue给了我一个对象,我无法运行LINQ查询(即使我将它强制转换为IQueryable或IEnumerable)。我甚至无法在设计时对其进行类型转换,因为这将是一种硬编码,并且将失去我的通用框架目的。

我尝试使用动态关键字..但在此我也无法编写LINQ查询..它给出了动态调度模型不支持LINQ查询的消息。!!!

有人可以提供帮助..

关心Badal

1 个答案:

答案 0 :(得分:0)

就像@Yuriy Faktorovich所推荐的那样,动态LINQ可能是你最好的镜头。

另一个选项是动态构建 expression trees 并通过反射执行表达式。请记住,这并不容易,可能需要一些时间来围绕表达式API,但对于简单的表达式来说,它并不是太糟糕。

示例:假设您要复制此表达式:

p => p.FirstName == firstName

您可以按如下方式构建表达式树:

var myType = Type.GetType("Person"); // <-- Find your type based on XML
var firstName = "John";

var param = Expression.Parameter(myType, "p");
var firstNameProperty = Expression.Property(param, "FirstName");
var constantExpression = Expression.Constant(firstName);
var equalsExpression = Expression.Equal(firstNameProperty, constantExpression);

var lambda = Expression.Lambda(equalsExpression, param);

lambda的运行时类型为Expression<Func<Person,bool>>,然后您可以将其传递给任何IQueryable实现。

<强>更新

然后在IQueryable上动态调用某种方法,你可以做类似以下的事情:

var queryableType = typeof(Queryable);
var whereMethod = queryableType.GetMethod("Where", BindingFlags.Public | BindingFlags.Static);

var parameters = new object[] { query, lambda }; // query is your IQueryable object
var list = whereMethod.Invoke(null, parameters);