纯手工打造Emit实现AOP private static void OverrideMethods(TypeBuilder tb, MethodInfo method) { if (!method.IsPublic|| !method.IsVirtual || IsObjectMethod(method)) return; Type[] paramTypes = GetParameterTypes(method); MethodAttributes attr = MethodAttributes.Public | MethodAttributes.Family | MethodAttributes.HideBySig | MethodAttributes.Virtual; MethodBuilder mb = tb.DefineMethod(method.Name, attr, method.ReturnType, paramTypes); LocalBuilder result = null; ILGenerator il = mb.GetILGenerator(); bool is_void = method.ReturnType != typeof(void); if (is_void == false) result = il.DeclareLocal(method.ReturnType); object[] attrs = method.GetCustomAttributes(typeof(AspectAttribute), false); if (attrs != null) { //初始化所有当前方法用到的参数object[] CreateLocalParameterArr(il, paramTypes); //初始化AspectContext Type ctxType = typeof(AspectContext); ConstructorInfo info = ctxType.GetConstructor(Type.EmptyTypes); var ctx = il.DeclareLocal(ctxType); il.Emit(OpCodes.Newobj, info); il.Emit(OpCodes.Stloc, ctx); //给AspectContext的参数值属性ParameterArgs赋值 var propMethod = ctxType.GetMethod("set_ParameterArgs"); il.Emit(OpCodes.Ldloc, ctx); il.Emit(OpCodes.Ldloc_0); il.Emit(OpCodes.Call, propMethod); int m = attrs.Length; LocalBuilder[] lbs = new LocalBuilder[m]; MethodInfo[] endInvokeMethods = new MethodInfo[m]; //初始化标记的横切对象,并调用横切对象的BeforeInvoke方法 for (int i = 0; i < m; i++) { var tmpType = attrs[i].GetType(); var aspect = il.DeclareLocal(tmpType); ConstructorInfo tmpInfo = tmpType.GetConstructor(Type.EmptyTypes); il.Emit(OpCodes.Newobj, tmpInfo); il.Emit(OpCodes.Stloc, aspect); var before_invoke_method = tmpType.GetMethod("BeforeInvoke"); endInvokeMethods[i] = tmpType.GetMethod("AfterInvoke"); il.Emit(OpCodes.Ldloc, aspect); il.Emit(OpCodes.Ldloc, ctx); il.Emit(OpCodes.Callvirt, before_invoke_method); il.Emit(OpCodes.Nop); lbs[i] = aspect; } //类对象,参数值依次入栈 for (int i = 0; i <= paramTypes.Length; i++) il.Emit(OpCodes.Ldarg, i); //调用基类的方法 il.Emit(OpCodes.Call, method); //如果有返回值,保存返回值到局部变量 if (is_void == false) il.Emit(OpCodes.Stloc, result); //调用横切对象的AfterInvoke方法 for (int i = 0; i < m; i++) { il.Emit(OpCodes.Ldloc, lbs[i]); il.Emit(OpCodes.Ldloc, ctx); il.Emit(OpCodes.Callvirt, endInvokeMethods[i]); il.Emit(OpCodes.Nop); } //如果有返回值,则把返回值压栈 if (is_void == false) il.Emit(OpCodes.Ldloc, result); //返回 il.Emit(OpCodes.Ret); } }
2023-02-21 00:41:39 33KB C# Emit AOP
1
千行代码实现代理式AOP+属性的自动装配
2023-02-21 00:21:54 137KB emit aop
1
$emit与emit与emit与 $on的用法 新建bus.js import Vue from ‘vue’ export const bus = new Vue() 引用bus.js import {bus} from './bus' bus.$on('test', function (msg) { console.log(msg) }) bus.$emit('test', 11) bus.$emit触发第一次emit触发第一次emit触发第一次 $on监听不到 因为$emit 先于 $on 执行了,VUE并没有储存监听事件,所以无法监听到数据。 我这里遇到的是在调用$emit的时
2022-10-18 10:32:17 42KB bu em emi
1
今天小编就为大家分享一篇PyQT5 emit 和 connect的用法详解,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
2022-08-20 23:33:52 43KB PyQT5 emit connect
1
主要介绍了vue 组件之间事件触发($emit)与event Bus($on)的用法说明,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
2021-09-15 16:20:15 211KB vue $emit eventBus $on
1
源码简介与安装说明: SqlSugar是一款简单易用的开源ORM框架。 优点: 简单易用、功能齐全、高性能、轻量级、服务齐全 支持数据库:MySql、SqlServer、Sqlite、Oracle、postgresql、达梦、人大金仓 性能: 比大部分的DbHelper性能要高,底层采用Emit动态创建数据绑定程序集进行缓存,缓存后的性能可以达到原生水平,相反原始的ADO需要用到大量装箱和拆箱操作性能反而下降。 功能: SqlSugar的功能需求都是来自1000多开发人员的真实项目需求,在这些需求上进行完美的设计,经过5年多的积累,可以完美满足企业级的所有需求特别是查询功能,支持了各种类型的返回例如DataTable、List、字典等,还支持各种查询,例如一次查询多个结果集,当然也支持存储过程。
2021-04-11 20:00:24 8.31MB ORM框架
本人是从0开始自学Emit的,中间比较难受的就是好多Opcpde指令不知道是什么意思、不会用,后来经过查资料总算是搞明白点了。 除了在网上查资料之外学习MSIL另一个好方法就是.Net Reflector和ildasm.exe配合使用,.Net Reflector可以把Emit代码转换为普通C#代码,ildasm.exe可以把普通C#代码转换为MSIL,不会写某一功能的Emit代码就先把它的C#代码写出来,用ildasm.exe转换成MSIL,然后根据生成的MSIL逻辑去写Emit代码,这个很好用。
2019-12-21 22:02:08 25KB Emit Opcodes
1