Search code examples
c#visual-studiodebuggingreflection.emit

Emitted properties do not appear in the debugger


I use System.Reflection.Emit to create classes at runtime that implement various interfaces which contain methods and properties.

When generating a class, I generate one concrete method for each interface method of each interface that the class is supposed to implement.

Since properties are just syntactic sugar, (or are they?) I do not handle them in any way: for any property Foo the interface is bound to declare a pair of get_Foo() and set_Foo() methods, so my code generates the corresponding concrete methods, and the resulting class has the property without any extra handling.

Everything works, except for one annoying thing:

When an object which is an instance of a generated class is shown in the "Locals" or "Autos" windows of the Visual Studio debugger, if I expand the node of that object, I do not see any of the properties and their values. They are just not shown. They are not there. They appear not.

Now, here is the funny thing: If I add the name of that instance plus a dot plus the name of one of the generated properties in the "Watches" window of the Visual Studio debugger, then the debugger recognizes the property, and shows me its value; so the property is there; but it just won't show under "Locals" or "Autos".

What is causing this? How can I fix it?


Solution

  • As it turns out, properties are mostly, but not entirely syntactic sugar.

    A class that contains get_Foo() and set_Foo() appears to implement the Foo property as far as any code invoking it is concerned, but the class does not really implement the Foo property unless it explicitly defines that property.

    So, when the visual studio debugger tries to decide which properties to show for an object in the "Locals" or "Autos" window, it enumerates the properties of that object, and if no properties are defined, no properties will be shown.

    So, the solution to this problem is that during code generation, besides invoking TypeBuilder.DefineMethod() to define each method, we also have to keep track of which methods are getters and setters, and then for each property do a TypeBuilder.DefineProperty() and specify the getter and setter for it.

    Strictly speaking it is not necessary, but the resulting class will then be complete from the point of view of reflection, so it will behave properly in the debugger.