2013-06-02 2 views
6

я нашел кусок кода следующего вида:Синтаксис для ссылки на метод, возвращающий выражение в другой метод?

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

В других частях коды, я хочу, чтобы получить тот же объект легкого CustomerContact, только не из счета-фактуры, а от самого Клиента. Таким образом, очевидно, что нужно сделать было бы иметь:

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

, а затем изменить Expression с Invoice в качестве входных данных для обозначения этого метода, то есть что-то вроде этого:

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

Что такое правильный синтаксис для это?

+2

Было бы полезно, если бы вы отправили сообщение об ошибке. –

+0

@newStackExchangeInstance: «Предполагается метод, делегат или событие» –

ответ

3

Вы можете использовать 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); 

Обратите внимание, что некоторые провайдеры LINQ имеют проблемы с такими Призыва выражений.

Самый простой способ обойти это (и дать вам более удобный синтаксис) является использование LINQKit:

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

Ой, это совершенно неэлегантно. Возможно, это лучшее решение, но я надеялся, что будет более простое решение, которое не включает в себя рефлексию или сторонние расширения ... –

+0

Я не думаю, что есть что-то проще, чем Expression.Invoke для составления выражений в этом манера. Метод LINQKIt довольно прост и изящен и дает вам возможность использовать язык lambdas для этого. – Ani

+0

Ну, оказывается, LinqKit будет полезен для моего проекта в других областях. Так что спасибо и ответим вам на кредит! :-) –

0

Вы уверены, что вам нужно использовать Expression? Если вам не нужны разные поставщики Linq для преобразования деревьев кода в запросы, тогда рассмотрите вместо этого только Func. Если вы просто используете Func так, что сигнатуры методов являются:

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

и

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

Тогда ваш синтаксис будет отлично подходит для построения второго Func прочь первой. Конечно, это будет работать только для объектов с памятью (с Linq-to-objects).

Проблема заключается в том, что для построения Expression вы должны явно построить дерево оценки, которое может быть довольно волосатым (используя различные статические методы на Expression). Из-за этой волосатости есть несколько вспомогательных пакетов, включая LINQKit.

+0

Да, мне нужно выражение; Я хочу, чтобы запрос выполнялся на стороне SQL. –

+0

Тогда пойдите с решением Ани! –

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