如何知道给定对象是否包含任何动态属性?

时间:2013-08-27 12:12:44

标签: c# dynamic reflection

我正在使用第三方API开发应用程序。他们提供了一个示例应用程序来演示API。在示例应用程序中有一个propertygrid,它显示所选对象的所有属性。在示例应用程序中,我可以看到一个属性让我们说“X”但是以编程方式我无法通过在对象后面放置点(。)来访问它变量。我也用反射来获得属性,但没有成功。有人建议它可能是一个动态的属性。我发现无法检查给定对象或该对象的任何成员是否是动态的?

请建议一种访问该属性的方法。

PropertGrid控件能够显示上述属性并允许更改值,但无法以编程方式访问此属性。

1 个答案:

答案 0 :(得分:1)

解决此问题的方法是直接查看已知具有动态属性的类型的生成的IL。在那里,您会发现这样的属性只是表示为对象类型,但它的所有组件都使用 DynamicAttribute 属性进行修饰。

此属性由编译器本身实现,并且开发人员无法使用。因此,您唯一需要做的就是检查属性是否使用 DynamicAttribute 属性进行修饰。

要看到这一点,请查看以下用于 IamDynamic 属性的Get访问器方法的IL代码,稍后我们将使用该方法进行测试。

.method public hidebysig specialname instance object 
      get_IamDynamic() cil managed

.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
.param [0]
.custom instance void [System.Core]System.Runtime.CompilerServices.DynamicAttribute::.ctor() = ( 01 00 00 00 ) 

.maxstack  1
.locals init (object V_0)
IL_0000:  ldarg.0
IL_0001:  ldfld      object Testing.TestClass::'<IamDynamic>k__BackingField'
IL_0006:  stloc.0
IL_0007:  br.s       IL_0009
IL_0009:  ldloc.0
IL_000a:  ret

您可以轻松注意到使用 DynamicAttribute 的行,表明这是一个动态声明。我们现在可以使用以下扩展方法发现所有动态属性。

public static class DynamicExtension
{
    public static void GetDynamicProperties(this Type source)
    {
        source.GetProperties()
              .Where(x => x.GetCustomAttributes().OfType<DynamicAttribute>().Any())
              .ToList()
              .ForEach(x => Console.WriteLine(x.Name));
    }
}

上面提到的这个类将测试动态属性。

class TestClass
{
    public dynamic IamDynamic { get; set; }        
    public object IamNotDynamic { get; set; }
    public dynamic IamAlsoDynamic { get; set; }
}

执行以下代码行后,您将看到只显示两个动态属性。

class Program
{
    static void Main()
    {
        typeof(TestClass).GetDynamicProperties();

        Console.Read();
    }
}