C# 动态库只包含元数据,不包含类型

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);

使用.NET4.7.2,我在运行时使用

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.