2013-08-19 22 views
16

Mam zmienną o nazwie sortColumn, która zawiera tekst kolumny, którą chcę posortować wynik zapytania według. Mam również ogólne repozytorium, które jako parametr przyjmuje wyrażenie, które zawiera pole, według którego chcę sortować. Nie mogę uzyskać od nazwy właściwości ciągu do wyrażenia.Utwórz wyrażenie ogólne z nazwy właściwości łańcucha

Więc rodzajowy repozytorium że mam zawiera następującą metodę

public IEnumerable<TEntity> Get<TOrderBy>(Expression<Func<TEntity, bool>> criteria, 
              Expression<Func<TEntity, TOrderBy>> orderBy, int pageIndex, 
              int pageSize, 
              bool isAssendingOrder = true, 
              EnumDeletePolicy deletePolicy = EnumDeletePolicy.ExcludeDeleted) 

Zawiadomienie drugi parametr to uzyskać jest Expression-Func-TEntity, TOrderBy. Jak już wspomniałem, mam zmienną o nazwie sortColumn, która zawiera ciąg dla właściwości na moim obiekcie TEntity, potrzebuję przekonwertować ten ciąg na wyrażenie, które mogę przekazać do metody Get.

Oto, co mam teraz.

 var parameter = Expression.Parameter(typeof(IContract)); 
     var memberExpression = Expression.Property(parameter, data.SortColumn); 
     var lambdaExpression = Expression.Lambda(memberExpression, parameter); 

Która tworzy obiekt typu LambdaExpression. Rzeczywistym typem tej LambdaExpression jest Expression-Func-IContract, ciąg znaków (lub jakikolwiek typ sortColumn właściwości jest). Jeśli zadzwonię do metody Get i przejdę do tej LambdaExpression i jawnie rzucę ją do typu Expression, to będzie działało dobrze. Problem polega na tym, że nie wiem, jaki jest typ wyrażenia, może to być ciąg, int, int ?, itp. Wszystko zależy od typu właściwości, która jest specyficzna dla właściwości sortColumn.

Czy możesz mi pomóc dokonać tego ostatniego skoku w odpowiednim typie ekspresji?

Edytuj w oparciu o sugestie Marca: Prawie wszystko działa, właściwie oparte jest na pytaniu, które właśnie działa, ale mam 1 pozostały problem.

The IContract, który jest typem jednostki, przeciwko któremu ja odpowiadam, dziedziczy po IRelationship. Jeśli określę pole z interfejsu IContract, powyższy kod zadziała. Jeśli określę pole z interfejsu IRelationship, poniższy wiersz zawiedzie.

 var memberExpression = Expression.Property(parameter, data.SortColumn); 

Gdy próbuję coś jak poniżej tak, że jestem chwytając MemberExpression z IRelationship, ale budowanie lambda w oparciu o IContract pojawia się błąd z repozytorium.

 var parameter = Expression.Parameter(typeof(IRelationship)); 
     var memberExpression = Expression.Property(parameter, data.SortColumn); 
     var orderBy = Expression.Lambda(memberExpression, Expression.Parameter(typeof(IContract))); 

Otrzymany błąd to "Parametr" nie był powiązany w określonym wyrażeniu zapytania LINQ do encji. "

Ostateczne wyrażenie, aby to działało to

 var parameter = Expression.Parameter(typeof(IContract)); 
     var memberExpression = Expression.Property(parameter, typeof(IRelationship), data.SortColumn); 
     var orderBy = Expression.Lambda(memberExpression, parameter); 

Więc musiałem podać parametr środku linii memberExpression, znaczy patrzeć w odziedziczonej interfejsu związku nieruchomości

+0

Co to chcesz zrobić z ekspresją? Istnieją sposoby użycia 'dynamic', aby zmusić go do przerzucenia na najbardziej odpowiednie ogólne przeciążenie, zasadniczo unikając' MakeGenericMethod'. Dowolne użycie? Na przykład: 'IQueryable filtered = Queryable.Where (source, (dynamic) expression);' –

Odpowiedz

17

You kinda trzeba użyć prawidłowego przeciążenia generycznego - co oznaczało, że musiałeś używać MakeGenericMethod; Jednakże, można również użyć dynamic celu uniknięcia konieczności korzystania MakeGenericMethod tutaj, na przykład (w tym przypadku poprzez Where, ale ważne jest to, jak to działa):

IQueryable<Foo> source = new[] { new Foo { Bar = 123 } }.AsQueryable(); 
Expression<Func<Foo,bool>> typed = x=>x.Bar == 123; 

LambdaExpression untyped = typed; 
IQueryable<Foo> filtered = Queryable.Where(source, (dynamic)untyped); 

Uwaga: nie można użyć rozszerzenie metody tutaj - stąd dlaczego musisz użyć Queryable.*.

Dla przykładu OrderBy używając kodu:

var parameter = Expression.Parameter(typeof(Foo)); 
var memberExpression = Expression.Property(parameter, "Bar"); 
var lambdaExpression = Expression.Lambda(memberExpression, parameter); 
LambdaExpression untyped = lambdaExpression; 

IQueryable<Foo> sorted = Queryable.OrderBy(source, (dynamic)untyped); 

var all = sorted.ToArray(); 

re edit:

var parameter = Expression.Parameter(typeof(IRelationship)); 
var memberExpression = Expression.Property(
    Expression.Convert(parameter, typeof(IContract)), data.SortColumn); 
var orderBy = Expression.Lambda(memberExpression, parameter); 
+0

Ale metoda, którą muszę wywołać, wymaga Expression-Func, a nie dynamicznego, więc nie mogę przekazać dynamicznej. –

+0

@PaulCavacas 'Queryable.Where' and 'Queryable.OrderBy' * take * take Expression-Func, a nie dynamiczny; to nie jest problem. Chodzi o to, że użycie 'dynamic' tutaj * sprawia, że ​​działa *. Magia. –

+0

Prawie wszystko działa. Jeden pozostały problem. Zapytaj o dalsze szczegóły. –

Powiązane problemy