public class DynamicProxyGenerator{private const string DynamicAssemblyName = "DynamicAssembly";//动态程序集名称private const string DynamicModuleName = "DynamicAssemblyModule";private const string DynamicModuleDllName = "DynamicAssembly.dll";//动态模块名称private const string ProxyClassNameFormater = "{0}Proxy";private const string ModifiedPropertyNamesFieldName = "ModifiedPropertyNames";private const MethodAttributes GetSetMethodAttributes = MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.CheckAccessOnOverride | MethodAttributes.Virtual | MethodAttributes.HideBySig;/// <summary>/// 创建动态程序集,返回AssemblyBuilder/// </summary>/// <param name="isSavaDll"></param>/// <returns></returns>private static AssemblyBuilder DefineDynamicAssembly(bool isSavaDll = false){//动态创建程序集AssemblyName DemoName = new AssemblyName(DynamicAssemblyName);AssemblyBuilderAccess assemblyBuilderAccess = isSavaDll ? AssemblyBuilderAccess.RunAndSave : AssemblyBuilderAccess.Run;AssemblyBuilder dynamicAssembly = AppDomain.CurrentDomain.DefineDynamicAssembly(DemoName, assemblyBuilderAccess);return dynamicAssembly;}/// <summary>/// 创建动态模块,返回ModuleBuilder/// </summary>/// <param name="isSavaDll"></param>/// <returns>ModuleBuilder</returns>private static ModuleBuilder DefineDynamicModule(AssemblyBuilder dynamicAssembly, bool isSavaDll = false){ModuleBuilder moduleBuilder = null;//动态创建模块if (isSavaDll)moduleBuilder = dynamicAssembly.DefineDynamicModule(DynamicModuleName, DynamicModuleDllName);elsemoduleBuilder = dynamicAssembly.DefineDynamicModule(DynamicModuleName);return moduleBuilder;}/// <summary>/// 创建动态代理类,重写属性Get Set 方法,并监控属性的Set方法,把变更的属性名加入到list集合中,需要监控的属性必须是virtual/// 如果你想保存修改的属性名和属性值,修改Set方法的IL实现/// </summary>/// <typeparam name="T"></typeparam>/// <param name="isSavaDynamicModule"></param>/// <returns></returns>public static T CreateDynamicProxy<T>(bool isSavaDynamicModule = false){Type modifiedPropertyNamesType = typeof(HashSet<string>);Type typeNeedProxy = typeof(T);AssemblyBuilder assemblyBuilder = DefineDynamicAssembly(isSavaDynamicModule);//动态创建模块ModuleBuilder moduleBuilder = DefineDynamicModule(assemblyBuilder, isSavaDynamicModule);string proxyClassName = string.Format(ProxyClassNameFormater, typeNeedProxy.Name);//动态创建类代理TypeBuilder typeBuilderProxy = moduleBuilder.DefineType(proxyClassName, TypeAttributes.Public, typeNeedProxy);//定义一个变量存放属性变更名FieldBuilder fbModifiedPropertyNames = typeBuilderProxy.DefineField(ModifiedPropertyNamesFieldName, modifiedPropertyNamesType, FieldAttributes.Public);/** 构造函数 实例化 ModifiedPropertyNames,生成类似于下面的代码ModifiedPropertyNames = new List<string>();*/ConstructorBuilder constructorBuilder = typeBuilderProxy.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, null);ILGenerator ilgCtor = constructorBuilder.GetILGenerator();ilgCtor.Emit(OpCodes.Ldarg_0);//加载当前类ilgCtor.Emit(OpCodes.Newobj, modifiedPropertyNamesType.GetConstructor(new Type[0]));//实例化对象入栈ilgCtor.Emit(OpCodes.Stfld, fbModifiedPropertyNames);//设置fbModifiedPropertyNames值,为刚入栈的实例化对象ilgCtor.Emit(OpCodes.Ret);//返回//获取被代理对象的所有属性,循环属性进行重写PropertyInfo[] properties = typeNeedProxy.GetProperties();foreach (PropertyInfo propertyInfo in properties){string propertyName = propertyInfo.Name;Type typePepropertyInfo = propertyInfo.PropertyType;//动态创建字段和属性FieldBuilder fieldBuilder = typeBuilderProxy.DefineField("_" + propertyName, typePepropertyInfo, FieldAttributes.Private);PropertyBuilder propertyBuilder = typeBuilderProxy.DefineProperty(propertyName, PropertyAttributes.SpecialName, typePepropertyInfo, null);//重写属性的Get Set方法var methodGet = typeBuilderProxy.DefineMethod("get_" + propertyName, GetSetMethodAttributes, typePepropertyInfo, Type.EmptyTypes);var methodSet = typeBuilderProxy.DefineMethod("set_" + propertyName, GetSetMethodAttributes, null, new Type[] { typePepropertyInfo });//il of get methodvar ilGetMethod = methodGet.GetILGenerator();ilGetMethod.Emit(OpCodes.Ldarg_0);ilGetMethod.Emit(OpCodes.Ldfld, fieldBuilder);ilGetMethod.Emit(OpCodes.Ret);//il of set methodILGenerator ilSetMethod = methodSet.GetILGenerator();ilSetMethod.Emit(OpCodes.Ldarg_0);ilSetMethod.Emit(OpCodes.Ldarg_1);ilSetMethod.Emit(OpCodes.Stfld, fieldBuilder);ilSetMethod.Emit(OpCodes.Ldarg_0);ilSetMethod.Emit(OpCodes.Ldfld, fbModifiedPropertyNames);ilSetMethod.Emit(OpCodes.Ldstr, propertyInfo.Name);ilSetMethod.Emit(OpCodes.Callvirt, modifiedPropertyNamesType.GetMethod("Add", new Type[] { typeof(string) }));ilSetMethod.Emit(OpCodes.Pop);ilSetMethod.Emit(OpCodes.Ret);//设置属性的Get Set方法propertyBuilder.SetGetMethod(methodGet);propertyBuilder.SetSetMethod(methodSet);}//使用动态类创建类型Type proxyClassType = typeBuilderProxy.CreateType();//保存动态创建的程序集if (isSavaDynamicModule)assemblyBuilder.Save(DynamicModuleDllName);//创建类实例var instance = Activator.CreateInstance(proxyClassType);return (T)instance;}/// <summary>/// 获取属性的变更名称,/// 此处只检测调用了Set方法的属性,不会检测值是否真的有变/// </summary>/// <param name="obj"></param>/// <returns></returns>public static HashSet<string> GetModifiedProperties(object obj){FieldInfo fieldInfo = obj.GetType().GetField(ModifiedPropertyNamesFieldName);if (fieldInfo == null) return null;object value = fieldInfo.GetValue(obj);return value as HashSet<string>;}}

使用:

Person p = DynamicProxyGenerator.CreateDynamicProxy<Person>(true);
p.Name = "tom";
p.Name = "tony";
p.Age = 111;
var changes = DynamicProxyGenerator.GetModifiedProperties(p);

本文转自这个地址

C# 使用Emit动态注入代码,实现监控属性的目的相关推荐

