微软企业库5.0-面向切面AOP(PolicyInjection)学习记录--自定义属性匹配来拦截方法

时间:2022-10-25 00:10:45

--自定义属性匹配来拦截方法

 

   面向切面关注将代码的业务流程和其他辅助流程分开解耦和,使我们写业务代码时不再关注之外的逻辑,比如定义一个人(person),具有咆哮的行为(Shout),有时候为了调试跟踪实现而输出一些内容,如下:

    public interface PersonBase

    {

        voidShout(string aa);

    }

 

    public class Person : PersonBase

    {

        public void Shout(string aa)

        {

            //这句是为了跟踪代码执行情况不属于业务逻辑-

            Console.WriteLine("Come Here,pre shout");

            //这句是真正的业务逻辑-

            Console.WriteLine(aa);

            //这句也是为了跟踪代码执行情况

            Console.WriteLine("Come Here,post shout");

        }

    }

 

可以看出,咆哮方法执行的实际内容只有一条,但是为了跟踪调试而带来了3条代码,而多余的代码是硬写的代码(我们经常会在日志,异常,验证)等代码里附加一些不雅观的代码(感觉不影响业务逻辑,就稍微偷懒点),这样的代码很影响整体的复用,是将来维护系统的杀手。

我希望将跟踪的代码放到方法外面,那么就可以使用方法拦截(AOP),下面开始动手。

注意:需要引用的程序集如下

MicroSoft.Practices.EnterpriseLibra.Common    

MicroSoft.Practices.EnterpriseLibra.Common

MicroSoft.Practices.EnterpriseLibra.Common

MicroSoft.Practices.EnterpriseLibra.Common

System.Configuration

 

首先要解决的第一个问题就是,定位要拦截方法,这就牵扯到匹配方法,这里为了学习,采用自定义属性的方式匹配。

定义一个属性类

         [AttributeUsage(AttributeTargets.Method)]

         public class TraceAttribute:System.Attribute

         {

         }

为接口的Shout方法添加该属性

    public interface IPerson

    {

        [Trace]

        voidShout(string aa);

}

修改Person的实现

    public class Person : IPerson

    {

        public void Shout(string aa)

        {

            Console.WriteLine(aa);

        }

}

然后修改AppConfig配置文件,使用配置工具配置如下

微软企业库5.0-面向切面AOP(PolicyInjection)学习记录--自定义属性匹配来拦截方法

这表示要拦截定义了TraceAttribute属性的方法。

第二步,方法拦截到了,现在的事情是要注入操作,定义一个用于拦截的类

    [ConfigurationElementType(typeof(CustomCallHandlerData))]

    public class TraceCallHandler: ICallHandler

    {

        public string PreMessage { get;privateset; }

        public string PostMessage { get;privateset; }

        //这个构造函数供配置系统使用(由配置文件自动调用)

        publicTraceCallHandler(System.Collections.Specialized.NameValueCollectionattributes)

        {

            this.PreMessage= String.IsNullOrEmpty(attributes["PreMessage"]) ?"" : attributes["PreMessage"];

            this.PostMessage= String.IsNullOrEmpty(attributes["PostMessage"]) ?"" : attributes["PostMessage"];

        }

        public IMethodReturn Invoke(IMethodInvocationinput,GetNextHandlerDelegate getNext)

        {

            if (input ==null)thrownewArgumentNullException("input");

            if(getNext == null) thrownewArgumentNullException("getNext");

            //这句是跟踪输出

            Console.WriteLine(PreMessage,System.Threading.Thread.CurrentPrincipal.Identity.Name,input.MethodBase.Name);      

            //这句是用来调用真正的业务方法

            varresult = getNext()(input, getNext);

            //这句也是跟踪输出

            Console.WriteLine(PostMessage,input.MethodBase.Name);

            returnresult;

        }

 

        public int Order{get;set;}

}

 修改appconfig文件

微软企业库5.0-面向切面AOP(PolicyInjection)学习记录--自定义属性匹配来拦截方法

好了,在Main里测试一下

IPerson per =Microsoft.Practices.EnterpriseLibrary.PolicyInjection.PolicyInjection.Create<Person,IPerson>();

            per.Shout("Helloworld ! Come ......");

输出如下

 用户[]试图执行[Shout]......
Hello world ! Come ......
[Shout]执行完毕......

 

可以看到,执行成功。