我如何反映dynamic对象的成员?

我需要从.NET 4中的dynamic关键字声明的对象中获取属性及其值的字典? 似乎使用reflection这是行不通的。

例:

dynamic s = new ExpandoObject(); s.Path = "/Home"; s.Name = "Home"; // How do I enumerate the Path and Name properties and get their values? IDictionary<string, object> propertyValues = ??? 

如果IDynamicMetaObjectProvider可以提供dynamic成员名称,则可以获取它们。 请参阅apache许可的PCL库Dynamitey (可在nuget中find)中的GetMemberNames实现,它适用于实现GetDynamicMemberNames ExpandoObjectDynamicObject ,以及在没有自定义testing的情况下提供具有GetDynamicMemberNames实现的元对象的任何其他IDynamicMetaObjectProvider is IDynamicMetaObjectProvider

获得成员名称之后,获得价值的方法还有一些工作要做,但是Impromptu做到了这一点,但仅仅指出一些有趣的部分并使之合理化就更困难了。 这里是文档 ,它等于或比reflection速度快,但是,不可能比查找expando的字典更快,但是它适用于任何对象,扩展,dynamic或原始 – 您的名字。

在ExpandoObject的情况下,ExpandoObject类实际上为其属性实现了IDictionary<string, object> ,所以解决scheme和cast一样简单:

 IDictionary<string, object> propertyValues = (IDictionary<string, object>)s; 

请注意,这不适用于一般的dynamic对象。 在这些情况下,您将需要通过IDynamicMetaObjectProvider将其下载到DLR。

有几种情况需要考虑。 首先,你需要检查你的对象的types。 你可以简单地调用GetType()。 如果types没有实现IDynamicMetaObjectProvider,则可以使用与其他任何对象相同的reflection。 就像是:

 var propertyInfo = test.GetType().GetProperties(); 

但是,对于IDynamicMetaObjectProvider实现,简单的reflection不起作用。 基本上,你需要更多地了解这个对象。 如果它是ExpandoObject(它是IDynamicMetaObjectProvider实现之一),则可以使用itowlson提供的答案。 ExpandoObject将其属性存储在字典中,您可以简单地将您的dynamic对象转换为字典。

如果它是DynamicObject(另一个IDynamicMetaObjectProvider实现),那么你需要使用这个DynamicObject公开的任何方法。 DynamicObject不需要实际“存储”任何地方的属性列表。 例如,它可能会这样做(我正在重复使用我的博客文章中的一个示例):

 public class SampleObject : DynamicObject { public override bool TryGetMember(GetMemberBinder binder, out object result) { result = binder.Name; return true; } } 

在这种情况下,只要你试图访问一个属性(使用任何给定的名字),对象只是以string的forms返回属性的名字。

 dynamic obj = new SampleObject(); Console.WriteLine(obj.SampleProperty); //Prints "SampleProperty". 

所以,你没有任何东西可以反思 – 这个对象没有任何属性,同时所有有效的属性名称都可以工作。

我认为对于IDynamicMetaObjectProvider实现,您需要过滤已知的实现,您可以获取一系列属性(如ExpandoObject),然后忽略(或抛出exception)。

需要Newtonsoft Json.Net

有点晚了,但我想出了这个。 它给你只是关键,然后你可以使用dynamic的:

  public List<string> GetPropertyKeysForDynamic(dynamic dynamicToGetPropertiesFor) { JObject attributesAsJObject = dynamicToGetPropertiesFor; Dictionary<string, object> values = attributesAsJObject.ToObject<Dictionary<string, object>>(); List<string> toReturn = new List<string>(); foreach (string key in values.Keys) { toReturn.Add(key); } return toReturn; } 

那么你只是这样的foreach:

  foreach(string propertyName in GetPropertyKeysForDynamic(dynamicToGetPropertiesFor)) { dynamic/object/string propertyValue = dynamicToGetPropertiesFor[propertyName]; // And dynamicToGetPropertiesFor[propertyName] = "Your Value"; // Or an object value } 

select以string或其他对象的forms获取该值,或者执行另一个dynamic操作并再次使用查找。