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

对象拦截简介

对象拦截是一种AOP(Aspect-oriented programming)编程的实践方法。其可帮助你保持业务类的纯净,而无需考虑诸如日志和缓存等外围关注点。

在.NET中,实现AOP有多种方法。一种方式是采用编译后处理方式,例如PostSharp。在编译后,PostSharp通过修改IL代码来诸如横切代码。

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

  • 透明代理拦截器:需要定义接口,或者要求类继承自MarshalByRefObject。
  • 接口拦截器:需要定义接口。
  • 虚方法拦截器:仅需要方法被定义成virtual方法。

对象拦截如何工作

当从Unity容器请求目标对象时,将不会获取到已配置的类的实例。实际上,将得到一个动态生成的代理对象,或者一个衍生类。

如果调用代理对象的一个方法,将可以在被调用方法执行前或执行后执行一些额外行为的代码。那些定义行为的类需要实现ICallHandler接口。通过这些行为定义,我们可以访问方法调用的参数列表,可以吞噬异常,或者可以返回自定义的异常。

附带提一下,在不使用Unity容器的条件下,也是可以使用Unity拦截器的。

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

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

  • LoggerCallHandler:将方法调用参数列表记录到日志中。
  • ExceptionLoggerCallHandler:将方法调用参数列表和异常信息及调用栈记录到日志中。

ExceptionLoggerCallHandler定义如下:

 1   internal class ExceptionLoggerCallHandler : ICallHandler
2 {
3 public IMethodReturn Invoke(
4 IMethodInvocation input, GetNextHandlerDelegate getNext)
5 {
6 IMethodReturn result = getNext()(input, getNext);
7 if (result.Exception != null)
8 {
9 Console.WriteLine("ExceptionLoggerCallHandler:");
10 Console.WriteLine("\tParameters:");
11 for (int i = 0; i < input.Arguments.Count; i++)
12 {
13 var parameter = input.Arguments[i];
14 Console.WriteLine(
15 string.Format("\t\tParam{0} -> {1}", i, parameter.ToString()));
16 }
17 Console.WriteLine();
18 Console.WriteLine("Exception occured: ");
19 Console.WriteLine(
20 string.Format("\tException -> {0}", result.Exception.Message));
21
22 Console.WriteLine();
23 Console.WriteLine("StackTrace:");
24 Console.WriteLine(Environment.StackTrace);
25 }
26
27 return result;
28 }
29
30 public int Order { get; set; }
31 }

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

1   internal class ExceptionLoggerAttribute : HandlerAttribute
2 {
3 public override ICallHandler CreateHandler(IUnityContainer container)
4 {
5 return new ExceptionLoggerCallHandler();
6 }
7 }

在这个示例中,我们创建一个简单的计算器类。同时为了使用接口拦截功能,我们还需创建一个接口类型,这样才能应用指定的行为:

1   public interface ICalculator
2 {
3 [Logger]
4 int Add(int first, int second);
5
6 [ExceptionLogger]
7 int Multiply(int first, int second);
8 }

计算器类的实现还和常规的一样。现在我们需要配置Unity容器:

 1       IUnityContainer container = new UnityContainer();
2 container.AddNewExtension<Interception>();
3 container
4 .RegisterType<ICalculator, Calculator>()
5 .Configure<Interception>()
6 .SetInterceptorFor<ICalculator>(new InterfaceInterceptor());
7
8 // Resolve
9 ICalculator calc = container.Resolve<ICalculator>();
10
11 // Call method
12 calc.Add(1, 2);

当在容器上通过调用Resolve方法来尝试获得一个Calculate类的实例时,将会得到一个代理类实例。它的名字可能类似于 ‘DynamicModule.ns.Wrapped_ICalculator_83093f794c8d452e8af4524873a017de’。当调用此包装类的某个方法时,CallHandlers将会被执行。

总结

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

