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. Unity内存存储揭秘

    笔者介绍:姜雪伟,IT公司技术合伙人,IT高级讲师,CSDN社区专家,特邀编辑,畅销书作者,已出版书籍:<手把手教你架构3D游戏引擎>电子工业出版社和<Unity3D实战核心技术详解 ...

  2. EasyPusher/EasyDarwin支持H.265 RTSP/RTP直播推流与分发播放

    前言描述 随着大屏时代和高清时代的到来,人们已经不再满足于VGA.CIF这种小分辨率了,取而代之的是720P.1080P.4K级的视频传输,虽然我们国家的基础带宽一直在上升,但普遍情况下,传输高清视频 ...

  3. OkHttp之BridgeInterceptor简单分析

    在< Okhttp源码简单解析(一) >这篇博客简单分析了Okhttp请求的执行流程,通过该篇博客我们知道OkHttp的核心网络请求中内置"拦截器"发挥了重大作用:本篇 ...

  4. [Linux] find文件查找和grep文件内容查找

    在使用linux时,经常需要进行文件查找.其中查找的命令主要有find和grep.两个命令是有区别的: (1)find命令:根据文件的属性进行查找,如文件名,文件大小,所有者,所属组,是否为空,访问时 ...

  5. IOS开发Block详细用法

    Block简介:       ios4.0系统已开始支持block,在编程过程中,blocks被Obj-C看成是对象,它封装了一段代码,这段代码可以在任何时候执行.Blocks可以作为函数参数或者函数 ...

  6. OPEN(SAP) UI5 学习入门系列之四:更好的入门系列-官方Walkthrough

    好久没有更新了,实在不知道应该写一些什么内容,因为作为入门系列,实际上应该更多的是操作而不是理论,而在UI5 SDK中的EXPLORER里面有着各种控件的用法,所以在这里也没有必要再来一遍,还是看官方 ...

  7. apt-get -f install

    http://zhidao.baidu.com/link?url=tZLEfm1Ycc1pWS67-95fXU596CtwA_1l2pPfzINUTxvOCvWdf3JZsWuZNxsxn0Jv6Om ...

  8. .NET实现CORS跨域

    1.NuGet:Install-Package Microsoft.AspNet.WebApi.Cors 2.Application_Start中增加(包含在#if DEBUG中):GlobalCon ...

  9. wampserver2.5的php.ini位置在wamp\bin\apache\apache2.4.9\bin

    wampserver2.5的php.ini位置在wamp\bin\apache\apache2.4.9\bin php.ini有多个地方,C:\wamp\bin\php\php5.5.12下面有php ...

  10. win10/ubuntu双系统卸载删除ubuntu系统

    1.重启进入boot-设置windows启动项为首选项. 2.删除EFI中ubuntu引导启动项: a.将EFI分区挂载到M盘->(管理员权限)命令行输入:mountvol M: /s b.进入 ...