有几种情况需要考虑。首先,您需要检查对象的类型。您可以为此简单地调用GetType()。如果该类型未实现IDynamicMetaObjectProvider,则可以与其他任何对象一样使用反射。就像是:
var propertyInfo = test.GetType().GetProperties();
但是,对于IDynamicMetaObjectProvider实现,简单的反射不起作用。基本上,您需要了解有关此对象的更多信息。如果它是ExpandoObject(这是IDynamicMetaObjectProvider实现之一),则可以使用itowlson提供的答案。ExpandoObject将其属性存储在字典中,您只需将动态对象转换为字典即可。
如果是DynamicObject(另一个IDynamicMetaObjectProvider实现),则需要使用此DynamicObject公开的任何方法。不需要DynamicObject实际在任何地方“存储”其属性列表。例如,它可能会执行以下操作(我正在重用博客文章中的示例):
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之类的属性列表,而其余部分则忽略(或抛出异常)。