kevin-montrose / Sigil

A fail-fast validating helper for .NET CIL generation
Microsoft Public License
988 stars 92 forks source link

Cannot use ConstructorBuilder when generating new Type #28

Closed hcesar closed 9 years ago

hcesar commented 9 years ago

When creating dynamic types it is not possible to emit a method that uses a ConstructorBuilder.

Given that ctor is a ConstructorBuilder, the following code works fine:

var createProxy = typeBuilder.DefineMethod("CreateProxy", MethodAttributes.Static | MethodAttributes.Public, interfaceType, new[] { interfaceType });
il = createProxy.GetILGenerator();
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Newobj, ctor);
il.Emit(OpCodes.Ret);

But its Sigil version doesn't:

var createProxy = Sigil.Emit<Func<TInterfaceType,TInterfaceType>>.BuildStaticMethod(typeBuilder, "CreateProxy", MethodAttributes.Public | MethodAttributes.Static, true, false)
            .LoadArgument(0)
            .NewObject(ctor)
            .Return()
            .CreateMethod();

An exception is thrown: "_The invoked member is not supported before the type is created_".

This exception is thrown when DeclaringType or GetParameters() members of ConstructorBuilder get called. And both are called in NewObject method.

In ConstructorBuilder context, the ReflectedType property should be a good alternative to DeclaringType, but the parameter list is not available anywhere.

Maybe a NewObject(ConstructorBuilder, Type[]) overload should be enough (but not completely safe).