• .NET Core中Emit的使用


    反射允许我们在运行时获取对象的相关信息,创建对象的实例,执行方法。Emit是作为反射的一个比较高级的功能。使用Emit,可以从零开始动态的创建程序集及类。提供程序的灵活性。本文主要介绍.NET Core中Emit的使用。

    1、程序集(Assembly)

    程序集构成了 .NET 应用程序的部署、版本控制、重用、激活范围和安全权限的基本单元。 程序集是为协同工作而生成的类型和资源的集合,这些类型和资源构成了一个逻辑功能单元。 程序集采用可执行文件 (.exe) 或动态链接库文件 (.dll) 的形式,是 .NET 应用程序的构建基块 。 它们向公共语言运行时提供了注意类型实现代码所需的信息。在 .NET 和 .NET Framework 中,可从一个或多个源代码文件生成程序集。 在 .NET Framework 中,程序集可以包含一个或多个模块。使用System.Reflection.Emit可以动态创建程序集。

    2、模块(Module)

    模块是程序集内代码的逻辑集合,每个模块可以使用不同的语言编写,大多数情况下,一个程序集包含一个模块。程序集包括了代码、版本信息、元数据等。模块是没有 Assembly 清单的 Microsoft 中间语言(MSIL)文件。

    3、Emit的使用

    Emit可以使用MSIL指令动态编写程序逻辑,然后将指令编译成程序集。通过编写代码的方式动态创建程序。比如软件授权,可以输入授权信息后,生成一个授权的DLL,使用Emit实现动态AOP框架等。

    1).NET Framework中使用Emit

    1. using System;
    2. using System.Collections.Generic;
    3. using System.Linq;
    4. using System.Reflection;
    5. using System.Reflection.Emit;
    6. using System.Text;
    7. using System.Threading.Tasks;
    8. namespace ConsoleApp1
    9. {
    10. class Program
    11. {
    12. static void Main(string[] args)
    13. {
    14. CreateAssembly();
    15. LoadAssembly();
    16. Console.ReadKey();
    17. }
    18. public static void LoadAssembly()
    19. {
    20. var ass = AppDomain.CurrentDomain.Load("MyAssembly");
    21. var m = ass.GetModule("MyModule");
    22. var ts = m.GetTypes();
    23. var t = ts.FirstOrDefault();
    24. if (t != null)
    25. {
    26. object obj = Activator.CreateInstance(t);
    27. var me = t.GetMethod("MyMethod");
    28. me.Invoke(obj, null);
    29. }
    30. }
    31. public static void CreateAssembly()
    32. {
    33. //定义一个程序集的名称
    34. var asmName = new AssemblyName("MyAssembly");
    35. //首先就需要定义一个程序集
    36. var defAssembly = AppDomain.CurrentDomain.DefineDynamicAssembly(asmName, AssemblyBuilderAccess.RunAndSave);
    37. //定义一个构建类
    38. var defModuleBuilder = defAssembly.DefineDynamicModule("MyModule", "MyAssembly.dll");
    39. //定义一个类
    40. var defClassBuilder = defModuleBuilder.DefineType("MyClass", TypeAttributes.Public);
    41. //定义一个方法
    42. var defMethodBuilder = defClassBuilder.DefineMethod("MyMethod",
    43. MethodAttributes.Public,
    44. null,//返回类型
    45. null//参数类型
    46. );
    47. //获取IL生成器
    48. var il = defMethodBuilder.GetILGenerator();
    49. //定义一个字符串
    50. il.Emit(OpCodes.Ldstr, "生成的第一个程序");
    51. //调用一个函数
    52. il.Emit(OpCodes.Call, typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string) }));
    53. //返回到方法开始(返回)
    54. il.Emit(OpCodes.Ret);
    55. //创建类型
    56. defClassBuilder.CreateType();
    57. //保存程序集
    58. defAssembly.Save("MyAssembly.dll");
    59. }
    60. }
    61. }

    2).NET Core中使用Emit

    1. using System;
    2. using System.Reflection;
    3. using System.Reflection.Emit;
    4. namespace ConsoleApp2
    5. {
    6. class Program
    7. {
    8. public static void Main()
    9. {
    10. AssemblyName aName = new AssemblyName("ChefDynamicAssembly");
    11. AssemblyBuilder ab =
    12. AssemblyBuilder.DefineDynamicAssembly(
    13. aName,
    14. AssemblyBuilderAccess.Run);
    15. ModuleBuilder mb = ab.DefineDynamicModule(aName.Name + ".dll");
    16. TypeBuilder tb = mb.DefineType("Commander");
    17. var attrs = MethodAttributes.Public;
    18. // 使用类型构建器创建一个方法构建器
    19. MethodBuilder methodBuilder = tb.DefineMethod("Do", attrs, typeof(string), Type.EmptyTypes);
    20. // 通过方法构建器获取一个MSIL生成器
    21. var IL = methodBuilder.GetILGenerator();
    22. // 开始编写方法的执行逻辑
    23. // var store = new string[3];
    24. var store = IL.DeclareLocal(typeof(string[]));
    25. IL.Emit(OpCodes.Ldc_I4, 3);
    26. IL.Emit(OpCodes.Newarr, typeof(string));
    27. IL.Emit(OpCodes.Stloc, store);
    28. //store[0] = "C"
    29. IL.Emit(OpCodes.Ldloc, store);
    30. IL.Emit(OpCodes.Ldc_I4, 0);
    31. IL.Emit(OpCodes.Ldstr, "C");
    32. IL.Emit(OpCodes.Stelem, typeof(string));
    33. //store[1] = "JAVA"
    34. IL.Emit(OpCodes.Ldloc, store);
    35. IL.Emit(OpCodes.Ldc_I4, 1);
    36. IL.Emit(OpCodes.Ldstr, "JAVA");
    37. IL.Emit(OpCodes.Stelem, typeof(string));
    38. //store[2] = "Python"
    39. IL.Emit(OpCodes.Ldloc, store);
    40. IL.Emit(OpCodes.Ldc_I4, 2);
    41. IL.Emit(OpCodes.Ldstr, "Python");
    42. IL.Emit(OpCodes.Stelem, typeof(string));
    43. // IChef chef = new GoodChef();
    44. var chef = IL.DeclareLocal(typeof(IChef));
    45. IL.Emit(OpCodes.Newobj, typeof(StoreChef).GetConstructor(Type.EmptyTypes));
    46. IL.Emit(OpCodes.Stloc, chef);
    47. //var dish = chef.Cook(vegetables);
    48. var dish = IL.DeclareLocal(typeof(string));
    49. IL.Emit(OpCodes.Ldloc, chef);
    50. IL.Emit(OpCodes.Ldloc, store);
    51. IL.Emit(OpCodes.Callvirt, typeof(IChef).GetMethod("Cook"));
    52. IL.Emit(OpCodes.Stloc, dish);
    53. // return dish;
    54. IL.Emit(OpCodes.Ldloc, dish);
    55. IL.Emit(OpCodes.Ret);
    56. //方法结束
    57. // 从类型构建器中创建出类型
    58. var dynamicType = tb.CreateType();
    59. // 通过反射创建出动态类型的实例
    60. var commander = Activator.CreateInstance(dynamicType);
    61. Console.WriteLine(dynamicType.GetMethod("Do").Invoke(commander, null).ToString());
    62. Console.ReadLine();
    63. }
    64. }
    65. public interface IChef
    66. {
    67. string Cook(string[] store);
    68. }
    69. public class StoreChef : IChef
    70. {
    71. public string Cook(string[] store)
    72. {
    73. return "Value:" + string.Join("+", store);
    74. }
    75. }
    76. }

  • 相关阅读:
    LeetCode-190. 颠倒二进制位(java)
    Microsoft Defender Vulnerability部署方案
    使用云过程中,云共享需要注意哪些内容
    C++之operator()和构造函数区别与总结(二百三十)
    CISCO设备信息泄漏漏洞案例2
    SpringCloud复习:(8)Zuul内置过滤器
    记录Windows安装Tomcat后无法打印项目日志原因,非catalina日志
    算法通过村第十二关-字符串|白银笔记|经典面试题
    linux————ceph分布式部署
    pdf怎么转图片,可得到高清图
  • 原文地址:https://blog.csdn.net/lwf3115841/article/details/134519392