前面我们介绍了Unity的依赖注入功能,现在来介绍下Unity的AOP功能。AOP是面向切面编程,它能够使我们在不改变现有代码结构的情况下额外的为其添加一些功能。

  我们还是使用配置文件来对类型进行注入

<configuration>
<configSections>
<!--<section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Microsoft.Practices.Unity.Configuration"/>-->
<section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Unity.Configuration"/>
</configSections>
<unity>
<!--<sectionExtension type="Microsoft.Practices.Unity.InterceptionExtension.Configuration.InterceptionConfigurationExtension, Microsoft.Practices.Unity.Interception.Configuration"/>-->
<sectionExtension type="Microsoft.Practices.Unity.InterceptionExtension.Configuration.InterceptionConfigurationExtension, Unity.Interception.Configuration"/>
<containers> <container name="IocContainer">
<!-- 格式:类名,程序集名称 -->
<register type="IocDemo.IService.IPay, IocDemo.IService" mapTo="IocDemo.Service.WeChatPay, IocDemo.Service"/>
<register type="IocDemo.IService.IOrder,IocDemo.IService" mapTo="IocDemo.Service.Order,IocDemo.Service">
<lifetime type="transient" />
<constructor>
<!--<param name="id" type="System.Int32" value="" />-->
<!--<param name="iPay" type="IocDemo.IService.IPay,IocDemo.IService"></param>-->
</constructor>
</register> </container> </containers>
</unity>
</configuration>

  接着先来看一下代码方式怎么实现AOP功能。

namespace IocDemo.Aop
{
#region 特性对应的行为
public class UserCallHandler : ICallHandler
{
public int Order { get; set; }
public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
{
Console.WriteLine("参数检测无误");
IMethodReturn methodReturn = getNext()(input, getNext); //getNext.Invoke().Invoke(input, getNext);
return methodReturn;
}
} public class LogCallHandler : ICallHandler
{
public int Order { get; set; }
public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
{
Console.WriteLine("日志已记录,Message:{0},CreateTime:{1}", "测试LogHandler", DateTime.Now);
return getNext()(input, getNext);
}
} public class ExceptionCallHandler : ICallHandler
{
public int Order { get; set; }
public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
{
IMethodReturn methodReturn = getNext()(input, getNext);
if (methodReturn.Exception == null)
{
Console.WriteLine("无异常");
}
else
{
Console.WriteLine("异常:{0}", methodReturn.Exception.Message);
}
return methodReturn;
}
} public class AfterLogCallHandler : ICallHandler
{
public int Order { get; set; }
public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
{
IMethodReturn methodReturn = getNext()(input, getNext);
Console.WriteLine("完成日志,Message:{0},CreateTime:{1},计算结果{2}", "测试LogHandler", DateTime.Now, methodReturn.ReturnValue);
return methodReturn;
}
}
#endregion 特性对应的行为 #region 特性
public class UserHandlerAttribute : HandlerAttribute
{
public override ICallHandler CreateHandler(IUnityContainer container)
{
ICallHandler handler = new UserCallHandler() { Order = this.Order };
return handler;
}
} public class LogHandlerAttribute : HandlerAttribute
{
public override ICallHandler CreateHandler(IUnityContainer container)
{
return new LogCallHandler() { Order = this.Order };
}
} public class ExceptionHandlerAttribute : HandlerAttribute
{
public override ICallHandler CreateHandler(IUnityContainer container)
{
return new ExceptionCallHandler() { Order = this.Order };
}
} public class AfterLogHandlerAttribute : HandlerAttribute
{
public override ICallHandler CreateHandler(IUnityContainer container)
{
return new AfterLogCallHandler() { Order = this.Order };
}
}
#endregion 特性
}
namespace IocDemo.IService
{
[UserHandler(Order = )]
[LogHandler(Order = )]
[AfterLogHandler]
[ExceptionHandler]
public interface IOrder
{
string ToPay();
}
}

