NetCore中怎么利用Transitional自定义注解事物
发表于:2023-03-21 作者:安全数据网编辑
编辑最后更新 2023年03月21日,本篇文章给大家分享的是有关NetCore中怎么利用Transitional自定义注解事物,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。之
本篇文章给大家分享的是有关NetCore中怎么利用Transitional自定义注解事物,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。
之前实现了NetCore实现自定义IOC容器注入,在Controller使用事物的过程中思考是否能够像Spring一样通过自定义注解实现事物管理,思路图如下
事物的动作拆分只需要根据当前执行线程划分Connection对象并开启事物即可,重点是在Emit代码织入过程中对异常捕捉的处理
处理过程中主要会用到BeginExceptionBlock开启try代码块,BeginCatchBlock开启catch代码块,EndExceptionBlock结束异常捕捉代码块
创建事物注解Transitional用来标记Controller中需要事物执行的方法
[AttributeUsage(AttributeTargets.Method)] public class Transitional : System.Attribute { public bool AutoRollBack { set; get; } public Transitional() { AutoRollBack = true; } }
Emit编织时需要注意异常捕捉时有返回值时建立全局变量返回,执行事物管理器类的静态方法直接使用call,例如 ilOfMethod.Emit(OpCodes.Call, typeof(TransitionManage).GetMethod("DoRollBack")),同时Controller被拦截的方法需要标记Transitional注解且同时是虚方法
被代理类示例
public class TransitionalMovie{ [Transitional]public virtual void Test1(){ Console.WriteLine("Test1"); } [Transitional]public virtual string Test2(){ Console.WriteLine("Test2");throw new Exception("111");return "Hello"; } [Transitional(AutoRollBack = false)]public virtual void Test3(string Key){ Console.WriteLine("Test3"); Console.WriteLine(Key); }
IOC使用示例,IOC容器原理可参考c#通过Emit方式实现动态代理
var container = new ContainerBuilder(); container.RegisterType().EnableIntercept(); container.Build(); TransitionalMovie tm = container.Resolve (); tm.Test1(); string result = tm.Test2(); Console.WriteLine(result); tm.Test3("世界第一等");
动态代理生成类反编译代码
动态代理包含异常拦截与事物的全部代码
public static Object CreateProxyObject(Type InterfaceType, Type ImpType, Type InterceptType, bool inheritMode = true, bool isInterceptAllMethod = true){string nameOfAssembly = ImpType.Name + "ProxyAssembly";string nameOfModule = ImpType.Name + "ProxyModule";string nameOfType = ImpType.Name + "Proxy";var assemblyName = new AssemblyName(nameOfAssembly); ModuleBuilder moduleBuilder = null;var assembly = AssemblyBuilder.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run); moduleBuilder = assembly.DefineDynamicModule(nameOfModule); TypeBuilder typeBuilder;if (inheritMode) { typeBuilder = moduleBuilder.DefineType( nameOfType, TypeAttributes.Public, ImpType); }else{ typeBuilder = moduleBuilder.DefineType( nameOfType, TypeAttributes.Public, null, new[] { InterfaceType }); } InjectInterceptor(typeBuilder, ImpType, InterceptType, inheritMode, isInterceptAllMethod);var t = typeBuilder.CreateType();return Activator.CreateInstance(t); }private static void InjectInterceptor(TypeBuilder typeBuilder, Type ImpType, Type InterceptType, bool inheritMode, bool isInterceptAllMethod){#region 变量定义// ---- 变量定义 ----var constructorBuilder = typeBuilder.DefineConstructor( MethodAttributes.Public, CallingConventions.Standard, null);var ilOfCtor = constructorBuilder.GetILGenerator();//---- 拦截类对象定义 ----if (InterceptType == null) { InterceptType = typeof(DefaultIntercept); }//声明var fieldInterceptor = typeBuilder.DefineField( "_interceptor", InterceptType, FieldAttributes.Private);//赋值ilOfCtor.Emit(OpCodes.Ldarg_0); ilOfCtor.Emit(OpCodes.Newobj, InterceptType.GetConstructor(new Type[0])); ilOfCtor.Emit(OpCodes.Stfld, fieldInterceptor);#endregion#region 代理对象定义//---- 实现类对象定义 ----//声明var fieldBeProxy = typeBuilder.DefineField( "_beproxy", ImpType, FieldAttributes.Private);//赋值ilOfCtor.Emit(OpCodes.Ldarg_0); ilOfCtor.Emit(OpCodes.Newobj, ImpType.GetConstructor(new Type[0])); ilOfCtor.Emit(OpCodes.Stfld, fieldBeProxy); ilOfCtor.Emit(OpCodes.Ret);#endregion// ---- 定义类中的方法 ----var methodsOfType = ImpType.GetMethods(BindingFlags.Public | BindingFlags.Instance).Where(a => a.IsVirtual).ToArray();string[] ignoreMethodName = new[] { "GetType", "ToString", "GetHashCode", "Equals" };for (var i = 0; i < methodsOfType.Length; i++) {#region 方法是否需要拦截判断,Object内置方法过滤bool IsMethodIntercept = false;bool IsTransitinal = false;var method = methodsOfType[i];//---- 过滤Object基类方法,如果是继承,基类中的属性get,set方法也要过滤 ----if (ignoreMethodName.Contains(method.Name) || method.Name.StartsWith("set_") || method.Name.StartsWith("get_")) {continue; }// ---- 判断方法是否需要拦截 ----if (isInterceptAllMethod) {if (method.GetCustomAttribute(typeof(IgnoreInterceptAttibute)) == null) { IsMethodIntercept = true; } }else{if (method.GetCustomAttribute(typeof(InterceptAttibute)) != null) { IsMethodIntercept = true; } }// ---- 判断方法是否需要纳入事物管理中 ----if (method.GetCustomAttribute(typeof(Transitional)) != null) { IsTransitinal = true; }#endregion#region 泛型方法处理var methodParameterTypes = method.GetParameters().Select(p => p.ParameterType).ToArray();// ---- 定义方法名与参数 ----var methodBuilder = typeBuilder.DefineMethod( method.Name, MethodAttributes.Public | MethodAttributes.Virtual, CallingConventions.Standard, method.ReturnType, methodParameterTypes);//如果是泛型方法if (method.IsGenericMethod) {//获取所有泛型参数类型定义Type[] Args = method.GetGenericArguments(); ListGenericArgNames = new List ();for (int j = 0; j < Args.Length; j++) { GenericArgNames.Add(Args[j].Name); }//代理类方法生成泛型参数定义GenericTypeParameterBuilder[] DGP = methodBuilder.DefineGenericParameters(GenericArgNames.ToArray());//泛型参数约束设置for (int j = 0; j < DGP.Length; j++) {//泛型参数继承约束DGP[j].SetBaseTypeConstraint(Args[j].BaseType);//泛型参数完成接口约束DGP[j].SetInterfaceConstraints(Args[j].GetInterfaces()); } }#endregionvar ilOfMethod = methodBuilder.GetILGenerator();var methodresult = ilOfMethod.DeclareLocal(typeof(object)); //instance of result//赋值方法结果对象初始值为nullilOfMethod.Emit(OpCodes.Ldnull); ilOfMethod.Emit(OpCodes.Stloc_0);#region 事物拦截开始if (IsTransitinal) {//开始try模块ilOfMethod.BeginExceptionBlock();//调用TransitionManage.StartTransitionilOfMethod.Emit(OpCodes.Call, typeof(TransitionManage).GetMethod("StartTransition")); ilOfMethod.Emit(OpCodes.Ldarg_0); }#endregion#region before拦截// ---- before ----if (IsMethodIntercept) {var parameters = ilOfMethod.DeclareLocal(typeof(object[])); ilOfMethod.Emit(OpCodes.Ldc_I4, methodParameterTypes.Length); ilOfMethod.Emit(OpCodes.Newarr, typeof(object)); ilOfMethod.Emit(OpCodes.Stloc, parameters);for (var j = 0; j < methodParameterTypes.Length; j++) { ilOfMethod.Emit(OpCodes.Ldloc, parameters); ilOfMethod.Emit(OpCodes.Ldc_I4, j); ilOfMethod.Emit(OpCodes.Ldarg, j + 1); ilOfMethod.Emit(OpCodes.Stelem_Ref); } ilOfMethod.Emit(OpCodes.Ldarg_0); ilOfMethod.Emit(OpCodes.Ldfld, fieldInterceptor);//拦截方法参数赋值if (inheritMode) {//继承传递代理类本身ilOfMethod.Emit(OpCodes.Ldarg_0); }else{//接口传递实现类ilOfMethod.Emit(OpCodes.Ldarg_0); ilOfMethod.Emit(OpCodes.Ldfld, fieldBeProxy); } ilOfMethod.Emit(OpCodes.Ldstr, method.Name); ilOfMethod.Emit(OpCodes.Ldloc, parameters);//调用拦截类中的Before方法ilOfMethod.Emit(OpCodes.Callvirt, InterceptType.GetMethod("Before")); }#endregion#region 方法执行// ---- call ----////定义实现类局部变量//var localimpobj = ilOfMethod.DeclareLocal(ImpType);////new一个实现类的对象//ilOfMethod.Emit(OpCodes.Newobj, ImpType.GetConstructor(new Type[0]));////局部变量赋值//ilOfMethod.Emit(OpCodes.Stloc, localimpobj);////局部变量出栈,等待调用//ilOfMethod.Emit(OpCodes.Ldloc, localimpobj);//方法执行开始时间var localstart = ilOfMethod.DeclareLocal(typeof(DateTime)); ilOfMethod.Emit(OpCodes.Call, typeof(DateTime).GetMethod("get_Now")); ilOfMethod.Emit(OpCodes.Stloc, localstart);if (inheritMode) {//继承方法调用父类的方法ilOfMethod.Emit(OpCodes.Ldarg_0);for (var j = 0; j < methodParameterTypes.Length; j++) { ilOfMethod.Emit(OpCodes.Ldarg, j + 1); } ilOfMethod.Emit(OpCodes.Call, ImpType.GetMethod(method.Name)); }else{//接口方法调用实现类的方法ilOfMethod.Emit(OpCodes.Ldarg_0); ilOfMethod.Emit(OpCodes.Ldfld, fieldBeProxy);for (var j = 0; j < methodParameterTypes.Length; j++) { ilOfMethod.Emit(OpCodes.Ldarg, j + 1); }//调用方法ilOfMethod.Emit(OpCodes.Callvirt, ImpType.GetMethod(method.Name)); }var localend = ilOfMethod.DeclareLocal(typeof(DateTime)); ilOfMethod.Emit(OpCodes.Call, typeof(DateTime).GetMethod("get_Now")); ilOfMethod.Emit(OpCodes.Stloc, localend);#endregion#region after拦截// ---- after ----if (IsMethodIntercept) {if (method.ReturnType == typeof(void)) { ilOfMethod.Emit(OpCodes.Ldnull); }else{ ilOfMethod.Emit(OpCodes.Box, method.ReturnType); } ilOfMethod.Emit(OpCodes.Stloc, methodresult); ilOfMethod.Emit(OpCodes.Ldarg_0); ilOfMethod.Emit(OpCodes.Ldfld, fieldInterceptor);//拦截方法参数赋值if (inheritMode) {//继承传递代理类本身ilOfMethod.Emit(OpCodes.Ldarg_0); }else{//接口传递实现类ilOfMethod.Emit(OpCodes.Ldarg_0); ilOfMethod.Emit(OpCodes.Ldfld, fieldBeProxy); } ilOfMethod.Emit(OpCodes.Ldstr, method.Name); ilOfMethod.Emit(OpCodes.Ldloc, methodresult); ilOfMethod.Emit(OpCodes.Ldloc, localstart); ilOfMethod.Emit(OpCodes.Ldloc, localend); ilOfMethod.Emit(OpCodes.Callvirt, InterceptType.GetMethod("After")); }#endregion#region 事物提交及异常捕获及回滚if (IsTransitinal) {//调用TransitionManage.DoCommitilOfMethod.Emit(OpCodes.Pop); ilOfMethod.Emit(OpCodes.Call, typeof(TransitionManage).GetMethod("DoCommit")); ilOfMethod.Emit(OpCodes.Ldarg_0);//开始catch模块ilOfMethod.BeginCatchBlock(typeof(System.Exception));//调用TransitionManage.DoRollBackTransitional transition = (Transitional)method.GetCustomAttribute(typeof(Transitional));if (transition.AutoRollBack) { ilOfMethod.Emit(OpCodes.Pop); ilOfMethod.Emit(OpCodes.Call, typeof(TransitionManage).GetMethod("DoRollBack")); }else{//throw异常ilOfMethod.Emit(OpCodes.Pop); ilOfMethod.Emit(OpCodes.Rethrow); }//结束异常块ilOfMethod.EndExceptionBlock(); }#endregion#region 处理返回值//调用完After方法后,将实现类的方法返回值的临时变量再次压栈用作代理方法的返回ilOfMethod.Emit(OpCodes.Ldloc, methodresult);// pop the stack if return voidif (method.ReturnType == typeof(void)) { ilOfMethod.Emit(OpCodes.Pop); }else{if (method.ReturnType.IsValueType) { ilOfMethod.Emit(OpCodes.Unbox_Any, method.ReturnType); }else{ ilOfMethod.Emit(OpCodes.Castclass, method.ReturnType); } }#endregion// completeilOfMethod.Emit(OpCodes.Ret); } }
以上就是NetCore中怎么利用Transitional自定义注解事物,小编相信有部分知识点可能是我们日常工作会见到或用到的。希望你能通过这篇文章学到更多知识。更多详情敬请关注行业资讯频道。
c语言网络技术和编程语言总结
c语言对应的三级考试网络技术
网站服务器后台如何加防护密码
c语言软件开发步骤
c语言中网络技术知识点
服务器对权限提升的防护措施
怎么在阿里云租服务器
黑苹果能做web服务器吗
c语言和网络技术哪个好考
云服务器2核4G是什么性能
服务器双电源的功率
asp.net服务器
服务器销售话术
德温特专利数据库的检索范围
企业网络安全论文格式
长沙程飞网络技术
格家网络技术是什么意思
熟悉软件开发什么意思
网络安全创意海报可打印
oa系统数据库
cf 北部战区服务器
计算机服务器冷却液龙头上市公司
服务器配置和数据库的关系
服务器附加值
网络安全小报手抄报图片鲜色
管理服务器启动项
益阳快速软件开发中介
mvc数据库传递数据
怎么命令行连接数据库
国产数据库迁移问题
网络技术开发操作
服务器和交换机是一个东西吗
如何查询dns服务器地址
云顶之弈如何区分是哪个服务器
服务器管理意义
网络安全产品属于商标第几类
专业性网络技术推广优点
数据库群集项目
时钟同步和网络安全
设计类软件开发产业名称