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

本文涉及的产品
密钥管理服务KMS,1000个密钥,100个凭据,1个月
简介:

     在前一篇文章中,介绍了如何使用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)[转]



本文转自kyo-yo博客园博客,原文链接:http://www.cnblogs.com/kyo-yo/archive/2010/12/27/Learning-EntLib-Tenth-Decoupling-Your-System-Using-The-Unity-PART5-Use-Unity-Interceptor.html,如需转载请自行联系原作者


目录
相关文章
|
28天前
|
图形学 开发者 UED
Unity游戏开发必备技巧:深度解析事件系统运用之道,从生命周期回调到自定义事件,打造高效逻辑与流畅交互的全方位指南
【8月更文挑战第31天】在游戏开发中,事件系统是连接游戏逻辑与用户交互的关键。Unity提供了多种机制处理事件,如MonoBehaviour生命周期回调、事件系统组件及自定义事件。本文介绍如何有效利用这些机制,包括创建自定义事件和使用Unity内置事件系统提升游戏体验。通过合理安排代码执行时机,如在Awake、Start等方法中初始化组件,以及使用委托和事件处理复杂逻辑,可以使游戏更加高效且逻辑清晰。掌握这些技巧有助于开发者更好地应对游戏开发挑战。
55 0
|
28天前
|
图形学 C# 开发者
Unity粒子系统全解析:从基础设置到高级编程技巧,教你轻松玩转绚丽多彩的视觉特效,打造震撼游戏画面的终极指南
【8月更文挑战第31天】粒子系统是Unity引擎的强大功能,可创建动态视觉效果,如火焰、爆炸等。本文介绍如何在Unity中使用粒子系统,并提供示例代码。首先创建粒子系统,然后调整Emission、Shape、Color over Lifetime等模块参数,实现所需效果。此外,还可通过C#脚本实现更复杂的粒子效果,增强游戏视觉冲击力和沉浸感。
55 0
|
28天前
|
开发者 图形学 前端开发
绝招放送:彻底解锁Unity UI系统奥秘,五大步骤教你如何缔造令人惊叹的沉浸式游戏体验,从Canvas到动画,一步一个脚印走向大师级UI设计
【8月更文挑战第31天】随着游戏开发技术的进步,UI成为提升游戏体验的关键。本文探讨如何利用Unity的UI系统创建美观且功能丰富的界面,包括Canvas、UI元素及Event System的使用,并通过具体示例代码展示按钮点击事件及淡入淡出动画的实现过程,助力开发者打造沉浸式的游戏体验。
42 0
|
1月前
|
图形学
Unity动画☀️Unity动画系统Bug集合
Unity动画☀️Unity动画系统Bug集合
|
2月前
|
数据可视化 vr&ar C#
|
3月前
|
存储 JSON 关系型数据库
【unity实战】制作unity数据保存和加载系统——大型游戏存储的最优解
【unity实战】制作unity数据保存和加载系统——大型游戏存储的最优解
87 2
|
3月前
|
图形学
【unity实战】Unity中基于瓦片的网格库存系统——类似《逃离塔科夫》的库存系统(下)
【unity实战】Unity中基于瓦片的网格库存系统——类似《逃离塔科夫》的库存系统
50 0
|
3月前
|
图形学 容器
【unity实战】Unity中基于瓦片的网格库存系统——类似《逃离塔科夫》的库存系统(上)
【unity实战】Unity中基于瓦片的网格库存系统——类似《逃离塔科夫》的库存系统
47 0
|
3月前
|
图形学
【unity小技巧】Unity中实现一个战斗连击连招系统,可以动态添加减少连击连招段数功能
【unity小技巧】Unity中实现一个战斗连击连招系统,可以动态添加减少连击连招段数功能
71 0
|
3月前
|
存储 JSON 图形学
【unity实战】制作unity数据保存和加载系统——小型游戏存储的最优解
【unity实战】制作unity数据保存和加载系统——小型游戏存储的最优解
111 0