C# 发出工厂方法

C# 发出工厂方法,c#,reflection,.net-core-3.1,reflection.emit,C#,Reflection,.net Core 3.1,Reflection.emit,给定以下代码: 公共接口IBar1{} 公共类Bar1:IBar1{} 公共接口IBar1工厂{IBar1工厂();} 我想动态地发出一个如下所示的类型 公共类TestBar1工厂:IBAR1工厂 { 公共IBar1工厂(){返回新的Bar1();} } 问题 我遵循了,我还创建了类型,手动构建了它,并在ILDASM中查看,以完全按照编译的DLL中的代码发出代码。我试图模仿的ILDASM生成的代码在本文的末尾 我甚至无法创建类型,我遇到以下错误: System.TypeLoadExcepti

给定以下代码:

公共接口IBar1{}
公共类Bar1:IBar1{}
公共接口IBar1工厂{IBar1工厂();}
我想动态地发出一个如下所示的类型

公共类TestBar1工厂:IBAR1工厂
{
公共IBar1工厂(){返回新的Bar1();}
}
问题

我遵循了,我还创建了类型,手动构建了它,并在ILDASM中查看,以完全按照编译的DLL中的代码发出代码。我试图模仿的ILDASM生成的代码在本文的末尾

我甚至无法创建类型,我遇到以下错误:

System.TypeLoadException : Signature of the body and declaration in a method implementation do not match.
我假设类定义/ctor/factory方法中的枚举有问题?但我正在尝试各种组合,问题不会消失:(

我的代码

AssemblyName asmName=newassemblyname{Name=“ToFactoryDynamicAssembly”};
AssemblyBuilder asmBuilder=AssemblyBuilder.DefinedDynamicAssembly(asmName,AssemblyBuilderAccess.Run);
ModuleBuilder ModuleBuilder=asmBuilder.DefinedDynamicModule(“ToFactoryModule”);
ConstructorInfo systemObjectCtor=Type.GetType(“System.Object”).GetConstructor(新类型[0]);
TypeBuilder facBuilder=moduleBuilder.DefineType($“DynamicFactoryFor{typeof(IBar1Factory.Name}”,
TypeAttributes.Public
|TypeAttributes.AutoClass
|TypeAttributes.AnsiClass
|TypeAttributes.BeforeFieldInit);
facBuilder.AddInterfaceImplementation(typeof(IBAR1工厂));
ConstructorBuilder FACTorBuilder=facBuilder.DefineConstructor(MethodAttributes.Public
|MethodAttributes.hidebysing
|MethodAttributes.SpecialName
|MethodAttributes.RTSpecialName,CallingConventions.Standard,null);
var ctorIL=facCtorBuilder.GetILGenerator();
ctorIL.Emit(操作码.Ldarg_0);
Emit(opcode.Call,systemObjectCtor);
发射(操作码Nop);
ctorIL.Emit(操作码.Ret);
var methodBuilder=facBuilder.DefineMethod(“工厂”,MethodAttributes.Public
|MethodAttributes.hidebysing
|MethodAttributes.NewSlot
|MethodAttributes.Virtual
|MethodAttributes.Final,typeof(IBar),null);
var bar1Ctor=typeof(Bar1).GetConstructors()[0];
var methodIL=methodBuilder.GetILGenerator();
方法发射(操作码Nop);
发射方法(操作码:Newobj、bar1Ctor);
发射方法(操作码Stloc_0);
发射方法(操作码Ldloc_0);
发射方法(操作码Ret);
facBuilder.DefineMethodOverride(methodBuilder,typeof(IBar1Factory).GetMethod(“Factory”);
var type=facBuilder.CreateType();//错误
var-ctor=type.GetConstructors()[0];
IBar1Factory factory=ctor.Invoke(null)作为IBar1Factory;
IBar1 bar1=factory.factory();
使用ILDASM中的IL代码(从Visual Studio编译的DLL中)

对于
TestBar1Factory
,ILDASM会生成此命令

类定义

.class public auto ansi beforefieldinit AddFactoryExtension.Tests.TestBar1Factory
       extends [System.Runtime]System.Object
       implements AddFactoryExtension.Tests.IBar1Factory
{
} // end of class AddFactoryExtension.Tests.TestBar1Factory
执行器

工厂法

.method public hidebysig newslot virtual final 
        instance class AddFactoryExtension.Tests.IBar1 
        Factory() cil managed
{
  // Code size       11 (0xb)
  .maxstack  1
  .locals init (class AddFactoryExtension.Tests.IBar1 V_0)
  IL_0000:  nop
  IL_0001:  newobj     instance void AddFactoryExtension.Tests.Bar1::.ctor()
  IL_0006:  stloc.0
  IL_0007:  br.s       IL_0009
  IL_0009:  ldloc.0
  IL_000a:  ret
} // end of method TestBar1Factory::Factory

我在您的代码中看到以下错误。修复这些错误后,我可以毫无问题地运行您的

var methodBuilder = facBuilder.DefineMethod("Factory", ..., typeof(IBar), null);
返回类型必须是typeof(IBar1)。传递type.EmptyTypes而不是null也是一种很好的做法

在下面的代码中,您有Stloc,但它需要一个目标局部变量

var methodIL = methodBuilder.GetILGenerator();
methodIL.Emit(OpCodes.Nop);
methodIL.Emit(OpCodes.Newobj, bar1Ctor);
methodIL.Emit(OpCodes.Stloc_0);
methodIL.Emit(OpCodes.Ldloc_0);
这里有一个快速解决方案

var bar1Ctor = typeof(Bar1).GetConstructors()[0];
var methodIL = methodBuilder.GetILGenerator();
methodIL.Emit(OpCodes.Newobj, bar1Ctor);
methodIL.Emit(OpCodes.Ret);
不相关,但是。它用于;具有相同名称和签名的虚拟方法的正常重写会自动发生。
var bar1Ctor = typeof(Bar1).GetConstructors()[0];
var methodIL = methodBuilder.GetILGenerator();
methodIL.Emit(OpCodes.Newobj, bar1Ctor);
methodIL.Emit(OpCodes.Ret);