在代码中使用 container.AddNewExtension 加入AOP

ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap();
fileMap.ExeConfigFilename = Path.Combine(AppDomain.CurrentDomain.BaseDirectory + "Config\\Unity.Config");//找配置文件的路径
Configuration configuration = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);
UnityConfigurationSection section = (UnityConfigurationSection)configuration.GetSection(UnityConfigurationSection.SectionName); IUnityContainer container = new UnityContainer();
section.Configure(container, "IocContainer"); container.AddNewExtension<Interception>().Configure<Interception>().SetInterceptorFor<IOrder>(new InterfaceInterceptor()); IOrder order = container.Resolve<IOrder>();
Console.WriteLine(order.ToPay());
Console.ReadLine();

运行结果:

  可以看到,使用代码方式实现AOP要编写的代码很多,需要编写继承 Unity.Interception.PolicyInjection.Policies.HandlerAttribute的属性,重写CreateHandler方法,该方法需要返回一个ICallHandler对象,然后需要将继承HandlerAttribute属性的attribute加在需要拦截的接口上面,调用的时候就会命中ICallHandler里面的Invoke方法。

  标记Attribute的方式有三种,一般使用第3种方式:

  1、TransparentProxyInterceptor:直接在类的方法上进行标记,但是这个类必须继承MarshalByRefObject...不建议用
  2、VirtualMethod:直接在类的方法上进行标记,但这个方法必须是虚方法(就是方法要带virtual关键字)
  3、InterfaceInterceptor:在接口的方法上进行标记,这样继承这个接口的类里实现这个接口方法的方法就能被拦截

  最后,让我们来看一下配置文件怎么配置AOP。

 <container name="IocContainer">
<!-- 格式:类名,程序集名称 -->
<register type="IocDemo.IService.IPay, IocDemo.IService" mapTo="IocDemo.Service.WeChatPay, IocDemo.Service"/>
<register type="IocDemo.IService.IOrder,IocDemo.IService" mapTo="IocDemo.Service.Order,IocDemo.Service">
<interceptor type="InterfaceInterceptor"/>
<interceptionBehavior type="IocDemo.Aop.LogBehavior, IocDemo.Aop"/>
</register> </container>

定义一个实现IInterceptionBehavior的LogBehavior类

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Unity.Interception.InterceptionBehaviors;
using Unity.Interception.PolicyInjection.Pipeline; namespace IocDemo.Aop
{
public class LogBehavior : IInterceptionBehavior
{
public IEnumerable<Type> GetRequiredInterfaces()
{
return Type.EmptyTypes;
} public IMethodReturn Invoke(IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext)
{
Console.WriteLine("LogBehavior before");
IMethodReturn method = getNext()(input, getNext);
Console.WriteLine("LogBehavior after");
return method;
} public bool WillExecute
{
get { return true; }
}
}
}

代码中调用

ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap();
fileMap.ExeConfigFilename = Path.Combine(AppDomain.CurrentDomain.BaseDirectory + "Config\\unity.config");//找配置文件的路径
Configuration configuration = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);
UnityConfigurationSection section = (UnityConfigurationSection)configuration.GetSection(UnityConfigurationSection.SectionName); IUnityContainer container = new UnityContainer();
section.Configure(container, "IocContainer"); //被拦截
/*
实现Unity.Interception.InterceptionBehaviors.IInterceptionBehavior接口,进入Invoke方法
*/
IOrder order = container.Resolve<IOrder>();
Console.WriteLine(order.ToPay());
Console.ReadLine();

运行结果可以看到,在调用ToPay之前进入了LogBehavior的Invoke方法

  可见使用配置文件的方式实现AOP比代码方式实现简单很多。需要注意的是,再引用Unity的时候需要注意Unity和Unity.Interception版本的问题,笔者在这个版本问题上调试了很久才找到匹配的版本。

