Overridding a Property With Reflection.Emit

Or how to use ILGenerator.
Apr 29 2009 by James Craig

This isn't a big discussion on Reflection.Emit or a how to when it comes to defining a property. To be honest, you can look that up rather easily. My issue was the fact that I could not for the life of me figure out how to override a virtual property within a base class. For example, let's assume I have this class:

 public class ExampleBaseClass
{
public ExampleBaseClass()
{
}

public virtual string Value { get; set; }

}

and all we want to do is dynamically create a class that takes that as a base class and overrides Value. You'd think that would be easy (and actually it is), but no one ever shows you how... Because normally you'd do something like this:

 FieldBuilder ValueField = TypeBuilder.DefineField("_Value", typeof(string), FieldAttributes.Private);

PropertyBuilder Property = TypeBuilder.DefineProperty("Value", PropertyAttributes.None, typeof(string), null);

MethodAttributes GetSetAttributes = MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig | MethodAttributes.Virtual;

MethodBuilder ValuePropertyGet = TypeBuilder.DefineMethod("get_Value", GetSetAttributes, typeof(string), Type.EmptyTypes);
ILGenerator Generator = ValuePropertyGet.GetILGenerator();
Generator.Emit(OpCodes.Ldarg_0);
Generator.Emit(OpCodes.Ldfld, ValueField);
Generator.Emit(OpCodes.Ret);


MethodBuilder ValuePropertySet = TypeBuilder.DefineMethod("set_Value", GetSetAttributes, null, new Type[] { typeof(string) });

Generator = ValuePropertySet.GetILGenerator();

Generator.Emit(OpCodes.Ldarg_0);
Generator.Emit(OpCodes.Ldarg_1);
Generator.Emit(OpCodes.Stfld, ValueField);
Generator.Emit(OpCodes.Ret);

Property.SetGetMethod(ValuePropertyGet);
Property.SetSetMethod(ValuePropertySet);

With TypeBuilder being the TypeBuilder for the class... This seems perfectly logical with the exception that when you try to call Value, the CLR complains that it's ambiguous... After bashing my head against a wall for a while I figured out that there were two Value properties that were defined for the object. One being the virtual, one being this new one that I created. The key to fixing this is to not define the property but only the get and set functions. As such our code above would look like this:

 FieldBuilder ValueField = TypeBuilder.DefineField("_Value", typeof(string), FieldAttributes.Private);

MethodAttributes GetSetAttributes = MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig | MethodAttributes.Virtual;

MethodBuilder ValuePropertyGet = TypeBuilder.DefineMethod("get_Value", GetSetAttributes, typeof(string), Type.EmptyTypes);
ILGenerator Generator = ValuePropertyGet.GetILGenerator();
Generator.Emit(OpCodes.Ldarg_0);
Generator.Emit(OpCodes.Ldfld, ValueField);
Generator.Emit(OpCodes.Ret);


MethodBuilder ValuePropertySet = TypeBuilder.DefineMethod("set_Value", GetSetAttributes, null, new Type[] { typeof(string) });

Generator = ValuePropertySet.GetILGenerator();

Generator.Emit(OpCodes.Ldarg_0);
Generator.Emit(OpCodes.Ldarg_1);
Generator.Emit(OpCodes.Stfld, ValueField);
Generator.Emit(OpCodes.Ret);

And sadly it took me searching through about 30 blog posts to find one that led me to this fix. Here's hoping this will help you before you reach the fourth page on Google. So try it out, leave feedback, and happy coding.