我正在努力熟悉表情树,而且我正在撞墙。我希望能够动态创建LINQ to XML查询,所以我想让自己熟悉Expression Trees。我从一个简单的LINQ to XML语句开始,我希望能够动态生成:
// sample data
var sampleData = new XElement("Items",
new XElement("Item", new XAttribute("ID", 1)),
new XElement("Item", new XAttribute("ID", 2)),
new XElement("Item", new XAttribute("ID", 3))
);
// simple example using LINQ to XML (hard-coded)
var resultsStatic = from item in sampleData.Elements("Item")
where item.Attribute("ID").Value == "2"
select item;
// trying to recreate the above dynamically using expression trees
IQueryable<XElement> queryableData = sampleData.Elements("Item").AsQueryable<XElement>();
ParameterExpression alias = Expression.Parameter(typeof(XElement), "item");
MethodInfo attributeMethod = typeof(XElement).GetMethod("Attribute", new Type[] { typeof(XName) });
PropertyInfo valueProperty = typeof(XAttribute).GetProperty("Value");
ParameterExpression attributeParam = Expression.Parameter(typeof(XName), "ID");
Expression methodCall = Expression.Call(alias, attributeMethod, new Expression[] { attributeParam });
Expression propertyAccessor = Expression.Property(methodCall, valueProperty);
Expression right = Expression.Constant("2");
Expression equalityComparison = Expression.Equal(propertyAccessor, right);
var resultsDynamic = queryableData.Provider.CreateQuery(equalityComparison);
调用CreateQuery时出现的错误是&#39;参数表达式无效&#39;。 equalityComparison的调试视图显示&#39;(。调用$ item.Attribute($ ID))。值==&#34; 2&#34;&#39;。有人可以识别我做错了什么吗?
答案 0 :(得分:2)
为了更好地了解正在进行的操作,请始终使用所需查询的方法语法。在你的情况下,它如下(我特别包括类型,虽然通常我会使用var
):
IQueryable<XElement> queryableData = sampleData.Elements("Item").AsQueryable();
IQueryable<XElement> queryStatic = queryableData
.Where((XElement item) => item.Attribute("ID").Value == "2");
现在让我们看看你有什么。
首先,attributeParam
变量
ParameterExpression attributeParam = Expression.Parameter(typeof(XName), "ID");
从静态查询中可以看出,属性名称没有lambda参数 - 唯一支持的(和必需的)参数是item
(在代码中由alias
表示变量)。因此,ConstantExpression
类型为XName
,值为&#34; ID&#34;:
var attributeParam = Expression.Constant((XName)"ID");
其次,equalityComparison
变量。它包含的全部是item.Attribute("ID").Value == "2"
表达式。但Where
方法需要Expression<Func<XElement, bool>>
,因此您必须使用equalityComparison
作为正文并alias
作为参数创建此类:
var predicate = Expression.Lambda<Func<XElement, bool>>(equalityComparison, alias);
最后你必须调用Where
方法。你可以直接这样做:
var queryDynamic = queryableData.Where(predicate);
或动态:
var whereCall = Expression.Call(
typeof(Queryable), "Where", new Type[] { queryableData.ElementType },
queryableData.Expression, Expression.Quote(predicate));
var queryDynamic = queryableData.Provider.CreateQuery(whereCall);
您可以查看使用过的Expression
方法文档,了解它们的详细信息。
答案 1 :(得分:0)
Linq to XML在内存中工作,意味着你没有表达树,只需使用Enumerable扩展方法。使您的代码更简单,更易于阅读!!!