动态库只包含元数据,没有类型
Dynamic library contains only metadata, no types
使用 .NET 4.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
中的类型,但是,当使用 DotPeek 和 IL Spy 浏览生成的 .dll
时,它们都没有显示任何名称空间或类型(尽管它们应该在命名空间 MyNamespace
).
中显示类型 TypeName
为什么在使用两个不同的反编译器时程序集看起来是空的,但是从代码中使用它的类型却工作得很好?
(上面的示例代码是 mvce,你应该能够重现我遇到的确切行为)
您的类型未保存,因为它是在 瞬态动态模块.
中声明的
AssemblyBuilder
的Save
方法只保存非瞬态动态模块。
见 remarks.
This method saves all non-transient dynamic modules defined in this
dynamic assembly.
Transient dynamic modules are not saved.
The assembly file name can be the same as the name of one of the modules. If so, the assembly
manifest is stored within that module. assemblyFileName can be
different from the names of all of the modules contained within the
assembly. If so, the assembly file contains only the assembly
manifest.
要保留您的类型,您必须在非瞬态 可持久动态模块 中声明它,使用接受 [=15] 的 DefineDynamicModule
的重载之一=] 参数,像这样:
ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule("ModuleName", "MyAssembly.dll");
您的完整代码如下所示。
使用相同的文件名将您的类型和清单一起保存在 1 个程序集文件中。
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.
使用 .NET 4.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
中的类型,但是,当使用 DotPeek 和 IL Spy 浏览生成的 .dll
时,它们都没有显示任何名称空间或类型(尽管它们应该在命名空间 MyNamespace
).
TypeName
为什么在使用两个不同的反编译器时程序集看起来是空的,但是从代码中使用它的类型却工作得很好?
(上面的示例代码是 mvce,你应该能够重现我遇到的确切行为)
您的类型未保存,因为它是在 瞬态动态模块.
中声明的
AssemblyBuilder
的Save
方法只保存非瞬态动态模块。
见 remarks.
This method saves all non-transient dynamic modules defined in this dynamic assembly.
Transient dynamic modules are not saved.
The assembly file name can be the same as the name of one of the modules. If so, the assembly manifest is stored within that module. assemblyFileName can be different from the names of all of the modules contained within the assembly. If so, the assembly file contains only the assembly manifest.
要保留您的类型,您必须在非瞬态 可持久动态模块 中声明它,使用接受 [=15] 的 DefineDynamicModule
的重载之一=] 参数,像这样:
ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule("ModuleName", "MyAssembly.dll");
您的完整代码如下所示。
使用相同的文件名将您的类型和清单一起保存在 1 个程序集文件中。
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.