我正在使用第三方 api 开发应用程序。他们提供了一个示例应用程序来演示 API。在示例应用程序中,有一个属性网格,它显示所选对象的所有属性。在示例应用程序中,我可以看到一个属性,可以说“X”,但以编程方式,我无法通过在对象后放置点(。)来访问它多变的。我还使用反射来获取属性但没有成功。有人建议它可能是一个动态属性。我发现无法检查给定对象或该对象的任何成员是否是动态的?
请建议一种访问该属性的方法。
PropertGrid 控件能够显示上述属性并允许更改值,但此属性不能以编程方式访问。
我正在使用第三方 api 开发应用程序。他们提供了一个示例应用程序来演示 API。在示例应用程序中,有一个属性网格,它显示所选对象的所有属性。在示例应用程序中,我可以看到一个属性,可以说“X”,但以编程方式,我无法通过在对象后放置点(。)来访问它多变的。我还使用反射来获取属性但没有成功。有人建议它可能是一个动态属性。我发现无法检查给定对象或该对象的任何成员是否是动态的?
请建议一种访问该属性的方法。
PropertGrid 控件能够显示上述属性并允许更改值,但此属性不能以编程方式访问。
解决这个问题的方法是直接查看生成的你知道具有动态属性的类型的 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();
}
}