C# 动态库只包含元数据,不包含类型
使用.NET4.7.2,我在运行时使用C# 动态库只包含元数据,不包含类型,c#,dynamic,dll,.net-assembly,typebuilder,C#,Dynamic,Dll,.net Assembly,Typebuilder,使用.NET4.7.2,我在运行时使用 internal class Program { private static void Main(string[] args) { AssemblyBuilder assemblyBuilder = Thread.GetDomain().DefineDynamicAssembly(new AssemblyName("MyAssembly"), AssemblyBuilderAccess.RunAndSave);
internal class Program
{
private static void Main(string[] args)
{
AssemblyBuilder assemblyBuilder = Thread.GetDomain().DefineDynamicAssembly(new AssemblyName("MyAssembly"), AssemblyBuilderAccess.RunAndSave);
ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule("ModuleName");
TypeBuilder typeBuilder = moduleBuilder.DefineType("MyNamespace.TypeName", TypeAttributes.Public);
typeBuilder.DefineDefaultConstructor(MethodAttributes.Public);
// Build the method 'public int ReturnTheAnswer() => 42;'.
MethodBuilder newMethod = typeBuilder.DefineMethod("ReturnTheAnswer", MethodAttributes.Public, typeof(int), new Type[0]);
ILGenerator ilGen = newMethod.GetILGenerator();
ilGen.Emit(OpCodes.Ldc_I4_S, 42);
ilGen.Emit(OpCodes.Ret);
Type newType = typeBuilder.CreateType();
assemblyBuilder.Save("MyAssembly.dll"); // Save the assembly in the programs work directory ('bin\Debug').
dynamic o = Activator.CreateInstance(newType); // Create an instance of the dynamically created type.
int r = (int) o.ReturnTheAnswer();
Debug.Assert(r == 42); // If this doesn't fail, the type has been built correctly, is in fact in the .dll and can be used perfectly fine.
}
}
我可以很好地使用.dll
中的类型,但是,当使用DotPeek和IL Spy浏览生成的.dll
时,它们都不显示任何名称空间或类型(尽管它们应该在名称空间MyNamespace
中显示类型TypeName
)
为什么在使用两个不同的反编译器时程序集看起来是空的,但使用代码中的类型却可以很好地工作?
(上面的示例代码是mvce,您应该能够重现我遇到的确切行为)您的类型不会被保存,因为它是在瞬态动态模块中声明的
AssemblyBuilder
的Save
方法仅保存非瞬态动态模块。看 此方法保存此方法中定义的所有非瞬态动态模块 动态装配。
不保存瞬态动态模块。
程序集文件名可以与其中一个模块的名称相同。若有,大会 清单存储在该模块中。assemblyFileName可以是 与中包含的所有模块的名称不同 装配如果是,则程序集文件仅包含程序集 舱单 要持久化您的类型,您必须在非瞬态的持久化动态模块中声明它,使用的重载之一接受
文件名
参数,如下所示:
ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule("ModuleName", "MyAssembly.dll");
您的完整代码如下所示。使用相同的文件名将类型和清单保存在一个程序集文件中
AssemblyBuilder assemblyBuilder = Thread.GetDomain().DefineDynamicAssembly(new
AssemblyName("MyAssembly"), AssemblyBuilderAccess.RunAndSave);
ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule("ModuleName", "MyAssembly.dll");
TypeBuilder typeBuilder = moduleBuilder.DefineType("MyNamespace.TypeName", TypeAttributes.Public);
typeBuilder.DefineDefaultConstructor(MethodAttributes.Public);
// Build the method 'public int ReturnTheAnswer() => 42;'.
MethodBuilder newMethod = typeBuilder.DefineMethod("ReturnTheAnswer",
MethodAttributes.Public, typeof(int), new Type[0]);
ILGenerator ilGen = newMethod.GetILGenerator();
ilGen.Emit(OpCodes.Ldc_I4_S, 42);
ilGen.Emit(OpCodes.Ret);
Type newType = typeBuilder.CreateType();
assemblyBuilder.Save("MyAssembly.dll"); // Save the assembly in the programs work directory ('bin\Debug').
dynamic o = Activator.CreateInstance(newType); // Create an instance of the dynamically created type.
int r = (int) o.ReturnTheAnswer();
Debug.Assert(r == 42); // If this doesn't fail, the type has been built correctly, is in fact in the .dll and can be used perfectly fine.