2015-04-19 3 views
1

Я пытаюсь создать выражение, которое использует FirstOrDefault с предикатом в выражении IEnumerable<TComparable>, но оно дает мне эту ошибку: Параметр 'o' не был связан в указано LINQ для выражения Сущности запросаНе удается преобразовать этот 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")); 

Проблема в том, что я не знаю, как связать тип строки, поскольку у нее нет свойства, которое даст значение свойства.

КСТАТИ: 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 для простых типов, таких как string.

Например. Если я должен построить дерево выражения для метода 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); 

Но для строкового типа я буду просто делать: (Так как ваше выражение будет просто be 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» (это только в комментарии). Затем вы должны принять правильное решение, которое объясняет, что вы должны использовать тот же экземпляр выражения параметра в списке объектов и параметров лямбда. – MBoros

Смежные вопросы