我需要从.NET 4中使用dynamic关键字声明的对象中获取属性及其值的字典吗?似乎使用反射这是行不通的。
示例:
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 = ???
答案 0 :(得分:97)
对于ExpandoObject,ExpandoObject类实际上为其属性实现了IDictionary<string, object>
,因此解决方案与转换一样简单:
IDictionary<string, object> propertyValues = (IDictionary<string, object>)s;
请注意,这不适用于一般动态对象。在这些情况下,您需要通过IDynamicMetaObjectProvider下拉到DLR。
答案 1 :(得分:57)
有几种情况需要考虑。 首先,您需要检查对象的类型。您可以直接调用GetType()。 如果类型未实现IDynamicMetaObjectProvider,则可以使用与任何其他对象相同的反射。类似的东西:
var propertyInfo = test.GetType().GetProperties();
但是,对于IDynamicMetaObjectProvider实现,简单反射不起作用。基本上,您需要了解有关此对象的更多信息。如果它是ExpandoObject(它是IDynamicMetaObjectProvider实现之一),您可以使用itowlson提供的答案。 ExpandoObject将其属性存储在字典中,您只需将动态对象转换为字典即可。
如果是DynamicObject(另一个IDynamicMetaObjectProvider实现),那么您需要使用此DynamicObject公开的任何方法。 DynamicObject不需要在任何地方实际“存储”其属性列表。例如,它可能会做这样的事情(我正在重用my blog post中的一个例子):
public class SampleObject : DynamicObject
{
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
result = binder.Name;
return true;
}
}
在这种情况下,每当您尝试访问属性(具有任何给定名称)时,该对象只是将该属性的名称作为字符串返回。
dynamic obj = new SampleObject();
Console.WriteLine(obj.SampleProperty);
//Prints "SampleProperty".
所以,你没有任何东西需要反思 - 这个对象没有任何属性,同时所有有效的属性名都可以。
我想对于IDynamicMetaObjectProvider实现,您需要过滤已知的实现,您可以在其中获取属性列表,例如ExpandoObject,并忽略(或抛出异常)。
答案 2 :(得分:29)
如果IDynamicMetaObjectProvider可以提供动态成员名称,您可以获取它们。请参阅apache许可的PCL库中的GetMemberNames实施Dynamitey(可在nuget中找到),适用于实现ExpandoObject
的{{1}}和DynamicObject
以及提供GetDynamicMemberNames
实施的元对象的任何其他IDynamicMetaObjectProvider
,而无需GetDynamicMemberNames
之外的自定义测试。
获得成员名称之后,以正确的方式获得价值的工作要多一些,但Impromptu会做到这一点,但是更难指出有趣的部分并让它有意义。这是documentation并且它比反射更快或更快,但是,它不可能比expando的字典查找更快,但它适用于任何对象,expando,动态或原始 - 你可以命名它。
答案 3 :(得分:16)
需要Newtonsoft Json.Net
有点晚了,但我想出了这个。它只为您提供了键,然后您可以在动态上使用它们:
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(string propertyName in GetPropertyKeysForDynamic(dynamicToGetPropertiesFor))
{
dynamic/object/string propertyValue = dynamicToGetPropertiesFor[propertyName];
// And
dynamicToGetPropertiesFor[propertyName] = "Your Value"; // Or an object value
}
选择将值作为字符串或其他对象获取,或者执行另一个动态并再次使用查找。