2015-04-19 42 views
1

我試圖創建一個表達式,該表達式使用FirstOrDefault與表達式IEnumerable<TComparable>上的謂詞,但它給了我這個錯誤: 參數'o'沒有綁定在指定的LINQ to Entities查詢表達式無法將此LINQ轉換爲動態表達式樹

我有一個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")); 

問題是我不知道如何綁定字符串類型,因爲它沒有提供屬性值的屬性。

BTW:collectionValuesType = typeof運算(字符串)

我已經編輯了一個問題,建議把事情說清楚。

+0

你的意思是如何調用新函數?或者如何在函數中使用「o」參數? – ANewGuyInTown

+0

如何使用函數內部的「o」參數,它的方式是我得到這個錯誤:參數'o'未綁定在指定的LINQ to Entities查詢表達式中 我已經將名稱「o」添加到用於調試的firstOrDefaultPredicateParameter –

+0

你的意思是這樣的嗎? 'ParameterExpression parameterExpression = System.Linq.Expressions.Expression.Parameter(collectionValuesType,「x」);'。 – ANewGuyInTown

回答

1

您不需要爲簡單類型(如字符串)構造Expression.Property。

例如。如果我必須建立表達式樹的OrderBy方法Person類型與Name財產,我將構建表達式樹是這樣的:

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

您可以使用相同的概念來解決您的問題。

0

OMG,整天失去了,因爲我在Expression.Call中傳遞了錯誤的參數。

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

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

@ANewGuyInTown感謝您的幫助,看了之後你的答案,我在我的代碼做了「全面掃描」,發現這個錯誤

+0

請修改你的問題以反映你真正的問題是什麼,然後接受正確的答案。據我所知,你的主要問題是錯誤「參數'o'沒有綁定在指定的LINQ to Entities查詢表達式」(它只在註釋中)。那麼你應該接受正確的解決方案,這就解釋了你必須在lambda的主體和參數列表中使用相同的參數表達式實例。 – MBoros

相關問題