Question

I have the following class: (FYI: I can't edit the base class)

public abstract class BaseClass
{
    protected TOutput Convert<TInput, TOutput>(TInput input)
    {
        return (TOutput)System.Convert.ChangeType(input, typeof(TOutput));
    }
}

And what I'm trying to build, is a dynamic type like this:

public class DynamicClass : BaseClass
{
    public string Convert(int value)
    {
        return base.Convert<int, string>(value);
    }
}

The method that I use to build the dynamic type, looks like this:

private MethodBuilder BuildConvertMethod(TypeBuilder typeBuilder)
{
    var baseConvertMethod = typeof(BaseClass).GetMethod("Convert", BindingFlags.NonPublic | BindingFlags.CreateInstance | BindingFlags.Instance);
    var baseConvertMethodInstance = baseConvertMethod.MakeGenericMethod(typeof(int), typeof(string));

    var convertMethodBuilder = typeBuilder.DefineMethod("Convert", MethodAttributes.Public, typeof(string), new[] { typeof(int) });

    var convertMethodILGenerator = convertMethodBuilder.GetILGenerator();
    convertMethodILGenerator.Emit(OpCodes.Nop);
    convertMethodILGenerator.Emit(OpCodes.Ldarg_0);
    convertMethodILGenerator.Emit(OpCodes.Ldarg_1);
    convertMethodILGenerator.Emit(OpCodes.Call, baseConvertMethodInstance);
    convertMethodILGenerator.Emit(OpCodes.Ldloc_0);
    convertMethodILGenerator.Emit(OpCodes.Ret);

    return convertMethodBuilder;
}

The creation of the type succeeds. But when I create an instance of DynamicClass, and then calls the Convert method I get the following exception:

System.Reflection.TargetInvocationException : Exception has been thrown by the target of an invocation. ----> System.InvalidProgramException : Common Language Runtime detected an invalid program.

Can someone please help me with this problem?

Was it helpful?

Solution

Call instructions push the return value on the stack so you can call Ret straight after.

var convertMethodILGenerator = convertMethodBuilder.GetILGenerator();
convertMethodILGenerator.Emit(OpCodes.Ldarg_0);
convertMethodILGenerator.Emit(OpCodes.Ldarg_1);
convertMethodILGenerator.Emit(OpCodes.Call, baseConvertMethodInstance);
convertMethodILGenerator.Emit(OpCodes.Ret);
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top