2011-12-25 30 views
54

Giả sử rằng tôi có một biến động (phản ánh?):Nhận giá trị tài sản từ C# đối tượng năng động của chuỗi

dynamic d = *something* 

Bây giờ, tạo tính để d mà tôi có mặt khác từ một chuỗi mảng:

string[] strarray = { 'property1','property2',..... } 

Tôi không biết trước tên thuộc tính.

Làm thế nào trong mã, sau khi d được tạo và strarray được lấy từ DB, tôi có thể nhận được các giá trị không?

Tôi muốn nhận d.property1 , d.property2.

Tôi thấy rằng đối tượng có từ điển nội bộ _dictionary chứa các khóa và giá trị, làm cách nào để truy xuất chúng?

+1

Là 'cái gì' một' IDynamicMetaObjectProvider'? – SLaks

+0

Kiểm tra kiểu thời gian chạy của 'cái gì đó' trong trình gỡ lỗi và xem các thành viên công khai của nó. – SLaks

+1

Bạn có thể kiểm tra những gì 'd.GetType()' cung cấp cho bạn trong thời gian chạy không? –

Trả lời

77

Tôi không biết nếu có một cách thanh lịch hơn với các đối tượng tự động tạo ra, nhưng sử dụng đơn giản phản ánh cũ nên làm việc:

var nameOfProperty = "property1"; 
var propertyInfo = myObject.GetType().GetProperty(nameOfProperty); 
var value = propertyInfo.GetValue(myObject, null); 

GetProperty sẽ trở lại null nếu loại myObject không chứa một tài sản công cộng với tên này.


EDIT: Nếu đối tượng không phải là một đối tượng "thường xuyên", nhưng một cái gì đó thực hiện IDynamicMetaObjectProvider, phương pháp này sẽ không hoạt động. Hãy có một cái nhìn tại câu hỏi này thay vì:

+0

Đáng tiếc là nó không hoạt động: object obj = serializer.Deserialize(json, typeof(object)); var propertyInfo = obj.GetType().GetProperty("H3"); var value = propertyInfo.GetValue(obj, null); PropertyInfo là null, dòng thứ 3 ném một ngoại lệ . –

+0

@ sergata.NETLTD: Nhưng 'var value = obj.H3' sẽ hoạt động? Bạn có thể xác minh điều đó không? – Heinzi

+0

có nó sẽ hoạt động. Công trình này: dynamic obj = serializer.Deserialize (json, typeof (đối tượng)); var value = obj.H3; giá trị chứa giá trị phù hợp. Vấn đề là: Tôi không biết rằng H3 là tên thuộc tính trước. Tên thuộc tính đến từ DB. Cảm ơn sự giúp đỡ của bạn. –

17

này sẽ cung cấp cho bạn tất cả tên thuộc tính và các giá trị được định nghĩa trong biến động của bạn.

dynamic d = { // your code }; 
object o = d; 
string[] propertyNames = o.GetType().GetProperties().Select(p => p.Name).ToArray(); 
foreach (var prop in propertyNames) 
{ 
    object propValue = o.GetType().GetProperty(prop).GetValue(o, null); 
} 
+1

Điều này làm việc tốt đẹp cho tôi, những gì tôi đã không thể đạt được cho loại năng động, nhờ –

+0

Điều đó chỉ hoạt động nếu d là một loại tĩnh. Nếu D là một IDynamicMetaObjectProvider, (chẳng hạn như một JObject) nó sẽ cung cấp cho bạn các thuộc tính sai. Ví dụ: nếu d = obj, thì nó sẽ không trả về 'x', nó sẽ trả về các thuộc tính thô trên JObject. JObject obj = JObject.TừObject (mới { x = 123 }); –

5
string json = w.JSON; 

var serializer = new JavaScriptSerializer(); 
serializer.RegisterConverters(new[] { new DynamicJsonConverter() }); 

DynamicJsonConverter.DynamicJsonObject obj = 
     (DynamicJsonConverter.DynamicJsonObject)serializer.Deserialize(json, typeof(object)); 

Bây giờ obj._Dictionary chứa một từ điển. Hoàn hảo!

Mã này phải được sử dụng cùng với Deserialize JSON into C# dynamic object? + làm biến _dictionary từ "readonly tin" cho công chúng trong các mã có

18

Hy vọng điều này sẽ giúp bạn:

public static object GetProperty(object o, string member) 
{ 
    if(o == null) throw new ArgumentNullException("o"); 
    if(member == null) throw new ArgumentNullException("member"); 
    Type scope = o.GetType(); 
    IDynamicMetaObjectProvider provider = o as IDynamicMetaObjectProvider; 
    if(provider != null) 
    { 
     ParameterExpression param = Expression.Parameter(typeof(object)); 
     DynamicMetaObject mobj = provider.GetMetaObject(param); 
     GetMemberBinder binder = (GetMemberBinder)Microsoft.CSharp.RuntimeBinder.Binder.GetMember(0, member, scope, new CSharpArgumentInfo[]{CSharpArgumentInfo.Create(0, null)}); 
     DynamicMetaObject ret = mobj.BindGetMember(binder); 
     BlockExpression final = Expression.Block(
      Expression.Label(CallSiteBinder.UpdateLabel), 
      ret.Expression 
     ); 
     LambdaExpression lambda = Expression.Lambda(final, param); 
     Delegate del = lambda.Compile(); 
     return del.DynamicInvoke(o); 
    }else{ 
     return o.GetType().GetProperty(member, BindingFlags.Public | BindingFlags.Instance).GetValue(o, null); 
    } 
} 
+0

bạn có thể giải thích mã này không? – Ewerton

+0

@Ewerton Đã khá lâu rồi, nhưng tôi thấy nó sử dụng * System.Linq.Expressions * để liên kết trình khởi động động với một trang gọi, và để phần biên dịch thành * LambdaExpression *. Tôi không biết nếu tôi lấy cái này từ một đoạn mã đã bị giải mã hay ở nơi khác. – IllidanS4

2

Bạn có xem ExpandoObject lớp học?

Trực tiếp từ MSDN description: "Thể hiện đối tượng có thành viên có thể được thêm và xóa tự động vào thời gian chạy."

Với nó, bạn có thể viết mã như thế này:

dynamic employee = new ExpandoObject(); 
employee.Name = "John Smith"; 
((IDictionary<String, Object>)employee).Remove("Name"); 
+0

Tên thuộc tính không được biết nên điều này sẽ không hoạt động. – user3285954

+0

Mã hoạt động (tôi đã kiểm tra trong phòng thu trực quan) vì cá thể của nhân viên là ExpandoObject nên nó có thể thêm và loại bỏ thuộc tính trong thời gian chạy (cách giải thích trong tài liệu chính thức của MS). Mã này hoàn thành câu hỏi. – ADIMO

0

Tư tưởng này có thể giúp một người nào đó trong tương lai.

Nếu bạn biết tên bất động sản đã có, bạn có thể làm một cái gì đó như sau:

[HttpPost] 
[Route("myRoute")] 
public object SomeApiControllerMethod([FromBody] dynamic args){ 
    var stringValue = args.MyPropertyName.ToString(); 
    //do something with the string value. If this is an int, we can int.Parse it, or if it's a string, we can just use it directly. 
    //some more code here.... 
    return stringValue; 
} 
+0

Tên thuộc tính không được biết. – user3285954

0

NẾU d được tạo ra bởi Newtonsoft bạn có thể sử dụng để đọc tên và giá trị tài sản:

foreach (JProperty property in d) 
    { 
     DoSomething(property.Name, property.Value); 
    } 
Các vấn đề liên quan