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?

Était-ce utile?

La 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);
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top