Tôi đang tìm cách kết hợp hai biểu thức lambda, không sử dụng Expression.Invoke
trên một trong hai biểu thức. Tôi muốn về cơ bản xây dựng một biểu thức mới có hai chuỗi riêng biệt. Xét đoạn mã sau:Kết hợp Biểu thức Lambda
class Model {
public SubModel SubModel { get; set;}
}
class SubModel {
public Foo Foo { get; set; }
}
class Foo {
public Bar Bar { get; set; }
}
class Bar {
public string Value { get; set; }
}
Và cho phép nói rằng tôi đã có hai biểu thức:
Expression<Func<Model, Foo>> expression1 = m => m.SubModel.Foo;
Expression<Func<Foo, string>> expression2 = f => f.Bar.Value;
Và tôi muốn tham gia cùng họ với nhau để chức năng được biểu thức sau đây:
Expression<Func<Model, string>> joinedExpression = m => m.SubModel.Foo.Bar.Value;
duy nhất cách tôi có thể nghĩ để làm điều này là sử dụng ExpressionVisitor như thế này:
public class ExpressionExtender<TModel, TIntermediate> : ExpressionVisitor
{
private readonly Expression<Func<TModel, TIntermediate>> _baseExpression;
public ExpressionExtender(Expression<Func<TModel, TIntermediate>> baseExpression)
{
_baseExpression = baseExpression;
}
protected override Expression VisitMember(MemberExpression node)
{
_memberNodes.Push(node.Member.Name);
return base.VisitMember(node);
}
private Stack<string> _memberNodes;
public Expression<Func<TModel, T>> Extend<T>(Expression<Func<TIntermediate, T>> extend)
{
_memberNodes = new Stack<string>();
base.Visit(extend);
var propertyExpression = _memberNodes.Aggregate(_baseExpression.Body, Expression.Property);
return Expression.Lambda<Func<TModel, T>>(propertyExpression, _baseExpression.Parameters);
}
}
Và sau đó sử dụng nó như thế này:
var expExt = new ExpressionExtender<Model, Foo>(expression1);
var joinedExpression = expExt.Extend(expression2);
Nó hoạt động, nhưng nó cảm thấy một chút thời gian cho tôi. Tôi vẫn đang cố gắng che đi những biểu cảm đầu của mình và tự hỏi liệu có cách nào để thể hiện điều này một cách thành ngữ hơn không, và tôi có một nghi ngờ lén lút rằng tôi thiếu một điều gì đó hiển nhiên.
Các lý do Tôi muốn làm điều này là sử dụng nó với ASP.net MVC 3 người giúp đỡ Html. Tôi có một số ViewModels lồng nhau và một số phần mở rộng HtmlHelper giúp giải quyết chúng, vì vậy biểu thức cần phải là một bộ sưu tập của MemberExpressions
cho những người trợ giúp MVC được xây dựng để xử lý chúng một cách chính xác và xây dựng các giá trị thuộc tính tên lồng nhau một cách chính xác. Bản năng đầu tiên của tôi là sử dụng Expression.Invoke()
và gọi biểu thức đầu tiên và chuỗi nó vào thứ hai, nhưng những người trợ giúp MVC không thích điều đó lắm. Nó mất bối cảnh phân cấp của nó.
+1 Điều này có ý nghĩa rất nhiều khi tôi nhìn thấy nó. Một điều tôi đã không đề cập đến trong câu hỏi ban đầu: là có một cách để làm điều này mà không có đột biến hoặc bắt đầu biểu hiện. Ví dụ, tôi có một biểu thức cốt lõi mà tôi cần phải mở rộng theo nhiều cách khác nhau, tạo ra các biểu thức mới với mỗi lời gọi. –
@ 32bitkid có! biểu thức là bất biến; Tôi đã không đột biến một trong hai người họ! –
Cảm ơn bạn rất nhiều vì đã giúp đỡ. –