代码之家  ›  专栏  ›  技术社区  ›  Thomas Flinkow

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

  •  2
  • Thomas Flinkow  · 技术社区  · 7 年前

    使用.NET4.7.2,我动态地生成 .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文件 .dll文件 对于DotPeek和ilspy,它们都不显示任何名称空间或类型(尽管它们应该显示类型) TypeName 在命名空间中 MyNamespace


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

    1 回复  |  直到 7 年前
        1
  •  2
  •   pfx    7 年前

    无法保存您的类型,因为它是在 .
    AssemblyBuilder Save
    看到了吗 remarks .

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

    要持久化您的类型,您必须以非暂时形式声明它 持久动态模块 ,使用 DefineDynamicModule fileName 论点,像这样:

    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.