[EntLib]微软企业库5.0 学习之路——第十步、使用Unity解耦你的系统—PART5——使用Unity自身的拦截器

       在前一篇文章中,介绍了如何使用Unity来接管PIAB进行拦截操作,而Unity自身也提供了类似于ICallHandler的拦截处理程序——IInterceptionBehavior,今天这篇文章就是主要是关于如何使用IInterceptionBehavior和Unity自带拦截器的相关信息。

以下是本文所要介绍的内容:

1、创建自定义InterceptionBehavior

2、三种拦截器的优缺点

3、三种拦截器的使用方法

 

一、创建自定义InterceptionBehavior

      IInterceptionBehavior和ICallHandler非常的类似,看下具体的定义代码:

public interface IInterceptionBehavior
{
    bool WillExecute { get; }

    IEnumerable<Type> GetRequiredInterfaces();
    IMethodReturn Invoke(IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext);
}

1、属性WillExecute ,指示拦截行为是否可被执行。

2、列表GetRequiredInterfaces,用于返回拦截所需的相关接口列表。

3、方法Invoke,具体的调用执行方法,可以在此方法处编写相关业务逻辑代码。

在了解了IInterceptionBehavior相关的代码后,我们就可以开始进行编写相关自定义拦截行为了,不过在此之前先要看下实验所需的一些相关接口和类:

接口IStudent:

public interface IStudent
{
    string Name { get; set; }

    int Age { get; set; }

    void ShowInfo();

    void VirtualShowInfo();
}

实现类Student1:

public class Student1 : IStudent
{
    public void ShowInfo()
    {
        Console.WriteLine("学生姓名:" + this.Name);
        Console.WriteLine("学生年龄:" + this.Age.ToString());
    }
    public virtual void VirtualShowInfo()
    {
        Console.WriteLine("虚拟方法调用");
        Console.WriteLine("学生姓名:" + this.Name);
        Console.WriteLine("学生年龄:" + this.Age.ToString());
    }

    private string _name = "顾磊";
    public string Name
    {
        get
        {
            return _name;
        }
        set
        {
            _name = value;
        }
    }

    private int _age = 22;
    public int Age
    {
        get
        {
            return _age;
        }
        set
        {
            _age = value;
        }
    }
}

其中VirtualShowInfo是为了介绍VirtualMethodInterceptor而用的,后面会介绍到。

现在开始编写具体的拦截行为,这边的拦截行为很简单,就是在调用具体的方法前输出一些字符,具体代码如下:

public class LogBehavior : IInterceptionBehavior
{
    private static readonly MethodInfo methodInfo =
        typeof(IStudent).GetMethod("ShowInfo");


    public IEnumerable<Type> GetRequiredInterfaces()
    {
        return new[] { typeof(IStudent) };
    }

    public IMethodReturn Invoke(IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext)
    {
        //检查参数是否存在
        if (input == null) throw new ArgumentNullException("input");
        if (getNext == null) throw new ArgumentNullException("getNext");
        if (input.MethodBase == methodInfo)
        {
            Console.WriteLine("开始日志记录");
            Console.WriteLine("日志记录完成");
            Console.WriteLine("调用具体方法开始");
            return getNext()(input, getNext);
        }
        else
        {
            return input.CreateMethodReturn(null);
        }
    }

    public bool WillExecute
    {
        get { return true; }
    }
}

这个具体的拦截行为类中有几个需要注意:

1、由于GetRequiredInterfaces是返回拦截相关的接口,所以我这边仅返回IStudent既可。

2、将属性WillExecute置为true,表示可执行。

3、定义一个静态变量methodInfo用于记录接口IStudent下方法ShowInfo信息,由于在实际的拦截过程中Invoke会被执行多次,所以需要针对实际需要拦截的方法进行处理,只有调用到方法ShowInfo时才进行拦截,如果调用到的是方法ShowInfo则输出相应的字符,如果不是则调用input.CreateMethodReturn方法,返回一个无效的IMethodReturn 。

接下来看下如何通过Unity容器来调用这个拦截行为,具体代码如下:

public static void TestInterception()
{
    container.AddNewExtension<Interception>();
    container.RegisterType<IStudent, Student1>(
              //透明代理拦截
              //new Interceptor<TransparentProxyInterceptor>(),
              //接口拦截,与上面的透明拦截效果一样
              new Interceptor<InterfaceInterceptor>(),
              new InterceptionBehavior<LogBehavior>(),
              new InterceptionBehavior<LogBehavior2>());
    var studentInfo = container.Resolve<IStudent>();
    studentInfo.ShowInfo();
}

此处也有几点需要注意:

1、必须为容器增加一个新的扩展AddNewExtension<Interception>();

2、拦截行为必须有一个对应的拦截器,上面代码中分别使用了TransparentProxyInterceptor(透明代理拦截器)和InterfaceInterceptor(接口拦截器)

3、可以为一个拦截器添加多个拦截行为,这样做更多的事情。

配置代码文件如下:

<alias alias="IStudent" type="UnityStudyConsole.IDemo.IStudent, UnityStudyConsole" />
<alias alias="Student1" type="UnityStudyConsole.Demo.Student1, UnityStudyConsole" />
<alias alias="LogBehavior" type="UnityStudyConsole.InterceptionBehavior.LogBehavior, UnityStudyConsole" />
<alias alias="LogBehavior2" type="UnityStudyConsole.InterceptionBehavior.LogBehavior2, UnityStudyConsole" />
<container name="Forth">
  <!--为容器增加Interception扩展,如不增加下面interception配置会报错-->
  <extension type="Interception"/>
  <register type="IStudent" mapTo="Student1">
    <interceptor isDefaultForType="true" type="InterfaceInterceptor"/>
    <interceptionBehavior type="LogBehavior"/>
    <interceptionBehavior type="LogBehavior2"/>
  </register>
