2013-06-02 9 views
6

znalazłem kawałek kodu z następującą postać:Składnia odnosząca się do metody zwracającej wyrażenie do innej metody?

public static Expression<Func<Invoice, CustomerContact>> GetCustomerContact() 
{ 
    return i => new CustomerContact { 
       FirstName = i.Customer.FirstName, 
       LastName = i.Customer.LastName, 
       Email = i.Customer.Email, 
       TelMobile = i.Customer.TelMobile, 
       }; 
} 

w innych częściach kodu, chcę dostać ten sam lekki CustomerContact przedmiotu, nie tylko z faktury, ale z samego Klienta. Więc oczywistym rozwiązaniem byłoby mieć:

public static Expression<Func<Customer, CustomerContact>> GetCustomerContact() 
{ 
    return c => new CustomerContact { 
       FirstName = c.FirstName, 
       LastName = c.LastName, 
       Email = c.Email, 
       TelMobile = c.TelMobile, 
       }; 
} 

a następnie zmienić Expression biorąc Invoice jako wejście odnieść się do tej metody, czyli coś takiego:

public static Expression<Func<Invoice, CustomerContact>> GetCustomerContact() 
{ 
    return i => GetCustomerContact(i.Customer); // doesn't compile 
} 

Jaka jest poprawna składnia to?

+2

Przydałby się komunikat o błędzie. –

+0

@newStackExchangeInstance: "Metoda, delegat lub wydarzenie jest oczekiwane" –

Odpowiedz

3

Można użyć Expression.Invoke:

var paramExpr = Expression.Parameter(typeof(Invoice), "i"); 
var propertyEx = Expression.Property(paramExpr, "Customer"); 

var body = Expression.Invoke(GetCustomerContactFromCustomer(), propertyEx); 

return Expression.Lambda<Func<Invoice, CustomerContact>>(body, paramExpr); 

Należy pamiętać, że niektórzy dostawcy LINQ mają problemy z takimi wywołania wyrażeń.

Najprostszym sposobem obejścia tego (i daje bardziej dogodnym składni) jest użycie LINQKit:

var expr = GetCustomerContactFromCustomer(); 
Expression<Func<Invoice, CustomerContact>> result = i => expr.Invoke(i.Customer);  
return result.Expand(); 
+0

Ouy, to dość nieeleganckie. Być może jest to najlepsze rozwiązanie, ale miałem nadzieję, że będzie prostsze rozwiązanie, które nie wymaga ani refleksji, ani rozszerzeń stron trzecich ... –

+0

Nie sądzę, że jest jakikolwiek sposób łatwiejszy niż Expression.Invoke do komponowania wyrażeń w tym sposób. Sposób LINQKIt jest jednak dość prosty i elegancki i daje ci możliwość używania języka lambdas. – Ani

+0

Cóż, okazuje się, że LinqKit przyda się w moim projekcie w innych dziedzinach. Więc dziękuję i udziel mi kredytu! :-) –

0

Czy na pewno trzeba użyć Expression? Jeśli nie potrzebujesz innych dostawców Linq, aby konwertować drzewa kodu na zapytania, zamiast tego rozważ użycie tylko Func. Jeśli wystarczy użyć Func tak że podpisy metody są:

public static Func<Customer, CustomerContact> GetCustomerContact(); 

i

public static Func<Customer, CustomerContact> GetCustomerContact(); 

Wtedy twoja składnia byłoby dobrze do budowy drugiego Func off pierwszej. Oczywiście będzie to działać tylko dla obiektów w pamięci (z Linq-do-obiektów).

Problem polega na tym, że aby zbudować model Expression, należy wyraźnie zbudować drzewo oceny, które może być dość owłosione (przy użyciu różnych metod statycznych na Expression). Z powodu tej włochatości istnieje kilka pakietów pomocniczych, w tym LINQKit.

+0

Tak, potrzebuję ekspresji; Chcę, aby zapytanie działało po stronie SQL. –

+0

Następnie idź z rozwiązaniem Ani! –

Powiązane problemy