需求:咱們須要給已經開發好的服務如這裏的UserService,添加額外的執行邏輯,可是又不想破壞原有的服務,如:咱們須要給UserService添加監控邏輯,監控的目的是看UserService服務裏的RegUser方法和GetUser方法的執行時間消耗緩存
一、定義1個用戶接口app
namespace UnityConfigAOP { public interface IUserService { void RegUser(User user); User GetUser(User user); } }
二、實現用戶這個接口性能
namespace UnityConfigAOP { public class UserService:IUserService { public void RegUser(User user) { Console.WriteLine("用戶已註冊。"); } public User GetUser(User user) { Console.WriteLine("獲得用戶信息。"); return user; } } }
三、Unity配置文件
3.一、須要引用以下圖這5個程序集ui
3.一、Unity.Config配置文件的註冊順序就是額外邏輯的調用順序,而後纔是業務方法自己,可是擴展邏輯能夠是業務方法後this
<configuration> <configSections> <section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Unity.Configuration"/> <!--Microsoft.Practices.Unity.Configuration.UnityConfigurationSection--> </configSections> <unity> <sectionExtension type="Microsoft.Practices.Unity.InterceptionExtension.Configuration.InterceptionConfigurationExtension, Unity.Interception.Configuration"/> <containers> <container name="aopContainer"> <extension type="Interception"/> <register type="UnityConfigAOP.IUserService,UnityConfigAOP" mapTo="UnityConfigAOP.UserService,UnityConfigAOP"> <interceptor type="InterfaceInterceptor"/> <interceptionBehavior type="UnityConfigAOP.AOPBehavior.MonitorBehavior, UnityConfigAOP"/> </register> </container> </containers> </unity> </configuration>
3.二、接口方法不須要某個AOP擴展怎麼辦呢?在方法上加個CustomNOAOPAttribute自定義屬性,在執行MonitorBehavior類的Invoke方法裏用特性input.Target.GetType().IsDefined(typeof(CustomNOAOPAttribute), true)去判斷一下
spa
3.三、MonitorBehavior監控行爲額外邏輯代碼pwa
using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Text; using System.Threading.Tasks; using Unity.Interception.InterceptionBehaviors; using Unity.Interception.PolicyInjection.Pipeline; namespace UnityConfigAOP.AOPBehavior { /// <summary> /// 性能監控的AOP擴展 /// </summary> public class MonitorBehavior : IInterceptionBehavior { public IEnumerable<Type> GetRequiredInterfaces() { return Type.EmptyTypes; } public IMethodReturn Invoke(IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext) { var type = input.Target.GetType(); string methodName = input.MethodBase.Name; if (type.IsDefined(typeof(CustomNOAOPAttribute), true)) { var method = getNext().Invoke(input, getNext);//後續邏輯執行 return method; } MethodInfo currentMethod = type.GetMethod(methodName); if (currentMethod.IsDefined(typeof(CustomNOAOPAttribute), true))//檢查方法有沒有定義此屬性 { var method = getNext().Invoke(input, getNext);//後續邏輯執行 return method; } Console.WriteLine(this.GetType().Name); Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); var methodReturn = getNext().Invoke(input, getNext);//後續邏輯執行 stopwatch.Stop(); Console.WriteLine($"{this.GetType().Name}統計方法{methodName}執行耗時{stopwatch.ElapsedMilliseconds}ms"); return methodReturn; } public bool WillExecute { get { return true; } } } }
四、客戶端調用UserService服務3d
namespace UnityConfigAOP { class Program { static void Main(string[] args) { User user = new User() { Name = "David.Meng", Password = "123456" }; //配置UnityContainer IUnityContainer container = new UnityContainer(); ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap(); fileMap.ExeConfigFilename = Path.Combine(AppDomain.CurrentDomain.BaseDirectory + "CfgFiles\\Unity.Config"); Configuration configuration = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None); UnityConfigurationSection configSection = (UnityConfigurationSection)configuration.GetSection(UnityConfigurationSection.SectionName); configSection.Configure(container, "aopContainer"); IUserService userService = container.Resolve<IUserService>(); userService.RegUser(user); userService.GetUser(user); } } }
五、調試代碼
執行userService.RegUser(user);代碼的時候,並無直接進入到RegUser(User user);方法裏面,而是先進到MonitorBehavior類的Invoke方法裏,直到執行到getNext().Invoke(input, getNext);這句代碼才真正的進入到RegUser(User user);方法裏面調試
七、項目截圖,咱們能夠配置多個AOP行爲不光是監控行爲,還能夠配置日誌行爲,異常行爲,緩存行爲等等,以下圖所示
日誌