I have the following class A.
public class A
{
public string Name { get; set; }
}
I need to emit a dynamic proxy using Reflection.Emit to override Equals.
// This class must be generated by Reflection.Emit.
public class AProxy : A
{
private bool equalsHasBeenCalled;
public override bool Equals(object obj)
{
if (this.equalsHasBeenCalled)
{
return base.Equals(obj);
}
this.equalsHasBeenCalled = true;
return CaseInsensitiveComparer.Equals(this, obj); // Demo.
}
}
However, the actual generated code (viewed with Reflector) is:
public class AProxy : A
{
private bool equalsHasBeenCalled;
public override bool Equals(object obj)
{
if (base.equalsHasBeenCalled)
{
return base.Equals(obj);
}
base.equalsHasBeenCalled = true;
return CaseInsensitiveComparer.Equals(this, obj);
}
}
..which of course throws a System.FieldAccessException (since no such member exists). The correct is to call this.equalsHasBeenCalled (not base.equalsHasBeenCalled).
I am using the Reflection.Emit add-in for Reflector to generate the code (field1 is the FieldInfo for the “equalsHasBeenCalled” field):
// Writing body
gen.Emit(OpCodes.Nop);
// I suspect it has to be around here.
gen.Emit(OpCodes.Ldarg_0);
gen.Emit(OpCodes.Ldfld, field1);
gen.Emit(OpCodes.Ldc_I4_0);
gen.Emit(OpCodes.Ceq);
gen.Emit(OpCodes.Stloc_1);
gen.Emit(OpCodes.Ldloc_1);
gen.Emit(OpCodes.Brtrue_S, label25);
gen.Emit(OpCodes.Nop);
gen.Emit(OpCodes.Ldarg_0);
gen.Emit(OpCodes.Ldarg_1);
gen.Emit(OpCodes.Call, method2);
gen.Emit(OpCodes.Stloc_0);
gen.Emit(OpCodes.Br_S, label42);
gen.MarkLabel(label25);
// ..and probably here also?
gen.Emit(OpCodes.Ldarg_0);
gen.Emit(OpCodes.Ldc_I4_1);
gen.Emit(OpCodes.Stfld, field1);
gen.Emit(OpCodes.Ldarg_0);
gen.Emit(OpCodes.Ldarg_1);
gen.Emit(OpCodes.Call, method3);
gen.Emit(OpCodes.Stloc_0);
gen.Emit(OpCodes.Br_S, label42);
gen.MarkLabel(label42);
gen.Emit(OpCodes.Ldloc_0);
gen.Emit(OpCodes.Ret);
Why dont you write what you need in C#, decompile to IL and see how it’s set up? Also, if you need to do any more of things like this in your project, I suggest you look into Castle DynamicProxy.