2012-10-03 30 views
13

Có cách nào để tạo một thể hiện của một đối tượng với bộ khởi tạo đối tượng bằng một cây biểu thức không? Ý tôi là tạo một Cây Biểu hiện để xây dựng lambda này:Biểu thức để tạo một thể hiện với đối tượng khởi tạo

// my class 
public class MyObject { 
    public bool DisplayValue { get; set; } 
} 

// my lambda: 
var lambda = (Func<bool, MyObject>) 
      (displayValue => new MyObject { DisplayValue = displayValue }); 

Làm cách nào để tạo lambda này với cây Biểu thức?

UPDATE:

Tôi tryed bản thân mình và viết mã sau:

public static Func<bool, dynamic> Creator; 

    static void BuildLambda() { 
     var expectedType = typeof(MyObject); 
     var displayValueParam = Expression.Parameter(typeof(bool), "displayValue"); 
     var ctor = Expression.New(expectedType); 
     var local = Expression.Parameter(expectedType, "obj"); 
     var displayValueProperty = Expression.Property(ctor, "DisplayValue"); 

     var returnTarget = Expression.Label(expectedType); 
     var returnExpression = Expression.Return(returnTarget,local, expectedType); 
     var returnLabel = Expression.Label(returnTarget, Expression.Default(expectedType)); 

     var block = Expression.Block(
      new[] { local }, 
      Expression.Assign(local, ctor), 
      Expression.Assign(displayValueProperty, displayValueParam), 
      Expression.Return(Expression.Label(expectedType), local, expectedType), 
      returnExpression, 
      returnLabel 
      ); 
     Creator = 
      Expression.Lambda<Func<bool, dynamic>>(block, displayValueParam) 
       .Compile(); 
    } 

Nhưng nó ném các lỗi sau:

Cannot jump to undefined label ''.

tất cả mọi người có thể giúp tôi xin vui lòng?

+0

Bạn có thể đọc bài đăng của tôi: http://www.abhisheksur.com/2010/09/use-of-expression-trees-in-lamda-c. html để tạo ra chính mình? – abhishek

+0

Nhờ liên kết, nó có vẻ là một aricle greate. Nhưng tiếc là tôi là một anh chàng mới trong biểu hiện và bài viết của bạn rất nặng. Bạn có thể gửi đề nghị của bạn được không? –

Trả lời

41

Đại diện initializers đối tượng trong một biểu thức, bạn nên sử dụng Expression.MemberInit():

Expression<Func<bool, MyObject>> BuildLambda() { 
    var createdType = typeof(MyObject); 
    var displayValueParam = Expression.Parameter(typeof(bool), "displayValue"); 
    var ctor = Expression.New(createdType); 
    var displayValueProperty = createdType.GetProperty("DisplayValue"); 
    var displayValueAssignment = Expression.Bind(
     displayValueProperty, displayValueParam); 
    var memberInit = Expression.MemberInit(ctor, displayValueAssignment); 

    return 
     Expression.Lambda<Func<bool, MyObject>>(memberInit, displayValueParam); 
} 

Để xác minh điều này thực sự làm những gì bạn muốn, bạn có thể gọi ToString() trên biểu thức tạo ra. Trong trường hợp này, đầu ra là như mong đợi:

displayValue => new MyObject() {DisplayValue = displayValue} 
+0

@svick cảm ơn bạn rất rất rất nhiều: D những gì tôi đang tìm kiếm thực sự là 'MemberInit'. cám ơn bạn một lần nữa. +1 và chấp nhận –

3

Cuối cùng tôi tìm thấy câu trả lời của tôi:

public static Func<bool, dynamic> Creator; 

static void BuildLambda() { 
    var expectedType = typeof(MyObject); 
    var displayValueParam = Expression.Parameter(typeof(bool), "displayValue"); 
    var ctor = Expression.New(expectedType); 
    var local = Expression.Parameter(expectedType, "obj"); 
    var displayValueProperty = Expression.Property(local, "DisplayValue"); 

    var returnTarget = Expression.Label(expectedType); 
    var returnExpression = Expression.Return(returnTarget,local, expectedType); 
    var returnLabel = Expression.Label(returnTarget, Expression.Default(expectedType)); 

    var block = Expression.Block( 
     new[] { local }, 
     Expression.Assign(local, ctor), 
     Expression.Assign(displayValueProperty, displayValueParam), 
     /* I forgot to remove this line: 
     * Expression.Return(Expression.Label(expectedType), local, expectedType), 
     * and now it works. 
     * */ 
     returnExpression, 
     returnLabel 
     ); 
    Creator = 
     Expression.Lambda<Func<bool, dynamic>>(block, displayValueParam) 
      .Compile(); 
} 

UPDATE:

Trong khi nó hoạt động tốt, nhưng @svick cung cấp một cách tốt hơn và ngắn hơn trong câu trả lời của mình đó là actuallt Wath tôi đang tìm kiếm : MemberInit. Vui lòng xem câu trả lời của @ svick.

+0

Nếu tất cả những gì bạn muốn làm là biên dịch và thực thi mã, điều này sẽ hoạt động tốt. Nhưng nếu bạn muốn sử dụng biểu thức theo cách khác (ví dụ: trong LINQ to SQL), điều này có thể không hoạt động tốt. Điều cần làm là sử dụng 'MemberInit()', như trong câu trả lời của tôi. Bằng cách này bạn cũng sẽ nhận được mã ngắn hơn, dễ đọc hơn. – svick

+0

@svick cảm ơn bạn quá nhiều. Tôi muốn làm biên dịch và bộ nhớ cache func để feture sử dụng. –