虽然反射对于在运行时检查类型并与之交互一直非常有用,但 .NET 9 更进一步,不仅允许我们创建动态程序集,还可以保存它们以备后用。
以前,构建程序集并跟踪动态创建类型的反射数据仅限于单个用例。这意味着我们可以动态创建程序集,但无法存储它以备将来使用。这给我们带来了一个障碍,我们习惯了在框架中保存程序集的灵活性。
新功能提供:DefinePersistedAssemblyAssemblyBuilder
这项新功能具有以下几个优点:
创建和保存持久化程序集的过程与使用非持久化程序集的过程类似。您仍然可以定义类型、方法和编写指令(称为“中间语言”或“IL”)来定义其行为。魔力在于新方法,它照顾到节省方面。DefinePersistedAssembly
虽然持久化程序集提供了令人兴奋的可能性,但重要的是要考虑以下几点:
让我们编写一个简单的代码示例来巩固我们的理解。
使用非持久化程序集的代码(以前的 .NET 版本):
using System.Reflection.Emit;
using System.Reflection;
public class DynamicAssemblyExample
{
public static void Main(string[] args)
{
// Create a non-persisted assembly
AssemblyBuilder ab = AssemblyBuilder.DefineDynamicAssembly(
new AssemblyName("MyAssembly"),
AssemblyBuilderAccess.Run); // Access needed for immediate execution
UseAssembly(ab); // Use the assembly directly (no need to load from disk)
}
public static void UseAssembly(AssemblyBuilder ab)
{
ModuleBuilder module = ab.GetDynamicModule("MyModule");
TypeBuilder tb = ab.DefineDynamicModule("MyModule").DefineType("MyType", TypeAttributes.Public | TypeAttributes.Class);
MethodBuilder mb = tb.DefineMethod(
"SumMethod",
MethodAttributes.Public | MethodAttributes.Static,
typeof(int), new[] { typeof(int), typeof(int) });
ILGenerator il = mb.GetILGenerator();
// Generate IL instructions for multiplication (instead of addition)
il.Emit(OpCodes.Ldarg_0); // Load first argument onto stack
il.Emit(OpCodes.Ldarg_1); // Load second argument onto stack
il.Emit(OpCodes.Mul); // Multiply the two arguments (changed from Add)
il.Emit(OpCodes.Ret); // Return the result
tb.CreateType();
// Get the method info directly from the in-memory assembly
Type type = ab.GetType("MyType");
MethodInfo method = type.GetMethod("SumMethod");
Console.WriteLine(method.Invoke(10, new object[] { 5, 10 })); // Call SumMethod with arguments
}
}
使用持久化程序集的代码 (.NET 9)
using System.Reflection.Emit;
using System.Reflection;
public class DynamicAssemblyExample
{
public static void Main(string[] args)
{
// Change the path as needed
string assemblyPath = "MyDynamicAssembly.dll";
// Create and save the assembly
CreateAndSaveAssembly(assemblyPath);
// Use the saved assembly
UseAssembly(assemblyPath);
}
public static void CreateAndSaveAssembly(string assemblyPath)
{
AssemblyBuilder ab = AssemblyBuilder.DefinePersistedAssembly(
new AssemblyName("MyAssembly"),
typeof(object).Assembly);
TypeBuilder tb = ab.DefineDynamicModule("MyModule")
.DefineType("MyType", TypeAttributes.Public | TypeAttributes.Class);
MethodBuilder mb = tb.DefineMethod(
"SumMethod",
MethodAttributes.Public | MethodAttributes.Static,
typeof(int), new[] { typeof(int), typeof(int)});
ILGenerator il = mb.GetILGenerator();
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ldarg_1);
il.Emit(OpCodes.Mul);
il.Emit(OpCodes.Ret);
tb.CreateType();
ab.Save(assemblyPath);
}
public static void UseAssembly(string assemblyPath)
{
Assembly assembly = Assembly.LoadFrom(assemblyPath);
Type type = assembly.GetType("MyType");
MethodInfo method = type.GetMethod("SumMethod");
Console.WriteLine(method.Invoke(10, new object[] { 5, 10 }));
}
}
创建持久化程序集
定义类型和方法
生成 IL 指令:
定稿和保存:
加载和使用组件:
简单地说,此代码演示了使用简单的“SumMethod”创建和保存动态程序集所涉及的核心概念。在 .NET 9 中使用持久化程序集。既然您已经对持久化程序集有了深入的了解,为什么不在自己的项目中试验它们呢?
.NET 9 引入了令人兴奋的新功能和改进,旨在满足软件工程师不断变化的需求。若要详细了解 .NET 9 中的新功能和增强功能,请查看官方文档并继续关注未来的更新。