I'm writing a library that requires a later type build. Library uses platform .Net core 2.0
There is issue with some type that I am generating using Reflection.Emit
public class GeneratedA : A, IA
{
public void DoInterface(string arg0, bool arg1, int arg2, object arg3, List<float> arg4, params object[] otherArgs)
{
DoClass(arg0, arg1, arg2, arg3, arg4, otherArgs);
}
}
for these types:
public interface IA
{
void DoInterface(string arg0, bool arg1, int arg2, object arg3, List<float> arg4, params object[] otherArgs);
}
public class A
{
public void DoClass(params object[] args)
{
}
}
Sample IL code:
class Program
{
public static class Generator
{
public static T Create<T>()
where T : class
{
AssemblyName aName = new AssemblyName("DynamicAssembly");
AssemblyBuilder ab = AssemblyBuilder.DefineDynamicAssembly(new AssemblyName(Guid.NewGuid().ToString()), AssemblyBuilderAccess.Run);
ModuleBuilder mb = ab.DefineDynamicModule(aName.Name);
var interfaceType = typeof(T);
var interfaceMethod = interfaceType.GetMethod("DoInterface");
var interfaceMethodArgs = interfaceMethod.GetParameters().Select(x => x.ParameterType).ToArray();
var classType = typeof(A);
var classMethod = classType.GetMethod("DoClass");
var returnType = typeof(void);
var baseType = typeof(object);
var baseConstructor = baseType.GetConstructor(BindingFlags.Public | BindingFlags.FlattenHierarchy | BindingFlags.Instance, null, Type.EmptyTypes, null);
TypeBuilder tb = mb.DefineType("GeneratedA", TypeAttributes.Public, baseType);
ConstructorBuilder ctor = tb.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, Type.EmptyTypes);
ILGenerator ctorIL = ctor.GetILGenerator();
ctorIL.Emit(OpCodes.Ldarg_0);
ctorIL.Emit(OpCodes.Call, baseConstructor);
ctorIL.Emit(OpCodes.Nop);
ctorIL.Emit(OpCodes.Nop);
ctorIL.Emit(OpCodes.Ret);
tb.AddInterfaceImplementation(interfaceType);
MethodBuilder mbIM = tb.DefineMethod(interfaceType.Name + "." + interfaceMethod.Name,
MethodAttributes.Private | MethodAttributes.HideBySig |
MethodAttributes.NewSlot | MethodAttributes.Virtual |
MethodAttributes.Final,
returnType,
interfaceMethodArgs);
ILGenerator genIM = mbIM.GetILGenerator();
// ToDo
genIM.Emit(OpCodes.Call, classMethod);
genIM.Emit(OpCodes.Ret);
tb.DefineMethodOverride(mbIM, interfaceMethod);
Type t = tb.CreateType();
return Activator.CreateInstance(t) as T;
}
}
static void Main(string[] args)
{
IA a;
a = new GeneratedA();
a.DoInterface("0", true, 2, 3, new List<float>() { 4 }, "5", 6);
a = Generator.Create<IA>();
a.DoInterface("0", true, 2, 3, new List<float>() { 4 }, "5", 6);
}
}
Whenever I try to fill out a comment "ToDo", I get an error "Common Language Runtime detected an invalid program".
I ask to help with a call of method DoClass.
Thanks