</container>

其效果图如下:

pic105

 

二、三种拦截器的优缺点

    Untiy内置了3种拦截器,下面说一下这3种拦截器的优缺点:

1、TransparentProxyInterceptor,透明代理拦截器(实例拦截器),使用.NET TransparentProxy/RealProxy技术来进行拦截

优点:可以拦截对象(虚拟的、非虚拟的以及接口)的所有方法

缺点:拦截的对象必须实现MarshalByRefObject或者实现一个接口,处理的速度过慢。

2、InterfaceInterceptor,接口拦截(实例拦截器),使用动态代码创建一个代理类来进行拦截。

优点:可以拦截所有实现了接口的对象,处理速度比TransparentProxyInterceptor快。

缺点:只能拦截实现了单一接口的方法。

3、VirtualMethodInterceptor,虚拟方法拦截器(类型拦截器),使用动态代码构建一个派生类来代替拦截原始类。

优点:处理速度比TransparentProxyInterceptor快。

缺点:只能拦截虚拟方法。

了解了3种拦截的优缺点后我们可以根据实际的需求来进行选择拦截器。

 

三、三种拦截器的使用方法

      虽说是三种拦截器的使用方法,但其中2种(TransparentProxyInterceptor和InterfaceInterceptor)已经在上面的代码中介绍了,这般主要介绍VirtualMethodInterceptor的使用方法。

由于VirtualMethodInterceptor的特殊性,只能拦截虚拟方法,而在接口的定义过程中,接口中的方法是不能定义为virtual的,但是又要使用VirtualMethodInterceptor的时候需要做以下处理:

1、在接口的实现类中为指定方法增加virtual关键字,如上面的方法VirtualShowInfo

2、更改拦截行为中,拦截方法的获取,如:typeof(Student1).GetMethod("VirtualShowInfo"),直接从指定类中获取方法。

3、更改具体的注册代码,如下:

public static void TestVirtualMethodInterceptor()
{
    container.AddNewExtension<Interception>();
    container.RegisterType<Student1>(
              new Interceptor<VirtualMethodInterceptor>(),
              new InterceptionBehavior<LogBehavior3>(),
              new AdditionalInterface<IStudent>());
    var studentInfo = container.Resolve<Student1>();
    studentInfo.VirtualShowInfo();
}

可以看到上面的代码中直接是对具体的实现类添加拦截器和拦截行为,但是由于其本质还是依赖于IStudent接口,所以还需为其添加一个额外的接口注册new AdditionalInterface<IStudent>(),这样修改以后,运行效果和上面是一样的。

具体配置代码如下:

<container name="Fifth">
  <!--为容器增加Interception扩展,如不增加下面interception配置会报错-->
  <extension type="Interception"/>
  <register type="Student1">
    <interceptor isDefaultForType="true" type="VirtualMethodInterceptor"/>
    <interceptionBehavior type="LogBehavior3"/>
    <addInterface type="IStudent"/>
  </register>
</container>

 

以上就是本文的所有内容了,谢谢阅读到此!

 

话说,各位看过的朋友如果觉得本文对您还有点用,或者觉得本文还有价值的话,麻烦将鼠标移到【推荐】上,帮我点击下,非常非常的感谢!

 

源代码下载:点我下载

 

微软企业库5.0 学习之路系列文章索引:

第一步、基本入门

第二步、使用VS2010+Data Access模块建立多数据库项目

第三步、为项目加上异常处理(采用自定义扩展方式记录到数据库中)

第四步、使用缓存提高网站的性能(EntLib Caching)

第五步、介绍EntLib.Validation模块信息、验证器的实现层级及内置的各种验证器的使用方法——上篇

第五步、介绍EntLib.Validation模块信息、验证器的实现层级及内置的各种验证器的使用方法——中篇

第五步、介绍EntLib.Validation模块信息、验证器的实现层级及内置的各种验证器的使用方法——下篇

第六步、使用Validation模块进行服务器端数据验证

第七步、Cryptographer加密模块简单分析、自定义加密接口及使用—上篇

第七步、Cryptographer加密模块简单分析、自定义加密接口及使用—下篇

第八步、使用Configuration Setting模块等多种方式分类管理企业库配置信息

第九步、使用PolicyInjection模块进行AOP—PART1——基本使用介绍

第九步、使用PolicyInjection模块进行AOP—PART2——自定义Matching Rule

第九步、使用PolicyInjection模块进行AOP—PART3——内置Call Handler介绍

第九步、使用PolicyInjection模块进行AOP—PART4——建立自定义Call Handler实现用户操作日志记录

第十步、使用Unity解耦你的系统—PART1——为什么要使用Unity?

第十步、使用Unity解耦你的系统—PART2——了解Unity的使用方法(1)

第十步、使用Unity解耦你的系统—PART2——了解Unity的使用方法(2)

第十步、使用Unity解耦你的系统—PART2——了解Unity的使用方法(3)

第十步、使用Unity解耦你的系统—PART3——依赖注入

第十步、使用Unity解耦你的系统—PART4——Unity&PIAB

第十步、使用Unity解耦你的系统—PART5——使用Unity自身的拦截器

扩展学习:

扩展学习篇、库中的依赖关系注入(重构 Microsoft Enterprise Library)[转]

posted @ 2010-12-27 09:24  kyo-yo  阅读(6188)  评论(19编辑  收藏  举报