使用EntLibPIAB Unity 实现动态代理
1 using System; 2 using Unity; 3 using Unity.Interception; 4 using Unity.Interception.Interceptors.InstanceInterceptors.InterfaceInterception; 5 using Unity.Interception.PolicyInjection.Pipeline; 6 using Unity.Interception.PolicyInjection.Policies; 7 namespace FrameworkConsole 8 { 9 public class UnityAOP 10 { 11 public static void Show() 12 { 13 IUnityContainer container = new UnityContainer();//声明一个容器 14 container.RegisterType<IBusiness, Business>();//注册IBusiness 15 IBusiness bus = container.Resolve<IBusiness>();//获取 IBusiness 对象 16 bus.DoSomething();//调用 17 18 Console.WriteLine("********************"); 19 container.AddNewExtension<Interception>(); 20 container.RegisterType<IBusiness, Business>()//注册IBusiness 21 .Configure<Interception>()//配置拦截 22 .SetInterceptorFor<IBusiness>(new InterfaceInterceptor());//设置拦截器 23 bus = container.Resolve<IBusiness>();//重新获取 IBusiness 对象 24 bus.DoSomething();//调用 25 Console.Read(); 26 } 27 28 } 29 }
业务层
1 #region 业务 2 [ExceptionHandlerAttribute(Order = 3)] 3 [LogHandlerAttribute(Order = 2)] 4 [AfterLogHandlerAttribute(Order = 5)] 5 public interface IBusiness 6 { 7 void DoSomething(); 8 } 9 10 public class Business : IBusiness 11 { 12 public void DoSomething() 13 { 14 Console.WriteLine("DoSomething"); 15 } 16 } 17 #endregion 业务 18 /* 19 20 InterfaceInterceptor:在接口的方法上进行标记,这样继承这个接口的类里实现这个接口方法的方法就能被拦截 21 */
Unity 扩展特性
1 #region 特性 2 3 public class LogHandlerAttribute : HandlerAttribute 4 { 5 public override ICallHandler CreateHandler(IUnityContainer container) 6 { 7 return new LogHandler() { Order = this.Order }; 8 } 9 } 10 11 public class ExceptionHandlerAttribute : HandlerAttribute 12 { 13 public override ICallHandler CreateHandler(IUnityContainer container) 14 { 15 return new ExceptionHandler() { Order = this.Order }; 16 } 17 } 18 19 public class AfterLogHandlerAttribute : HandlerAttribute 20 { 21 public override ICallHandler CreateHandler(IUnityContainer container) 22 { 23 return new AfterLogHandler() { Order = this.Order }; 24 } 25 } 26 #endregion 特性
特性对应的行为
1 #region 特性对应的行为 2 3 public class LogHandler : ICallHandler 4 { 5 public int Order { get; set; } 6 /// <summary> 7 /// 8 /// </summary> 9 /// <param name="input">方法调用的参数列表</param> 10 /// <param name="getNext"></param> 11 /// <returns></returns> 12 public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext) 13 { 14 Console.WriteLine("日志已记录,Message:{0},Ctime:{1}", "logInfo", DateTime.Now); 15 return getNext()(input, getNext);//先记录日志后,执行下一步操作 16 } 17 } 18 19 20 public class ExceptionHandler : ICallHandler 21 { 22 public int Order { get; set; } 23 public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext) 24 { 25 IMethodReturn methodReturn = getNext()(input, getNext);//先执行下一步操作,再回来校验执行结果是否发生异常 26 if (methodReturn.Exception == null) 27 { 28 Console.WriteLine("无异常"); 29 } 30 else 31 { 32 Console.WriteLine($"异常:{methodReturn.Exception.Message}"); 33 } 34 return methodReturn; 35 } 36 } 37 38 public class AfterLogHandler : ICallHandler 39 { 40 public int Order { get; set; } 41 public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext) 42 { 43 IMethodReturn methodReturn = getNext()(input, getNext);//先执行下一步操作,再回来记录完成日志 44 Console.WriteLine("完成日志,Message:{0},Ctime:{1},计算结果{2}", "AfterLog", DateTime.Now, methodReturn.ReturnValue); 45 return methodReturn; 46 } 47 } 48 #endregion 特性对应的行为
跟踪程序执行过程会发现 程序执行顺序:记录日志=>异常检测=>完成日志=>业务方法=>完成日志=>异常检测
这里程序执行的顺序类似MVC管道模型 典型的俄罗斯套娃模式
把这些业务结合配置文件改成可配置
配置文件Unity.Config
1 <configuration> 2 <configSections> 3 <section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Unity.Configuration"/> 4 <!--Microsoft.Practices.Unity.Configuration.UnityConfigurationSection--> 5 </configSections> 6 <unity> 7 <sectionExtension type="Microsoft.Practices.Unity.InterceptionExtension.Configuration.InterceptionConfigurationExtension, Unity.Interception.Configuration"/> 8 <containers> 9 <container name="aop"> 10 <extension type="Interception"/> 11 <register type="FrameworkConsole.IBusiness,FrameworkConsole" mapTo="FrameworkConsole.Business,FrameworkConsole"> 12 <interceptor type="InterfaceInterceptor"/> 13 <interceptionBehavior type="FrameworkConsole.UnityWay.MonitorBehavior, FrameworkConsole"/> 14 15 <interceptionBehavior type="FrameworkConsole.UnityWay.LogBeforeBehavior, FrameworkConsole"/> 16 <interceptionBehavior type="FrameworkConsole.UnityWay.ParameterCheckBehavior, FrameworkConsole"/> 17 <interceptionBehavior type="FrameworkConsole.UnityWay.CachingBehavior, FrameworkConsole"/> 18 <interceptionBehavior type="FrameworkConsole.UnityWay.ExceptionLoggingBehavior, FrameworkConsole"/> 19 <interceptionBehavior type="FrameworkConsole.UnityWay.LogAfterBehavior, FrameworkConsole"/> 20 21 </register> 22 </container> 23 </containers> 24 </unity> 25 </configuration>
配置文件配置值 前一项为类地址,后一项为dll地址
另外记得添加Unity.Interception.Configuration.dll
配置行为
1 public class CachingBehavior : IInterceptionBehavior 2 { 3 public IEnumerable<Type> GetRequiredInterfaces() 4 { 5 return Type.EmptyTypes; 6 } 7 8 public IMethodReturn Invoke(IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext) 9 { 10 Console.WriteLine("CachingBehavior"); 11 return getNext().Invoke(input, getNext); 12 } 13 14 public bool WillExecute 15 { 16 get { return true; } 17 } 18 }
1 public class ExceptionLoggingBehavior : IInterceptionBehavior 2 { 3 public IEnumerable<Type> GetRequiredInterfaces() 4 { 5 return Type.EmptyTypes; 6 } 7 8 public IMethodReturn Invoke(IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext) 9 { 10 Console.WriteLine("ExceptionLoggingBehavior"); 11 IMethodReturn methodReturn = getNext()(input, getNext); 12 if (methodReturn.Exception == null) 13 { 14 Console.WriteLine("无异常"); 15 } 16 else 17 { 18 Console.WriteLine($"异常:{methodReturn.Exception.Message}"); 19 } 20 return methodReturn; 21 } 22 23 public bool WillExecute 24 { 25 get { return true; } 26 } 27 }
1 public class LogAfterBehavior : IInterceptionBehavior 2 { 3 public IEnumerable<Type> GetRequiredInterfaces() 4 { 5 return Type.EmptyTypes; 6 } 7 8 public IMethodReturn Invoke(IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext) 9 { 10 Console.WriteLine("LogAfterBehavior"); 11 foreach (var item in input.Inputs) 12 { 13 Console.WriteLine(item.ToString());//反射获取更多信息 14 } 15 IMethodReturn methodReturn = getNext()(input, getNext); 16 Console.WriteLine("LogAfterBehavior" + methodReturn.ReturnValue); 17 return methodReturn; 18 } 19 20 public bool WillExecute 21 { 22 get { return true; } 23 } 24 }
1 public class LogBeforeBehavior : IInterceptionBehavior 2 { 3 public IEnumerable<Type> GetRequiredInterfaces() 4 { 5 return Type.EmptyTypes; 6 } 7 8 public IMethodReturn Invoke(IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext) 9 { 10 Console.WriteLine("LogBeforeBehavior"); 11 foreach (var item in input.Inputs) 12 { 13 Console.WriteLine(item.ToString());//反射获取更多信息 14 } 15 return getNext().Invoke(input, getNext); 16 } 17 18 public bool WillExecute 19 { 20 get { return true; } 21 } 22 }
1 /// <summary> 2 /// 性能监控的AOP扩展 3 /// </summary> 4 public class MonitorBehavior : IInterceptionBehavior 5 { 6 public IEnumerable<Type> GetRequiredInterfaces() 7 { 8 return Type.EmptyTypes; 9 } 10 11 public IMethodReturn Invoke(IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext) 12 { 13 Console.WriteLine(this.GetType().Name); 14 string methodName = input.MethodBase.Name; 15 Stopwatch stopwatch = new Stopwatch(); 16 stopwatch.Start(); 17 18 var methodReturn = getNext().Invoke(input, getNext);//后续逻辑执行 19 20 stopwatch.Stop(); 21 Console.WriteLine($"{this.GetType().Name}统计方法{methodName}执行耗时{stopwatch.ElapsedMilliseconds}ms"); 22 23 return methodReturn; 24 } 25 26 public bool WillExecute 27 { 28 get { return true; } 29 } 30 }
1 public class ParameterCheckBehavior : IInterceptionBehavior 2 { 3 public IEnumerable<Type> GetRequiredInterfaces() 4 { 5 return Type.EmptyTypes; 6 } 7 8 public IMethodReturn Invoke(IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext) 9 { 10 Console.WriteLine("ParameterCheckBehavior"); 11 Console.WriteLine("参数检测无误"); 12 return getNext().Invoke(input, getNext); 13 } 14 15 public bool WillExecute 16 { 17 get { return true; } 18 } 19 }
调用
1 ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap(); 2 fileMap.ExeConfigFilename = Path.Combine(AppDomain.CurrentDomain.BaseDirectory , "Unity.Config"); 3 Configuration configuration = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None); 4 5 UnityConfigurationSection configSection = (UnityConfigurationSection)configuration.GetSection(UnityConfigurationSection.SectionName); 6 configSection.Configure(container, "aop"); 7 8 bus = container.Resolve<IBusiness>();//重新获取 IBusiness 对象 9 bus.DoSomething();//调用
程序执行顺序(按配置文件顺序执行):监控=>LogBefore=>参数检测=>缓存=>异常检测=>LogAfter=>业务方法=>LogAfter=>异常检测=>监控
微软文档:
System.Configuration https://docs.microsoft.com/zh-cn/dotnet/api/system.configuration?view=netframework-4.8
IUnityContainer https://docs.microsoft.com/zh-cn/previous-versions/msp-n-p/ee649880%28v%3dpandp.10%29