AOP和IoC(微软企业库实现)
本文是讲使用微软企业库来实现AOP和IoC/DI的,大家先装下微软企业库5.0,地址:http://www.microsoft.com/en-us/download/details.aspx?id=15104
AOP的实现,使用PIAB(Policy Injection Application Block)
比如想给这个TestManager类的Method2方法检查权限,有权限时才允许执行Method2方法体,最初的代码如下:
public class TestManager { public void Method2(int x) { Console.WriteLine("output222:{0}", x); } }
下面是改造后的代码:
static class Identity//这个类纯属是为了权限而写的一个很简单的mock用户是否login的类 { public static int UserID { get; set; }//如果UserID>0代表合法用户 } public class TestManager : MarshalByRefObject //这个MarshalByRefObject必须加上 { [PermissionCheckHandlerAttribute] //在目标方法上加上自定义的Attribute(可以多个,就看需求了),这个Attribute必须继承于HandlerAttribute public void Method2(int x) { Console.WriteLine("output222:{0}", x); } } public class PermissionCheckHandler : ICallHandler //这个类是最终AOP要挂载上去的,横切逻辑就在这个类中,这个类必须实现ICallHandler { public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext) { if(Identity.UserID>0) return getNext()(input, getNext); //这句就代表继续执行后续操作,这个后续操作也许是后续的AOP横切点,也许是真正的业务方法调用(随需求) return input.CreateExceptionMethodReturn(new Exception("Permission Denied")); //当报错需要抛异常时,需要用这个方法来生成,不能直接throw new exception } public int Order { get; set; } //当多个AOP横切点存在时,这个Order属性代表优先顺序,数字越低,优先级越高 } [AttributeUsage(AttributeTargets.Method)] //这句可以不写 public class PermissionCheckHandlerAttribute : HandlerAttribute //这个class是最终被贴到业务方法上的Attribute,这个Attribute用来把{业务函数/方法 和 横切点} 绑定起来 { public override ICallHandler CreateHandler(Microsoft.Practices.Unity.IUnityContainer container) { return new PermissionCheckHandler(); //返回横切点class } }
最终调用的代码:
TestManager mgrProxy = PolicyInjection.Create<TestManager>(); //这个就是PIAB入口,能够根据目标class生成代理 Identity.UserID = 0; try { mgrProxy.Method2(1); } catch(Exception ex) { Console.WriteLine("1111111111111-->"+ex.Message); } Identity.UserID = 1; try { mgrProxy.Method2(2); } catch (Exception ex) { Console.WriteLine("2222222222222-->" + ex.Message); } Console.ReadKey();
运行如下:
下面来看看使用Unity时,IoC/DI的实现
初始代码如下(一个interface, 分别有2个具体的实现,很简单):
public interface IManager { void Method1(int x); } public class Manager1 : IManager { public void Method1(int x) { Console.WriteLine("Manager1-->"+x); } } public class Manager2 : IManager { public void Method1(int x) { Console.WriteLine("Manager2-->" + x); } }
程序中,为了达到隔离的目的,只依赖接口,如下代码:
IUnityContainer container = new UnityContainer(); container.RegisterType<IManager, Manager1>(); container.RegisterType<IManager, Manager2>("mgr2"); //当一个Interface拥有多个具体实现的时候,就需要用这种别名的形式标识了 IManager mgr = container.Resolve<IManager>(); //得到默认实例 mgr.Method1(1); mgr = container.Resolve<IManager>("mgr2"); //得到命名实例 mgr.Method1(2); Console.ReadKey();
运行如下:
下面我们来看看更加智能的IoC/DI
上面说的那个IManager的具体实现类,都是默认构造器,我们增加一个具体实现,如下:
public class Manager3 : IManager { private ILog log; public Manager3(ILog log) //多了个依赖ILog,并且这个Manager3没有默认构造器 { this.log = log; } public void Method1(int x) { Console.WriteLine("Manager2-->" + x); log.Write(x.ToString()); } }
咋办呢?难道要Resolve ILog后,再手工放入Manager3?不用,哈哈,如下:
container.RegisterType<ILog, Log1>(); //页注册一个Log进去 container.RegisterType<IManager, Manager3>("mgr3"); //注册一个明明实例 mgr = container.Resolve<IManager>("mgr3"); //直接拉出一个mgr就好,一点都不麻烦,哈哈 mgr.Method1(3); Console.ReadKey();
运行如下:
AOP能结构化很多横切点(日志、事务、权限等)
IoC/DI能简化很多代码...
自省推动进步,视野决定未来。
心怀远大理想。
为了家庭幸福而努力。
商业合作请看此处:https://www.magicube.ai
心怀远大理想。
为了家庭幸福而努力。
商业合作请看此处:https://www.magicube.ai