C# 无法将此linq转换为动态表达式树

C# 无法将此linq转换为动态表达式树,c#,linq,expression,expression-trees,C#,Linq,Expression,Expression Trees,我正在尝试创建一个表达式,该表达式在IEnumerable表达式上使用带谓词的FirstOrDefault,但它给了我以下错误: 参数“o”未绑定在指定的LINQ to Entities查询表达式中 我有这样一个linq表达式: IEnumerable<string> names = new List<string>() { "abc", "def", "ghi" }; string name = names.FirstOrDefault(o => o.Contai

我正在尝试创建一个表达式,该表达式在IEnumerable表达式上使用带谓词的FirstOrDefault,但它给了我以下错误: 参数“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))
);
}
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);
问题是我不知道如何绑定字符串类型,因为它没有一个属性可以给出属性值

顺便说一句:collectionValuesType=字符串类型


我已经按照建议对问题进行了编辑,以澄清问题。

对于字符串等简单类型,不需要构造Expression.Property

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

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))
);
}
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);
}

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

OMG,因为我在表达式中传递了错误的参数而浪费了整整一天。最后调用

return Expression.Call(
    firstOrDefaultMethod,
    expression,
    Expression.Lambda(firstOrDefaultDelegateType, firstOrDefaultCompareExpression, 

//THIS IS THE PROBLEM, it should be "firstOrDefaultPredicateParameter"
Expression.Parameter(collectionValuesType))
        );

@ANewGuyInTown感谢您的帮助,在查看您的答案后,我对代码进行了全面扫描,发现了此错误

您的意思是如何调用新函数?或者如何在函数中使用o参数?如何在函数中使用o参数,我得到此错误的方式:参数“o”未绑定在指定的LINQ to Entities查询表达式中我已将名称o添加到firstOrDefaultPredicateParameter以进行调试您的意思是这样的吗?ParameterExpression ParameterExpression=System.Linq.Expressions.Expression.ParametercollectionValuesType,x。您可能会发现这个答案很有用:@ANewGuyInTown参数已定义ParameterExpression firstOrDefaultPredicateParameter,问题是将其绑定到谓词属性o。我查看了你发布的页面,但它对我没有帮助,我不想循环使用ienumerable,FirstOrDefault方法可以帮我完成。我看到一个示例,其中使用IEnumerable而不是IEnumerable,绑定如下:MemberExpression MemberExpression=Expression.Propertyexpression,typeofSomeComplexType.GetPropertypropertyName;请编辑您的问题以反映您真正的问题,然后接受正确答案。据我所知,您的主要问题是参数“o”未绑定到指定的LINQ to Entities查询表达式中的错误,该表达式仅位于注释中。然后,您应该接受正确的解决方案,这说明您必须在lambda的主体和参数列表中使用相同的参数表达式实例。