2013-04-04 60 views
54

Tôi biết có một số câu hỏi giải quyết vấn đề này, nhưng câu trả lời thường tuân theo các dòng giới thiệu từ điển hoặc tập hợp các tham số, không hoạt động trong tình huống của tôi.Tự động thêm thuộc tính C# tại thời gian chạy

Tôi đang sử dụng thư viện hoạt động thông qua sự phản chiếu để thực hiện rất nhiều điều thông minh với các đối tượng có thuộc tính. Điều này làm việc với các lớp được định nghĩa, cũng như các lớp động. Tôi cần thực hiện thêm một bước nữa và thực hiện điều gì đó dọc theo các dòng sau:

public static object GetDynamicObject(Dictionary<string,object> properties) { 
    var myObject = new object(); 
    foreach (var property in properties) { 
     //This next line obviously doesn't work... 
     myObject.AddProperty(property.Key,property.Value); 
    } 
    return myObject; 
} 

public void Main() { 
    var properties = new Dictionary<string,object>(); 
    properties.Add("Property1",aCustomClassInstance); 
    properties.Add("Property2","TestString2"); 

    var myObject = GetDynamicObject(properties); 

    //Then use them like this (or rather the plug in uses them through reflection) 
    var customClass = myObject.Property1; 
    var myString = myObject.Property2; 

} 

Thư viện hoạt động tốt với loại biến động, với thuộc tính được gán theo cách thủ công. Tuy nhiên tôi không biết bao nhiêu hoặc những gì tài sản sẽ được thêm trước.

Trả lời

75

Bạn đã xem ExpandoObject chưa?

xem: http://blogs.msdn.com/b/csharpfaq/archive/2009/10/01/dynamic-in-c-4-0-introducing-the-expandoobject.aspx

Từ MSDN:

Lớp ExpandoObject cho phép bạn thêm và xóa các thành viên của trường tại thời gian chạy và cũng để thiết lập và nhận được giá trị của các thành viên. Lớp này hỗ trợ ràng buộc động, cho phép bạn sử dụng cú pháp chuẩn như sampleObject.sampleMember thay vì cú pháp phức tạp hơn như sampleObject.GetAttribute ("sampleMember").

Cho phép bạn làm những điều lý thú như:

dynamic dynObject = new ExpandoObject(); 
dynObject.SomeDynamicProperty = "Hello!"; 
dynObject.SomeDynamicAction = (msg) => 
    { 
     Console.WriteLine(msg); 
    }; 

dynObject.SomeDynamicAction(dynObject.SomeDynamicProperty); 

Dựa trên mã thực tế của bạn, bạn có thể quan tâm nhiều hơn trong:

public static dynamic GetDynamicObject(Dictionary<string, object> properties) 
{ 
    return new MyDynObject(properties); 
} 

public sealed class MyDynObject : DynamicObject 
{ 
    private readonly Dictionary<string, object> _properties; 

    public MyDynObject(Dictionary<string, object> properties) 
    { 
     _properties = properties; 
    } 

    public override IEnumerable<string> GetDynamicMemberNames() 
    { 
     return _properties.Keys; 
    } 

    public override bool TryGetMember(GetMemberBinder binder, out object result) 
    { 
     if (_properties.ContainsKey(binder.Name)) 
     { 
      result = _properties[binder.Name]; 
      return true; 
     } 
     else 
     { 
      result = null; 
      return false; 
     } 
    } 

    public override bool TrySetMember(SetMemberBinder binder, object value) 
    { 
     if (_properties.ContainsKey(binder.Name)) 
     { 
      _properties[binder.Name] = value; 
      return true; 
     } 
     else 
     { 
      return false; 
     } 
    } 
} 

Bằng cách đó bạn chỉ cần:

var dyn = GetDynamicObject(new Dictionary<string, object>() 
    { 
     {"prop1", 12}, 
    }); 

Console.WriteLine(dyn.prop1); 
dyn.prop1 = 150; 

Bắt nguồn từ DynamicObject cho phép bạn có chiến lược riêng để xử lý các yêu cầu thành viên năng động này, hãy cẩn thận ở đó: trình biên dịch sẽ không có thể xác minh nhiều cuộc gọi năng động của bạn và bạn sẽ không nhận được intellisense, vì vậy chỉ cần giữ cho rằng trong tâm trí.

17

Cảm ơn @Clint cho câu trả lời tuyệt vời:

Chỉ muốn làm nổi bật cách dễ dàng là để giải quyết việc này bằng cách sử dụng Object expando:

public static dynamic GetDynamicObject(Dictionary<string,object> properties) { 
    var dynamicObject = new ExpandoObject() as IDictionary<string, Object>; 
    foreach (var property in properties) { 
     dynamicObject.Add(property.Key,property.Value); 
    } 
    return dynamicObject; 
} 
+6

+1. Lưu ý: Tại sao bạn không trả lại một từ điển thay vì năng động? (ít nhất, IDictionary)? Ý tôi là, trở về động là một chút "gây hiểu lầm", vì bạn sẽ luôn trả về một từ điển. – Veverke

Các vấn đề liên quan