  1. 【转载】使用javassist动态注入代码

    关于java字节码的处理,目前有很多工具,如bcel,asm.不过这些都需要直接跟虚拟机指令打交道.如果你不想了解虚拟机指令,可以采用javassist.javassist是jboss的一个子项目,其 ...

  2. 使用javassist动态注入代码

    http://dennis-zane.iteye.com/blog/57540 关于java字节码的处理,目前有很多工具,如bcel,asm.不过这些都需要直接跟虚拟机指令打交道.如果你不想了解虚拟机 ...

  3. 【Android 逆向】Android 进程代码注入原理 ( 注入本质 | 静态注入和动态注入 | 静态注入两种方式 | 修改动态库重打包 | 修改 /data/app/xx/libs 动态库 )

    文章目录 一.注入本质 二.静态注入和动态注入 三.静态注入两种方式 ( 修改动态库重打包 | 修改 /data/app/packageName/libs/ 下的动态库 ) 一.注入本质 进程注入本质 ...

  4. 【Android 逆向】Android 进程注入工具开发 ( 注入代码分析 | 注入工具收尾操作 | 关闭注入的动态库 | 恢复寄存器 | 脱离远程调试附着 )

    文章目录 一.dlclose 函数简介 二.关闭注入的 libbridge.so 动态库 三.恢复寄存器 四.脱离远程调试附着 一.dlclose 函数简介 dlclose 函数的作用是 卸载一个 指 ...

