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能简化很多代码...

posted @ 2013-04-09 15:55  McKay  阅读(4580)  评论(8编辑  收藏  举报