Ioc 之 Unity的AOP功能的更多相关文章

  1. C# Unity依赖注入利用Attribute实现AOP功能

    使用场景? 很多时候, 我们定义一个功能, 当我们要对这个功能进行扩展的时候, 按照常规的思路, 我们一般都是利用OOP的思想, 在原有的功能上进行扩展. 那么有没有一种东西, 可以实现当我们需要扩展 ...

  2. 运用Unity实现AOP拦截器

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

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

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

  4. IoC组件Unity再续~根据类型字符串动态生产对象

    回到目录 这个根据类型字符串动态去生产一个接口的对象,在实现项目中用途很广,这即省去了配置config文件的麻烦,又使用生产对象变更可配置,你完全可以把这种多态持久化到数据库里或者XML文件里,在使用 ...

  5. IOC使用Unity 实现依赖注入

    转自:http://www.cnblogs.com/techborther/archive/2012/01/06/2313498.html http://www.cnblogs.com/xishuai ...

  6. ASP.NET MVC IOC之Unity攻略

    ASP.NET MVC IOC之Unity攻略 一.你知道IOC与DI吗? 1.IOC(Inversion of Control )——控制反转 即依赖对象不在被依赖模块的类中直接通过new来获取 先 ...

  7. Spring AOP功能和目标

    1.AOP的作用 在OOP中,正是这种分散在各处且与对象核心功能无关的代码(横切代码)的存在,使得模块复用难度增加.AOP则将封装好的对象剖开,找出其中对多个对象产生影响的公共行为,并将其封装为一个可 ...

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

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

  9. .NET中使用unity实现aop

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

随机推荐

  1. .NETFramework:Regex

    ylbtech-.NETFramework:Regex 1.返回顶部 1. #region 程序集 System, Version=4.0.0.0, Culture=neutral, PublicKe ...

  2. background-clip与background-origin

    规定背景的绘制区域 浏览器支持 IE9+.Firefox.Opera.Chrome 以及 Safari 支持 background-clip 属性. 注释:Internet Explorer 8 以及 ...

  3. 010-- 开发脚本自动部署nginx_web和nfs及监控内存

    1.编写脚本自动部署反向代理.web.nfs: #!/bin/bash #检测安装nginx function detection_nginx(){ if [ -f /etc/nginx/nginx. ...

  4. FTP相关内容

    FTP相关介绍 FTP 1)File Transfer Protocol ( FTP ) 是相当古老的网络协议之一,他最主要的功能就是进行 Server端与 Client 端之间的档案传送的功能.这个 ...

  5. angular源码剖析之Provider系列--QProvider

    QProvider 简介 源码里是这么描述的: A service that helps you run functions asynchronously, and use their return ...

  6. ASP.NET Core Web API + Angular 仿B站(一) 目的分析以及创建 WebAPI + Angular7 项目

    前言: 本系列文章主要为对所学 Angular 框架的一次微小的实践,对 b站页面作简单的模仿. 本系列文章主要参考资料: 微软文档: https://docs.microsoft.com/zh-cn ...

  7. bzoj 1207: [HNOI2004]打鼹鼠【dp】

    跟简单的dp,设f[i]表示前i只最多打几只,因为起点不确定,所以f[i]可以从任意abs(x[i]-x[j])+abs(y[i]-y[j])<=abs(time[i]-time[j])的j&l ...

  8. vlc media player

    还是很好用的目前来看 倍速播放: [      减速播放 ]      加速播放 =     恢复原速度

  9. nginx命令介绍

    [root@webmaster nginx]# ./sbin/nginx -h nginx version: nginx/1.12.2 Usage: nginx [-?hvVtTq] [-s sign ...

  10. Linux 命令与学习

    2014-10-10 ps -ef|grep ***   可以查找包含***名称的进程 netstat -ntlp       查看端口占用 kill -9 pid           强制杀死进程 ...