.NET中使用unity实现aop的更多相关文章

  1. 20181122_C#中AOP_使用Unity实现AOP

    一.   使用Unity的AOP实现 a)         整体项目截图: b) 添加Unity的Nuget包, 直接使用最新版就行, 需要添加两个 Unity 和 Unity.Interceptio ...

  2. 运用Unity实现AOP拦截器

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

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

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

  4. Ioc 之 Unity的AOP功能

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

  5. Castle框架中的IOC和AOP机制

    反转控制(IOC)和面向切面编程(AOP)技术作为当前比较流行的技术,其优势已受到广泛关注,但是这两项新技术在实际项目上的应用研究却很落后,而且在.NET平台下实现这两项技术没有形成可以广泛套用的框架 ...

  6. 从Profile中窥探Unity的内存管理

    刨根问底U3D---从Profile中窥探Unity的内存管理 这篇文章包含哪些内容 这篇文章从Unity的Profile组件入手,来探讨一下Unity在开发环境和正式环境中的内存使用发面的一些区别, ...

  7. 在C#中使用CastleDynamicProxy 实现AOP

      原文链接:Aspect Oriented Programming (AOP) in C# using CastleDynamicProxy 本文主要展示在C#中如何使用Castle Dynamic ...

  8. MVC中使用Unity Ioc Container

    ASP.NET MVC中使用Unity Ioc Container   写在前面 安装Unity 添加服务层 IArticleRepository类型映射 服务注入到控制器 Global.asax初始 ...

  9. ASP.NET MVC中使用Unity进行依赖注入的三种方式

    在ASP.NET MVC中使用Unity进行依赖注入的三种方式 2013-12-15 21:07 by 小白哥哥, 146 阅读, 0 评论, 收藏, 编辑 在ASP.NET MVC4中,为了在解开C ...

随机推荐

  1. AE编码、稀疏编码(待续)

    http://ufldl.stanford.edu/tutorial/unsupervised/SparseCoding/

  2. Linux服务器运行环境搭建(二)——Redis数据库安装

    官网地址:http://redis.io/ 官网下载地址:http://redis.io/download 1. 下载Redis源码(tar.gz),并上传到Linux 2. 解压缩包:tar zxv ...

  3. 关于dyld: Library not loaded

    在接入智凡迪的sdk过程中,遇到以下问题: dyld: Library not loaded: @rpath/SDKFramework.framework/SDKFramework   Referen ...

  4. 新的开源java反汇编程序Procyon

    wiki:https://bitbucket.org/mstrobel/procyon/wiki/Java%20Decompiler 由于jd好多年没更新了,今天找到这个新的开源反汇编,很不错 分享一 ...

  5. 剑指offer第七章&第八章

    剑指offer第七章&第八章 1.把字符串转换成整数 将一个字符串转换成一个整数,要求不能使用字符串转换整数的库函数. 数值为0或者字符串不是一个合法的数值则返回0 输入描述: 输入一个字符串 ...

  6. python笔记-10(socket提升、paramiko、线程、进程、协程、同步IO、异步IO)

    一.socket提升 1.熟悉socket.socket()中的省略部分 socket.socket(AF.INET,socket.SOCK_STREAM) 2.send与recv发送大文件时对于黏包 ...

  7. 20165222 实验三 敏捷开发与XP实践

    实验内容: 1.XP基础 2.XP核心实践 3.相关工具 二.具体实验内容 (一)代码规范格式化 总结:感觉就那个Code->Reformate Code代码重新格式化最好用,其他的我都点了下, ...

  8. 《DSP using MATLAB》示例Example 8.23

    代码: %% ------------------------------------------------------------------------ %% Output Info about ...

  9. 《selenium2 python 自动化测试实战》(18)——自动化测试模型(一)

    线性测试 已经被淘汰了:线性测试就是一个脚本完成一个场景,代码基本没有复用,每一个脚本都要从头开始写——这哪行. 模块化与类库 这个就是分模块:有点类似面系那个对象,把功能(比如登录)单独拿出来,当下 ...

  10. (转)Linux安装SwfTools-0.9.2安装事,在执行make install时报错

    系统:CentOS6.5 安装SwfTools-0.9.2的时候,在执行make install时报错, rm -f /usr/local/share/swftools/swfs/default_vi ...