【问题标题】:Can't convert this linq to dynamic expression tree无法将此 linq 转换为动态表达式树
【发布时间】:2015-06-26 13:18:50
【问题描述】:

我正在尝试创建一个表达式,它使用 FirstOrDefault 和 IEnumerable<TComparable> 表达式上的谓词,但它给了我这个错误: 参数“o”未绑定在指定的 LINQ to Entities 查询表达式中

我有一个这样的 linq 表达式:

IEnumerable<string> names = new List<string>() { "abc", "def", "ghi" };
string name = names.FirstOrDefault(o => o.Contains("abc"));

public static Expression FirstOrDefault(this Expression expression, Type collectionValuesType, MethodInfo comparerMethod, string keyword)
{
    MethodInfo firstOrDefaultMethod = typeof(Enumerable).GetMethods()
        .FirstOrDefault(o => o.Name == "FirstOrDefault" && o.GetParameters().Length == 2)
        .MakeGenericMethod(new Type[] { collectionValuesType });


  Type firstOrDefaultDelegateType = typeof(Func<,>).MakeGenericType(collectionValuesType, typeof(bool));
    ParameterExpression firstOrDefaultPredicateParameter = Expression.Parameter(collectionValuesType);


//THIS LINE binds the "o" in (o => o.Contains("abc")) , and it is where I'm stuck with since yesterday!
    MemberExpression firstOrDefaultParameterO = Expression.Property(expression, typeof(string).GetProperty(???)); 

//o => o.ComparerMethod(keyword)
MethodCallExpression firstOrDefaultCompareExpression = Expression.Call(
    firstOrDefaultParameterO,
    comparerMethod,
    Expression.Constant(keyword, typeof(string))
);

//expression.FirstOrDefault(firstOrDefaultCompareExpression);
return Expression.Call(
    firstOrDefaultMethod,
    expression,
    Expression.Lambda(firstOrDefaultDelegateType, firstOrDefaultCompareExpression, Expression.Parameter(collectionValuesType))
);
}

如果我有一个复杂的类型,我会这样使用:

public class Example { public string Name; }

//o => o.Name.Contains("abc"))
        MemberExpression firstOrDefaultParameterO = Expression.Property(expression, typeof(Example).GetProperty("Name")); 

问题是我不知道如何绑定字符串类型,因为它没有可以赋予属性值的属性。

顺便说一句:collectionValuesType = typeof(string)

我已按照建议编辑了问题以使事情变得清晰。

【问题讨论】:

  • 你的意思是如何调用新函数?或者如何在你的函数中使用“o”参数?
  • 如何在函数内使用“o”参数,我得到这个错误的方式:参数'o'未绑定在指定的LINQ to Entities查询表达式中我添加了名称"o" 到 firstOrDefaultPredicateParameter 进行调试
  • 你的意思是这样的吗? ParameterExpression parameterExpression = System.Linq.Expressions.Expression.Parameter(collectionValuesType, "x");.
  • 您可能会发现这个答案很有用:stackoverflow.com/questions/4135625/…
  • @ANewGuyInTown 参数已定义(ParameterExpression firstOrDefaultPredicateParameter),问题是将其绑定到谓词属性“o”。我查看了您发布的页面,但它没有帮助我,我不想循环遍历 ienumerable,FirstOrDefault 方法会为我完成。我看到了一个示例,其中使用 IEnumerable&lt;SomeComplexType&gt; 而不是 IEnumerable&lt;string&gt; 绑定将是这样的:MemberExpression memberExpression = Expression.Property(expression, typeof(SomeComplexType).GetProperty("propertyName"));

标签: c# linq expression expression-trees


【解决方案1】:

您不需要为字符串等简单类型构造 Expression.Property。

例如。如果我必须为具有 Name 属性的类型 Person 的 OrderBy 方法构建表达式树,我将像这样构建表达式树:

ParameterExpression pe = System.Linq.Expressions.Expression.Parameter(typeof(T), "p");
Expression<Func<T, TPropertyType>> expr = System.Linq.Expressions.Expression.Lambda<Func<T, TPropertyType>>(System.Linq.Expressions.Expression.Property(pe, propertyName), pe);

但是对于字符串类型,我会简单地做:(因为对于字符串类型,您的表达式将只是 x=>x)

If( typeof(T)==typeof(string))
{
    ParameterExpression pe = System.Linq.Expressions.Expression.Parameter(typeof(T), "p");
    Expression<Func<T, TPropertyType>> expr = System.Linq.Expressions.Expression.Lambda<Func<T, TPropertyType>>(pe,pe);
}

您可能可以使用相同的概念来解决您的问题。

【讨论】:

    【解决方案2】:

    我的天啊,因为我最后在 Expression.Call 中传递了错误的参数,所以损失了一整天。

    return Expression.Call(
        firstOrDefaultMethod,
        expression,
        Expression.Lambda(firstOrDefaultDelegateType, firstOrDefaultCompareExpression, 
    
    //THIS IS THE PROBLEM, it should be "firstOrDefaultPredicateParameter"
    Expression.Parameter(collectionValuesType))
            );
    

    @ANewGuyInTown 感谢您的帮助,在查看了您的答案后,我在代码中进行了“全面扫描”并发现了这个错误

    【讨论】:

    • 请编辑您的问题以反映您的真正问题,然后接受正确答案。据我了解,您的主要问题是错误“参数'o'未绑定在指定的LINQ to Entities查询表达式中”(仅在评论中)。然后您应该接受正确的解决方案,这说明您必须在 lambda 的主体和参数列表中使用相同的参数表达式实例。
    猜你喜欢
    • 1970-01-01
    • 2010-12-04
    • 1970-01-01
    • 2020-01-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多