像C#中的属性字典一样处理对象

我希望能够使用属性的名称作为键来访问像字典这样的对象中的属性值。 我不关心值是否作为对象返回,因此Dictionary很好。 这是预期用途:

 object person = new { Name: "Bob", Age: 45 }; IDictionary lookup = new PropertyDictionary(person); string name = (string)person["Name"]; person["Age"] = (int)person["Age"] + 1; // potentially editable 

我本来要为此实现我自己的类,但后来我开始注意像DynamicObject这样的类实现了IDictionary接口,这让我觉得这已经在某个地方为我做了。

我想要的是类似于ASP.NET MVC使用的function,允许使用匿名类型来设置HTML标记属性。 我有很多使用字典作为数据源的类,但大多数时候我也应该能够传入对象。

因为这是一个通用库 ,我想我会创建一个可重用的类,只使用IDictionary接口装饰一个对象。 它将使我免于造成过载的爆炸。

我不相信.Net框架中已经存在这样的内置.Net类型。 看起来你真的想要创建一个行为与Javascript对象很相似的对象。 如果是这样,那么从DynamicObject派生可能是正确的选择。 它允许您创建一个对象,当使用dynamic包装时,您可以直接绑定obj.Name或通过索引器obj["Name"]绑定。

 public class PropertyBag : DynamicObject { private object _source; public PropertyBag(object source) { _source = source; } public object GetProperty(string name) { var type = _source.GetType(); var property = type.GetProperty(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); return property.GetValue(_source, null); } public override bool TryGetMember(GetMemberBinder binder, out object result) { result = GetProperty(binder.Name); return true; } public override bool TryGetIndex(GetIndexBinder binder, object[] indexes, out object result) { result = GetProperty((string)indexes[0]); return true; } } 

您可以使用它来包装任何类型,并使用索引器和名称语法来获取属性

 var student = new Student() { FirstName = "John", LastName = "Doe" }; dynamic bag = new PropertyBag(student); Console.WriteLine(bag["FirstName"]); // Prints: John Console.WriteLine(bag.FirstName); // Prints: John 

我有这个扩展方法,可能是最简单的方法:

 public static Dictionary ToPropertyDictionary(this object obj) { var dictionary = new Dictionary(); foreach (var propertyInfo in obj.GetType().GetProperties()) if (propertyInfo.CanRead && propertyInfo.GetIndexParameters().Length == 0) dictionary[propertyInfo.Name] = propertyInfo.GetValue(obj, null); return dictionary; } 

现在你可以这样做:

 object person = new { Name = "Bob", Age = 45 }; var lookup = person.ToPropertyDictionary(); string name = (string)lookup["Name"]; lookup["Age"] = (int)lookup["Age"] + 1; // indeed editable 

注意:

  1. 这个字典区分大小写(你可以通过正确的StringComparer轻松扩展它)。

  2. 它忽略了索引器(也是属性),但是你可以自己动手。

  3. 该方法不是通用的,因为它不会帮助装箱,因为它在内部调用obj.GetType ,所以它在那时无论如何都是盒子。

  4. 您只获得“可读”属性(否则您不会获得其中的值)。 既然你希望它也是“可写的”那么你也应该使用CanWrite标志。

动态关键字可能是您的唯一选择。 它使用动态语言运行时。 在运行时,它会尝试匹配程序中最接近的可用类型。 如果它不能,那么它将动态类型转换为dictionay对象,其中key是property的名称,value是property的值。

请关注MSDN的这些链接:

在C#中使用动态关键字
动态(C#参考)
DLR概述
使用动态样本walkthough页面