2020-07-12

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<TransitionalMovie>().EnableIntercept(); container.Build(); TransitionalMovie tm = container.Resolve<TransitionalMovie>(); 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);   

No comments:

Post a Comment