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)扩展定义.本篇文章将介绍如何使用对象拦截功能来帮助你分离横切关 ...
 
随机推荐
- Hibernate中两种获取Session的方式
			
转自:https://www.jb51.net/article/130309.htm Session:是应用程序与数据库之间的一个会话,是hibernate运作的中心,持久层操作的基础.对象的生命周期 ...
 - 语言学习系列-Scala连接数据库示例
			
Scala语法 预装数据库Mysql,登录用户名密码为:root:root,建立数据库test1,建立数据表emp: package com.ccb.day1 import java.sql.Dr ...
 - 数据库连接  ADO,OLEDB,ODBC,DAO的区别 转载
			
http://blog.csdn.net/ithomer/article/details/6624684 ODBC(Open Database Connectivity,开放数据库互连) 1992年, ...
 - c语言函数参考
			
...
 - E20170414-ms
			
collapse v/n 奔溃,垮台 constraint n 约束,限制 adaptive adj 适应的; 有适应能力的; exhausitive adj. 详尽的; store n 商店,仓 ...
 - 875. Koko Eating Bananas
			
Koko loves to eat bananas. There are N piles of bananas, the i-th pile has piles[i] bananas. The g ...
 - hdoj1272【并查集】
			
因为是第二遍,所以题目也没怎么看,然后一开始的思路就是如果每次输入两个点的时候判断是不是同一个集合,如果同一个就是No,然后就wa了,想想也是,然后瞄了一下题解,还要判连通-真是蠢死了-多个集合都想不 ...
 - python  int对象的方法
			
1.求绝对值 >>> a = -10 >>> a.__abs__() 10 >>> abs(10) 10 2.加法 >>> a ...
 - python __builtins__ help类 (32)
			
32.'help', 接收对象作为参数,更详细地返回该对象的所有属性和方法 class _Helper(builtins.object) | Define the builtin 'help'. | ...
 - C#递归拷贝文件夹下文件以及文件夹
			
public bool CopyOldLabFilesToNewLab(string sourcePath, string savePath) { if (!Directory.Exists(save ...