Ioc 之 Unity的AOP功能
前面我们介绍了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功能的更多相关文章
- C# Unity依赖注入利用Attribute实现AOP功能
使用场景? 很多时候, 我们定义一个功能, 当我们要对这个功能进行扩展的时候, 按照常规的思路, 我们一般都是利用OOP的思想, 在原有的功能上进行扩展. 那么有没有一种东西, 可以实现当我们需要扩展 ...
- 运用Unity实现AOP拦截器
运用Unity实现AOP拦截器[结合异常记录实例] 本篇文章将通过Unity实现Aop异常记录功能:有关Unity依赖注入可以看前两篇文章: 1:运用Unity实现依赖注入[结合简单三层实例] 2:运 ...
- 运用Unity实现AOP拦截器[结合异常记录实例]
本篇文章将通过Unity实现Aop异常记录功能:有关Unity依赖注入可以看前两篇文章: 1:运用Unity实现依赖注入[结合简单三层实例] 2:运用Unity实现依赖注入[有参构造注入] 另早期 ...
- IoC组件Unity再续~根据类型字符串动态生产对象
回到目录 这个根据类型字符串动态去生产一个接口的对象,在实现项目中用途很广,这即省去了配置config文件的麻烦,又使用生产对象变更可配置,你完全可以把这种多态持久化到数据库里或者XML文件里,在使用 ...
- IOC使用Unity 实现依赖注入
转自:http://www.cnblogs.com/techborther/archive/2012/01/06/2313498.html http://www.cnblogs.com/xishuai ...
- ASP.NET MVC IOC之Unity攻略
ASP.NET MVC IOC之Unity攻略 一.你知道IOC与DI吗? 1.IOC(Inversion of Control )——控制反转 即依赖对象不在被依赖模块的类中直接通过new来获取 先 ...
- Spring AOP功能和目标
1.AOP的作用 在OOP中,正是这种分散在各处且与对象核心功能无关的代码(横切代码)的存在,使得模块复用难度增加.AOP则将封装好的对象剖开,找出其中对多个对象产生影响的公共行为,并将其封装为一个可 ...
- 20181122_C#中AOP_使用Unity实现AOP
一. 使用Unity的AOP实现 a) 整体项目截图: b) 添加Unity的Nuget包, 直接使用最新版就行, 需要添加两个 Unity 和 Unity.Interceptio ...
- .NET中使用unity实现aop
Unity是一款知名的依赖注入容器,其支持通过自定义扩展来扩充功能.在Unity软件包内默认包含了一个对象拦截(Interception)扩展定义.本篇文章将介绍如何使用对象拦截功能来帮助你分离横切关 ...
随机推荐
- node npm 总结
是nodejs的软件包管理器,用于node插件管理 npm install <name> [-g] [--save -dev] name:安装模块的名称 -g:全局安装 --save:将保 ...
- centos7 编译安装新版LNMP环境
centos7 编译安装新版LNMP环境 环境版本如下: 1.系统环境:Centos 7 x86_64 2.NGINX:nginx-1.11.3.tar.gz 3.数据库:mariadb-10.0.2 ...
- printf(“%06d\n”,x);
%06d : %是格式化输入接受参数的标记 0格式化命令:结果将用零来填充 6:填充位数 d:代表十进制 数据 printf(“%06d\n”,x); console: 000001 000002 0 ...
- 用deamon打开ISO文件,提示命令行错误!!
用deamon打开ISO文件,提示命令行错误!! 解决方法:(没有关联iso文件)重新卸载deamon,再重新安装,在关联iso文件处打对勾,安装完成后即可用
- CentOS-用户的管理
用户组及配置文件 用户的类型 Linux是一个多用户.多任务的操作系统,如果要使用系统资源,就必须向系统管理员申请一个用户,通过这个用户进入系统,通过建立不同属性的用户实现不同的作用或权限,可以合理利 ...
- 洛谷 - P1801 - 黑匣子 - 对顶堆
这道题是提高+省选-的难度,做出来的话对数据结构题目的理解会增加很多. 可以使用一种叫做对顶堆的东西,对顶堆是在线维护第n小的logn的算法.大概的思路是,假如我们要找的是第n小,我们就维护一个大小为 ...
- bzoj 3594: [Scoi2014]方伯伯的玉米田【二维树状数组+dp】
设f[i][j]为前i棵玉米被拔高了j(因为是单调不降所以前面越高越好,所以每次拔一个前缀),转移是f[i][j]=f[k][l]+1,l<=j,a[k]+l<=a[i]+j,然后用二维树 ...
- 第三章 Python运算符
1.算数运算符 运算符 描述 实例 + 加 - 两个对象相加 a + b 输出结果 31 - 减 - 得到负数或是一个数减去另一个数 a - b 输出结果 * 乘 - 两个数相乘或是返回一个被重复若干 ...
- 屏蔽QQ黄钻官方团队送礼物的方法
按照在网上查到的方法: 登录手机QQ \(\longrightarrow\) 好友动态 \(\longrightarrow\) 个人主页 \(\longrightarrow\) 右上角三道杠 \(\l ...
- 常用JSTL标签
1.判断是否为空 <c:choose> <c:when test="${not empty reportInfo.user_register_orgs.register_o ...