2、动态代理
了解了静态拦截的例子,你是否对AOP有一个初步的认识了呢。下面我们就来到底AOP该如何使用。按照园子里面很多牛人的说法,AOP的实现方式大致可以分为两类:动态代理和IL 编织两种方式。博主也不打算照本宣科,分别拿Demo来说话吧。下面就以两种方式各选一个代表框架来说明。
动态代理方式,博主就以微软企业库(MS Enterprise Library)里面的PIAB(Policy Injection Application Block)框架来作说明。
首先需要下载以下几个dll,然后添加它们的引用。
然后定义对应的Handler
public class User { public string Name { set; get; } public string PassWord { set; get; } } #region 1、定义特性方便使用 public class LogHandlerAttribute : HandlerAttribute { public string LogInfo { set; get; } public int Order { get; set; } public override ICallHandler CreateHandler(IUnityContainer container) { return new LogHandler() { Order = this.Order, LogInfo = this.LogInfo }; } } #endregion #region 2、注册对需要的Handler拦截请求 public class LogHandler : ICallHandler { public int Order { get; set; } public string LogInfo { set; get; } //这个方法就是拦截的方法,可以规定在执行方法之前和之后的拦截 public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext) { Console.WriteLine("LogInfo内容" + LogInfo); //0.解析参数 var arrInputs = input.Inputs; if (arrInputs.Count > 0) { var oUserTest1 = arrInputs[0] as User; } //1.执行方法之前的拦截 Console.WriteLine("方法执行前拦截到了"); //2.执行方法 var messagereturn = getNext()(input, getNext); //3.执行方法之后的拦截 Console.WriteLine("方法执行后拦截到了"); return messagereturn; } } #endregion #region 3、用户定义接口和实现 public interface IUserOperation { void Test(User oUser); void Test2(User oUser, User oUser2); } //这里必须要继承这个类MarshalByRefObject,否则报错 public class UserOperation : MarshalByRefObject, IUserOperation { private static UserOperation oUserOpertion = null; public UserOperation() { //oUserOpertion = PolicyInjection.Create(); } //定义单例模式将PolicyInjection.Create()产生的这个对象传出去,这样就避免了在调用处写这些东西 public static UserOperation GetInstance() { if (oUserOpertion == null) oUserOpertion = PolicyInjection.Create(); return oUserOpertion; } //调用属性也会拦截 public string Name { set; get; } //[LogHandler],在方法上面加这个特性,只对此方法拦截 [LogHandler(LogInfo = "Test的日志为aaaaa")] public void Test(User oUser) { Console.WriteLine("Test方法执行了"); } [LogHandler(LogInfo = "Test2的日志为bbbbb")] public void Test2(User oUser, User oUser2) { Console.WriteLine("Test2方法执行了"); } } #endregion |
最后我们来看调用的代码:
static void Main(string[] args) { try { var oUserTest1 = new User() { Name = "test2222", PassWord = "yxj" }; var oUserTest2 = new User() { Name = "test3333", PassWord = "yxj" }; var oUser = UserOperation.GetInstance(); oUser.Test(oUserTest1); oUser.Test2(oUserTest1,oUserTest2); } catch (Exception ex) { //throw; } } |
得到结果如下:
我们来看执行Test()方法和Test2()方法时候的顺序。
由于Test()和Test2()方法上面加了LogHander特性,这个特性里面定义了AOP的Handler,在执行Test和Test2方法之前和之后都会进入Invoke()方法里面。其实这就是AOP的意义所在,将切面的通用功能在统一的地方处理,在主要逻辑里面直接用过特性使用即可。