  5. 【Android 逆向】Android 进程注入工具开发 ( 注入代码分析 | 获取注入的 libbridge.so 动态库中的 load 函数地址 并 通过 远程调用 执行该函数 )

    文章目录 一.dlsym 函数简介 二.获取 目标进程 linker 中的 dlsym 函数地址 三.远程调用 目标进程 linker 中的 dlsym 函数 获取 注入的 libbridge.so ...

  6. 【Android 逆向】Android 进程注入工具开发 ( 注入代码分析 | 远程调用 目标进程中 libc.so 动态库中的 mmap 函数 三 | 等待远程函数执行完毕 | 寄存器获取返回值 )

    文章目录 前言 一.等待远程进程 mmap 函数执行完毕 二.从寄存器中获取进程返回值 三.博客资源 前言 前置博客 : [Android 逆向]Android 进程注入工具开发 ( 注入代码分析 | ...

  7. 【Android 逆向】Android 进程注入工具开发 ( 注入代码分析 | 远程调用 目标进程中 libc.so 动态库中的 mmap 函数 二 | 准备参数 | 远程调用 mmap 函数 )

    文章目录 一.准备 mmap 函数的参数 二.mmap 函数远程调用 一.准备 mmap 函数的参数 上一篇博客 [Android 逆向]Android 进程注入工具开发 ( 注入代码分析 | 远程调 ...

  8. Spring Boot轻松理解动态注入,删除bean

    原文地址:http://412887952-qq-com.iteye.com/blog/2348445 ​ 我们通过getBean来获得对象,但这些对象都是事先定义好的,我们有时候要在程序中动态的加入 ...

  9. PE病毒初探——向exe注入代码

    PE文件其实就是Windows可执行文件,关于它的一些简要介绍摘自百度: PE文件被称为可移植的执行体是Portable Execute的全称,常见的EXE.DLL.OCX.SYS.COM都是PE文件 ...

最新文章

  1. php批量请求url_php请求url的方法小结
  2. 泛在电力物联网(能源互联网+物联网)浅析
  3. C# this关键字
  4. win10如何关闭文件夹或者照片的最近浏览?
  5. 端口复用突破防火墙(图)
  6. 小红书成立六周年内部信:月活用户量已经突破8500万
  7. 腾讯已问灵魂,鹅厂新立家风
  8. java 管道流_Java IO7:管道流、对象流
  9. 三种基于感知哈希算法的相似图像检索技术
  10. java使用elasticsearch进行模糊查询-已在项目中实际应用
  11. smartprinter注册版_SmartPrinter下载 4.2 共享版
  12. Html 页面底部添加版权信息11
  13. java 数字拆分_如何在java中分割数字?
  14. 在不借助第三方变量情况下实现两个变量的交换(借助于异或运算)
  15. linux操作的进程调度没有采用,Linux进程调度分析
  16. 推荐几款公众号写作必备工具
  17. JavaScript知识之正则表达式(RegExp)
  18. Android 时间轴的实现
  19. Translation idea插件
  20. 经典数字游戏——数独(Sudoku)解法的Python代码实现

热门文章

  1. 【Hibernate框架】关联映射(多对多关联映射)
  2. 基于深度学习分析与检索海量短视频内容
  3. 深圳科目二考试注意事项-手动挡-水头考场
  4. 全球5G论坛主席Latif Ladid:基于IPv6的5G无线移动网络和SDN带来的冲击
  5. 听劝,不要试图以编程为基础去学习网络安全
  6. 【转】周鸿祎:创业计划书,十页PPT讲清九大问题!
  7. 具有穿透性微针的新型脑机接口
  8. c++17可变参函数模板详解
  9. STM32应用开发实践教程:环境光照强度监测的应用开发
  10. 教你使用cookie登录