Home All Groups Group Topic Archive Search About

Reflection.Emit accessing a field in the base class of a dynamically constructed class

Author
11 Feb 2006 11:28 PM
Douglas Harber
I'm using Reflection.Emit to define a dynamic type. The class inherits from
a generic base class. In C# this would all look like this:

    public class Base<T>
    {
        int someField = 0;
    }

    public class Derived : Base<Derived>
    {
        void CheckField()
        {
            Console.WriteLine(someField);
        }
    }

This is obviously very simplified code and the reasons for Base<Derived>
aren't shown in it. However, this snippet of code basicaly compiles and does
what you would expect, i.e., prints out the value of someField.

The problem is I'm trying to generate Derived dynamically using
Reflection.Emit. So I have something like this:

    TypeBuilder derivedBuilder = mod.DefineType("Derived",
TypeAttributes.Public);
    Type baseDerived = typeof(Base<>).MakeGenericType(derivedBuilder);

    derivedBuilder.SetParent(baseInt);

    MethodBuilder check = derivedBuilder.DefineMethod(
        "CheckField",
        MethodAttributes.Public,
        typeof(void),
        new Type[] { typeof(void) });

In the next step, I'm going to generate the IL code for the CheckField
method. To emit that instruction, I'm going to need the FieldInfo for
someField. Normally I would do this:

    FieldInfo someFieldInfo = baseDerived.GetField("someField");

    ILGenerator gen = check.GetILGenerator();
    gen.Emit(OpCodes.Ldfld, someFieldInfo);

However, GetField() throws a NotSupportedException. In searching for a
possible explanation I stumbled across something that suggested GetField
won't work on incomplete types. I'm guessing that because Derived is still
being defined, Base<Derived> isn't complete and, hence, GetField is not
available. Evidence supporting something along those lines is provided by
the fact that if I change the base class of Derived to Base<int>, GetField
can return the FieldInfo for someField.

It's obviously possible to generate code to do this since the C# code works
just fine. I suppose there are probably things that compilers can do that
aren't actually supported by Reflection.Emit but I'm hoping this isn't one
of those cases.

Does anybody have any idea how to access the fields in the base class in
this instance?

Thanks for any help,
Doug Harber

AddThis Social Bookmark Button