Unity 是一款知名的依赖注入容器( dependency injection container) ,其支持通过自定义扩展来扩充功能。

在Unity软件包内 默认包含了一个对象拦截(Interception)扩展定义。

本篇文章将介绍如何使用对象拦截(Interception)来分离横切关注点(Separation of cross-cutting concerns)。

对象拦截简介

对象拦截(Interception)是一种 AOP(Aspect-oriented programming)编程的实践方法。

其可帮助你保持业务类的纯净,而无需考虑诸如日志和缓存等外围关注点(other concerns)。

在.NET中,实现AOP有多种方法。

一种方式是采用编译后( post-compiler)处理方式,例如 PostSharp。在编译后( after compilation),PostSharp通过修改IL代码来注入(injects)横切代码。

相反地,对象拦截(Interception)是在运行时(Runtime)执行的,同时也意味着会有一些限制。依据不同的拦截器实现,会有如下这些约束:

  • 透明代理拦截器(Transparent Proxy Interceptor):需要定义接口(interface),或者要求类继承(inherit)自MarshalByRefObject。
  • 接口拦截器(Interface Interceptor):需要定义接口。
  • 虚方法拦截器(Virtual Method Interceptor):仅需要方法被定义成virtual方法。

对象拦截如何工作

当从Unity容器请求目标对象时,将不会获取到已配置的类的实例。

实际上,将得到一个动态生成的代理对象(dynamically generated proxy object),或者一个衍生类(derived class)。

如果调用代理对象的一个方法,将可以在被调用方法执行前或执行后执行一些额外行为的代码。

那些定义行为的类需要实现ICallHandler接口。

通过这些行为定义,我们可以访问方法调用的参数列表(arguments),可以吞噬异常(swallow exceptions),或者返回自定义的异常( return custom exceptions)。

  附带提一下,在不使用 Unity container的条件下,也是可以使用 Unity interception的。

示例:将异常和方法调用参数列表记录到日志中

在下面的示例中,我们将创建两个自定义的行为(behaviors),都实现了ICallHandler接口:

  • LoggerCallHandler:将方法调用参数列表(method arguments)记录到日志中。
  • ExceptionLoggerCallHandler:当发生异常时,将方法调用参数列表和调用栈信息记录到日志中。

ExceptionLoggerCallHandler定义如下:

internal class ExceptionLoggerCallHandler : ICallHandler
{
public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
{
// before invoking the method on the original target
Console.WriteLine(String.Format("Invoking method {0} at {1} ", input.MethodBase, DateTime.Now.ToString() )); // invoke the next behavior in the chain
IMethodReturn result = getNext()(input, getNext); // after invoking the method on the original target
if (result.Exception != null)
{
Console.WriteLine("Exception occured: " + result.Exception.Message); Console.WriteLine("Parameters:");
foreach (var parameter in input.Arguments)
{
Console.WriteLine(parameter.ToString());
} Console.WriteLine("StackTrace:");
Console.WriteLine(Environment.StackTrace);
} return result;
} public int Order { get; set; }
}

为了将行为应用到方法上,我们需要创建相应的HandlerAttribute来创建行为的实例。

internal class ExceptionLoggerAttribute : HandlerAttribute
{
public override ICallHandler CreateHandler(IUnityContainer container)
{
return new ExceptionLoggerCallHandler();
}
}

在这个示例中,我们创建一个简单的计算器类。

同时为了使用接口拦截( Interface Interception),我们还需创建一个接口类型,这样才能应用指定的行为:

public interface ICalculator
{
[Logger]
int Add(int first, int second); [ExceptionLogger]
int Multiply(int first, int second);
}

计算器类的实现还和常规的一样。

现在我们需要配置(setup)Unity容器:

IUnityContainer container = new UnityContainer();
container.AddNewExtension<Interception>();
container.RegisterType<ICalculator, Calculator>()
.Configure<Interception>()
.SetInterceptorFor<ICalculator>(new InterfaceInterceptor()); // Resolve
ICalculator calc = container.Resolve<ICalculator>(); // Call method
calc.Add(, );

当在容器上通过调用Resolve方法来尝试获得一个Calculate类的实例时,将会得到一个代理类(proxy  class)实例。

它的名字可能类似于 ‘DynamicModule.ns.Wrapped_ICalculator_83093f794c8d452e8af4524873a017de’。

当调用此包装类(the wrapper class)的某个方法时,CallHandlers将会被执行。

总结

Unity并不提供一个完整的AOP框架,因此使用它会有一些限制。但不管怎样,使用Unity对象拦截功能来实现一些基本的AOP需求已经足够了。

