我使用
System.Reflection.Emit
在运行时创建类来实现包含方法和属性的各种接口。
生成类时,我为该类应该实现的每个接口的每个接口方法生成一个具体方法。
由于属性只是语法糖,(或者它们是吗?)我不会以任何方式处理它们:对于任何属性
Foo
,接口都必须声明一对get_Foo()
和set_Foo()
方法,所以我的代码生成了相应的具体方法,并且生成的类具有该属性,无需任何额外的处理。
一切正常,除了一件烦人的事情:
当作为生成类实例的对象显示在 Visual Studio 调试器的“Locals”或“Autos”窗口中时,如果我展开该对象的节点,则看不到任何属性及其值。它们只是没有显示出来。他们不在那儿。他们没有表现出。
现在,有趣的是:如果我在 Visual Studio 调试器的“Watches”窗口中添加该实例的名称加上一个点加上生成的属性之一的名称,那么调试器会识别该属性,并显示我它的价值;所以财产就在那里;但它只是不会显示在“本地”或“汽车”下。
这是什么原因造成的?我该如何解决它?
事实证明,属性是大部分,但不完全是语法糖。
包含
get_Foo()
和 set_Foo()
的类似乎实现了 Foo
属性,就调用它的任何代码而言,但该类并没有真正实现 Foo
属性,除非它明确定义了该属性。
因此,当 Visual Studio 调试器尝试决定在“Locals”或“Autos”窗口中显示对象的哪些属性时,它会枚举该对象的属性,如果没有定义属性,则不会显示任何属性。
所以,这个问题的解决方案是,在代码生成过程中,除了调用
TypeBuilder.DefineMethod()
来定义每个方法之外,我们还必须跟踪我们生成的哪些方法是属性的 getter 和 setter,然后为每个属性执行一个TypeBuilder.DefineProperty()
并指定 getter 和 setter。
严格来说,这是没有必要的,但是从反射的角度来看,生成的类将是完整的,因此它将在调试器中正常运行。