使用 Reflection.Emit / Sigil 的构造函数链接
Constructor chaining with Reflection.Emit / Sigil
我正在尝试使用 Sigil 创建一个如下所示的 class,它是 Reflection.Emit.
的包装器
public class Test
{
public Test(string arg1)
{
}
public Test() : this("arg1")
{
}
}
使用以下代码我不断收到异常:"The invoked member is not supported before the type is created."
using System;
using System.Reflection;
using System.Reflection.Emit;
using Sigil.NonGeneric;
public class Program
{
public static void Main()
{
var asmName = new AssemblyName("MyAssembly");
var asm = AppDomain.CurrentDomain.DefineDynamicAssembly(asmName, AssemblyBuilderAccess.Save);
var mod = asm.DefineDynamicModule(asmName.Name, asmName.Name + ".dll");
var test = mod.DefineType("Test", TypeAttributes.Public);
// special constructor
var ctorBuilder1 = Emit.BuildConstructor(new Type[] { typeof(string) }, test, MethodAttributes.Public);
ctorBuilder1.Return();
var ctor1 = ctorBuilder1.CreateConstructor();
// default constructor calling the special one
var ctorBuilder2 = Emit.BuildConstructor(new Type[] { }, test, MethodAttributes.Public);
ctorBuilder2.LoadArgument(0);
ctorBuilder2.LoadConstant("arg1");
ctorBuilder2.Call(ctor1); // Exception thrown here
ctorBuilder2.Return();
var ctor2 = ctorBuilder2.CreateConstructor();
test.CreateType();
asm.Save(asmName.Name + ".dll");
}
}
我阅读了有关使用“DynamicMethod”的信息,但是当我用以下内容替换 BuildConstructor
调用时出现错误 "Delegate of type Sigil.Impl.NonGenericPlaceholderDelegate takes no parameters":
var piCtor = Emit.NewDynamicMethod(pi, new Type[] {}, ".ctor", mod);
感谢您的帮助。
目前看来,至少 Sigil.NonGeneric
没有正确处理这个问题。但是,看起来您也可以将 Sigil 与非 Sigil 代码混合搭配。
所以你可以改变只是你的ctorBuilder2
代码以使用内置Reflection.Emit代码:
var ctorBuilder2 = test.DefineConstructor(MethodAttributes.Public,
CallingConventions.Standard, new Type[0]);
var generator = ctorBuilder2.GetILGenerator();
generator.Emit(OpCodes.Ldarg_0);
generator.Emit(OpCodes.Ldstr, "arg1");
generator.Emit(OpCodes.Call, ctor1);
generator.Emit(OpCodes.Ret);
这似乎是根据需要构建程序集。
我正在尝试使用 Sigil 创建一个如下所示的 class,它是 Reflection.Emit.
的包装器public class Test
{
public Test(string arg1)
{
}
public Test() : this("arg1")
{
}
}
使用以下代码我不断收到异常:"The invoked member is not supported before the type is created."
using System;
using System.Reflection;
using System.Reflection.Emit;
using Sigil.NonGeneric;
public class Program
{
public static void Main()
{
var asmName = new AssemblyName("MyAssembly");
var asm = AppDomain.CurrentDomain.DefineDynamicAssembly(asmName, AssemblyBuilderAccess.Save);
var mod = asm.DefineDynamicModule(asmName.Name, asmName.Name + ".dll");
var test = mod.DefineType("Test", TypeAttributes.Public);
// special constructor
var ctorBuilder1 = Emit.BuildConstructor(new Type[] { typeof(string) }, test, MethodAttributes.Public);
ctorBuilder1.Return();
var ctor1 = ctorBuilder1.CreateConstructor();
// default constructor calling the special one
var ctorBuilder2 = Emit.BuildConstructor(new Type[] { }, test, MethodAttributes.Public);
ctorBuilder2.LoadArgument(0);
ctorBuilder2.LoadConstant("arg1");
ctorBuilder2.Call(ctor1); // Exception thrown here
ctorBuilder2.Return();
var ctor2 = ctorBuilder2.CreateConstructor();
test.CreateType();
asm.Save(asmName.Name + ".dll");
}
}
我阅读了有关使用“DynamicMethod”的信息,但是当我用以下内容替换 BuildConstructor
调用时出现错误 "Delegate of type Sigil.Impl.NonGenericPlaceholderDelegate takes no parameters":
var piCtor = Emit.NewDynamicMethod(pi, new Type[] {}, ".ctor", mod);
感谢您的帮助。
目前看来,至少 Sigil.NonGeneric
没有正确处理这个问题。但是,看起来您也可以将 Sigil 与非 Sigil 代码混合搭配。
所以你可以改变只是你的ctorBuilder2
代码以使用内置Reflection.Emit代码:
var ctorBuilder2 = test.DefineConstructor(MethodAttributes.Public,
CallingConventions.Standard, new Type[0]);
var generator = ctorBuilder2.GetILGenerator();
generator.Emit(OpCodes.Ldarg_0);
generator.Emit(OpCodes.Ldstr, "arg1");
generator.Emit(OpCodes.Call, ctor1);
generator.Emit(OpCodes.Ret);
这似乎是根据需要构建程序集。