动态库仅包含元数据,没有类型

时间:2018-10-26 12:10:56

标签: c# dynamic dll .net-assembly typebuilder

使用.NET 4.7.2,我在运行时使用{p>动态生成了.dll

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时,它们都不会显示任何名称空间或类型(尽管它们应该显示命名空间TypeName中的类型MyNamespace


为什么使用两个不同的反编译器时程序集看起来是空的,但是使用代码中的类型可以很好地工作?

(上面的示例代码是mvce,您应该能够重现我遇到的确切行为)

1 个答案:

答案 0 :(得分:2)

您的类型未保存,因为它是在瞬态动态模块中声明的。
AssemblyBuilder的{​​{1}}方法仅保存非瞬态动态模块。
参见remarks

  

此方法保存在此定义的所有非瞬态动态模块   动态装配。
  暂存动态模块不会保存。
  程序集文件名可以与模块之一的名称相同。如果是这样,组装   清单存储在该模块中。 assemblyFileName可以是   与包含在其中的所有模块的名称不同   部件。如果是这样,则程序集文件仅包含程序集   清单。

要保留您的Type,必须使用接受Save参数的DefineDynamicModule的重载之一,在非瞬态的可持久动态模块中对其进行声明。这个:

fileName

您的完整代码如下所示。
使用相同的文件名将您的Type和manifest放在一个单独的汇编文件中。

ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule("ModuleName", "MyAssembly.dll");