原文链接:AOP - Interception with Unity 2.0 (http://www.palmmedia.de/Blog/2010/9/26/aop-interception-with-unity-20)

(翻译) 使用Unity进行AOP对象拦截的更多相关文章

  1. 运用Unity实现AOP拦截器

    运用Unity实现AOP拦截器[结合异常记录实例] 本篇文章将通过Unity实现Aop异常记录功能:有关Unity依赖注入可以看前两篇文章: 1:运用Unity实现依赖注入[结合简单三层实例] 2:运 ...

  2. 运用Unity实现AOP拦截器[结合异常记录实例]

      本篇文章将通过Unity实现Aop异常记录功能:有关Unity依赖注入可以看前两篇文章: 1:运用Unity实现依赖注入[结合简单三层实例] 2:运用Unity实现依赖注入[有参构造注入] 另早期 ...

  3. Unity Ioc 依赖倒置及Untity AOP被动拦截/自动拦截

    各位博友金安,首先声明这是一篇转载的博客,原文链接:https://www.cnblogs.com/scottpei/archive/2013/01/08/2851087.html 十年河东,十年河西 ...

  4. 我心中的核心组件(可插拔的AOP)~第十三回 实现AOP的拦截组件Unity.Interception

    回到目录 说在前 本节主要说一下Unity家族里的拦截组件,对于方法拦截有很多组件提供,基本上每个Ioc组件都有对它的实现,如autofac,它主要用在orchard项目里,而castle也有以拦截的 ...

  5. AOP实现拦截对象以及获取切入目标方法和注解

    AOP实现拦截对象以及获取切入目标方法和注解 一.JoinPoint是什么? AspectJ使用org.aspectj.lang.JoinPoint接口表示目标类连接点对象,如果是环绕增强时,使用 o ...

  6. 运用Unity结合PolicyInjection实现拦截器

    运用Unity结合PolicyInjection实现拦截器[结合操作日志实例] 上一篇文章我们通过Unity自身Unity.InterceptionExtension.IInterceptionBeh ...

  7. AOP之拦截函数调用链实现

    AOP之拦截函数调用链实现 定义函数A,B,C,调用A->B->C,这样就形成了函数静态调用链,而AOP要做的是能动态的添加多个B,形成A->B1->B2->B3...- ...

  8. .NET中使用unity实现aop

    Unity是一款知名的依赖注入容器,其支持通过自定义扩展来扩充功能.在Unity软件包内默认包含了一个对象拦截(Interception)扩展定义.本篇文章将介绍如何使用对象拦截功能来帮助你分离横切关 ...

  9. Ioc 之 Unity的AOP功能

    前面我们介绍了Unity的依赖注入功能,现在来介绍下Unity的AOP功能.AOP是面向切面编程,它能够使我们在不改变现有代码结构的情况下额外的为其添加一些功能. 我们还是使用配置文件来对类型进行注入 ...

随机推荐

  1. virtualenv 个人指南

    virtualenv是解决一个机器上多个应用需要的Python版本不一致的问题,virtualenv就是用来为一个应用创建一套"隔离"的Python运行环境,解决了解决了不同应用间 ...

  2. myeclipse安装插件svn的步骤

    下载插件地址:http://subclipse.tigris.org/ 方法一:本地安装 1.打开HELP->MyEclipse Configuration或者myeclipse->MyE ...

  3. docker-compose的安装和设定

    docker的1.12版本中,swarm已经合体,docker-engine/swarm/docker-compose的三件套装已经变成两件.后续会不会将docker-compose进一步合体呢,想做 ...

  4. 容易出错的JavaScript题目集锦

    容易出错的JavaScript题目集锦 1.typeof(null) 会得到什么?object,在JavaScript中null被认为是一个对象. 2.下列代码将输出控制台的是什么?为什么? 1234 ...

  5. Python爬虫-百度模拟登录(二)

    上一篇-Python爬虫-百度模拟登录(一) 接上一篇的继续 参数 codestring codestring jxG9506c1811b44e2fd0220153643013f7e6b1898075 ...

  6. sql -- 获取连续签到的用户列表

    签到表: 需求:统计连续签到的 用户 1.根据用户和日期分组 select user_name, sign_date from user_sign group by user_name, sign_d ...

  7. Java程序员考研失败后的面试经历,oppo、VIVO、等面经

      温馨提示:有些可能会遗漏个别问题,都是最近一周的面试,有点忘了. 浪潮(一面挂) 你是网络工程的?对网络很了解? 解释一下什么是广播域 怎么划分子网 说一下CSS的几种分类器 数据库中有哪些聚集函 ...

  8. [LeetCode] 207. Course Schedule 课程表

    题目: 分析: 这是一道典型的拓扑排序问题.那么何为拓扑排序? 拓扑排序: 有三件事情A,B,C要完成,A随时可以完成,但B和C只有A完成之后才可完成,那么拓扑排序可以为A>B>C或A&g ...

  9. python如何在图片上添加文字(中文和英文)

    Python在图片上添加文字的两种方法:OpenCV和PIL 一.OpenCV方法 1.安装cv2 pip install opencv-python 2.利用putText方法来实现在图片的指定位置 ...

  10. 【Spring Data 系列学习】Spring Data JPA 自定义查询,分页,排序,条件查询

    Spring Boot Jpa 默认提供 CURD 的方法等方法,在日常中往往时无法满足我们业务的要求,本章节通过自定义简单查询案例进行讲解. 快速上手 项目中的pom.xml.application ...