2010-08-19 3 views
6

Tôi có hai cây biểu được định nghĩa như thế này:Đi qua một cây biểu hiện như một tham số khác cây biểu

private Expression<Func<TEntity, TPropertyResult>> PropertyAccessor { get; set; } 

private Expression<Func<TPropertyResult, bool>> TestExpression { get; set; } 

tôi cần phải tạo ra một cây biểu thức mới mà sẽ cho kết quả tương đương với:

var expression = p => this.TestExpression(this.PropertyAccessor(p)); 

Khi sử dụng Expression.Invoke(this.TestExpression, this.PropertyAccessor), tôi gặp lỗi sau

{"Expression of type 'System.Func`2[MyEntity,System.String]' cannot be used for parameter of type 'System.String'"}

TPropertyResult là một chuỗi trong khi thử nghiệm.

Tôi đã thử sử dụng Expression.Call hoặc Expression.Invoke. Không may mắn. Tôi nên sử dụng cái gì?

+0

lỗi biên dịch là gì? Ngoài ra, mã không thể đọc được. Bạn có chắc chắn rằng công cụ .Net 2.0 không đủ cho những gì bạn muốn hoàn thành? –

+0

Khi sử dụng Invoke, nó nói: '{" Biểu thức kiểu 'System.Func'2 [MyEntity, System.String]' không thể được sử dụng cho tham số kiểu 'System.String' "}'. Đó là khi tôi cố gắng xác định một chuỗi là 'TPropertyResult', nhưng vấn đề không bị giới hạn trong một chuỗi. –

Trả lời

7

Tôi nghĩ rằng đây có phải những gì bạn đang yêu cầu:

Expression<Func<TEntity, bool>> Combined 
{ 
    get 
    { 
     var entity = Expression.Parameter(typeof(TEntity)); 
     var pa = Expression.Invoke(PropertyAccessor, entity); 
     var te = Expression.Invoke(TestExpression, pa); 
     return (Expression<Func<TEntity, bool>>) Expression.Lambda(te, entity); 
    } 
} 

Tôi thử nghiệm này và nó hoạt động như tôi mong đợi.

Tuy nhiên, đọc lại câu hỏi ban đầu của bạn (trước khi chỉnh sửa), tôi bắt đầu có ấn tượng rằng bạn đã đặt câu hỏi sai và có thể bạn không cần cây biểu thức. Nếu tất cả bạn cần là chức năng, sau đó bạn có thể sử dụng chúng mà không cần Expression:

private Func<TEntity, TPropertyResult> PropertyAccessor { get; set; } 
private Func<TPropertyResult, bool> TestExpression { get; set; } 
private Func<TEntity, bool> Combined 
{ 
    get 
    { 
     return entity => TestExpression(PropertyAccessor(entity)); 
    } 
} 

Ví dụ về sử dụng:

// Set up the original functions 
PropertyAccessor = entity => GenerateResult(entity); 
TestExpression = result => result.IsCool(); 

// This stores a reference to the combined function 
var fn = Combined; 

// This actually evaluates the function 
bool isCool = fn(myEntity); 

// Alternatively, you could evaluate the function directly, without the variable 
bool isCool = Combined(myEntity); 
+0

Wow cảm ơn bạn vì câu trả lời này. Tôi đã vượt qua đầu của tôi bằng cách lặn vào biểu hiện. Tôi đoán rằng nhìn vào mã ASP.NET MVC làm cho bạn nghĩ rằng 'Expression ' là cần thiết ở khắp mọi nơi. –

+0

Marc Gravell có một bài viết tuyệt vời về InfoQ về cách thức và lý do tại sao bạn nên sử dụng Expression và một số ví dụ cụ thể tốt. http://www.infoq.com/articles/expression-compiler –

+0

Cảm ơn, tôi cần sử dụng nó trong 'linq to sql' nhưng gặp phải lỗi này:' Kiểu nút biểu thức LINQ 'Invoke' không được hỗ trợ trong LINQ đến Entities.' bạn có thể giúp tôi không? – Mohsen