UnityInterception_With_ICallHandler
2021-06-09 15:03
标签:call ons ODB dbase gets 扩展 console 顺序 lazy 应先阅读:《AOP概念,拦截,与UnityInterception基础应用》 https://www.cnblogs.com/xinpingqiyouhe/p/14482213.html 代码基于net472 配置文件(可选) 执行结果 UnityInterception_With_ICallHandler 标签:call ons ODB dbase gets 扩展 console 顺序 lazy 原文地址:https://www.cnblogs.com/xinpingqiyouhe/p/14489705.html/*
* 附着InterfaceInterceptor,并通过ICallHandler处理拦截
*
* 应先阅读:《AOP概念,拦截,与UnityInterception基础应用》
* https://www.cnblogs.com/xinpingqiyouhe/p/14482213.html
*
* 对ICallHandler做了一些抽象和凝练,以及进一步测试和验证。
*
*
* 使用这种方式需要:
* 1、实现ICallHandler作为拦截处理类
* 2、实现抽象HandlerAttribute的特性,并将其标注到要拦截的目标(或其成员)上——用于实例化ICallHandler,同时表明使用这个Handler处理拦截
* 3、为Unity容器配置拦截扩展,以及为目标对象配置拦截器
*
*
* 这种方式可以支持“单次拦截”对“多拦截处理函数”,并按ICallHandler.Order有小到大(支持负数)的顺序执行:
* 比如有两个处理函数CH1、CH2(有序),则实际效果为:CH1前 -> CH2前 -> 真实调用 -> CH2后 -> CH1后
* 【但为Order = 0的永远排在最后!!!】
*
* 另外,如果真实调用发生了未处理异常,不会打断后续处理链,即一切“后”照常执行(下方ExceptionCallHandler);
* 而如果拦截处理链中,想主动【生成】异常,希望打断处理链,参见下方VerificationCallHandler
*
*
* 这里的“多拦截处理函数”实际有两种情况:
* 1、不同的处理函数(通过不同特性进行标注)
* 由于特性的不可重叠,这种是最为合理的——同一个目标想拥有多个处理函数,给他挂上不同特性就好
* 比如下方的ExceptionCallHandler(真实函数抛出异常)和VerificationCallHandler(拦截处理链主动【生成】异常)
*
* 2、相同特性的处理函数
* 由于特性挂在interface上、class上、和各自的member上,都可以正确标识拦截,所以存在同特性多次处理拦截的情况
* 此时若Order相同,则调用顺序为:接口前 -> 接口成员前 -> 类前 -> 类成员前 -> 真实调用 -> 类成员后 -> 类后 -> 接口成员后 -> 接口后
* 例子为下方LogCallHandler
*
*
* 本例使用InterfaceInterceptor类型的拦截器,这种拦截器同样可以拦截对目标的一切访问,但目标必须是个接口。
*/
namespace ConsoleApp2
{
#region 被拦截的接口,与对其实例化的类
[LogInterception(Order = 60, ZiDingYi = "接口")]//特性放在接口上,对内部所有内容(包括属性)均生效
[HandleExceptionInterception(Order = 55)]
public interface IProductDao
{
[LogInterception(Order = 20, ZiDingYi = "接口属性")]//放在成员只对这个成员生效,这里导致处理函数叠加
int Id
{
get;
[VerificationInterception(Order = 15)]//仅处理对Id属性的Set调用
set;
}
[LogInterception(Order = 30, ZiDingYi = "接口方法")]
void Get();
void ThrowExpectionMethod();
}
[LogInterception(Order = 40, ZiDingYi = "类")]//特性放到类上也是OK,同样对内部所有内容生效
public class ProductDao : IProductDao
{
int _id;
[LogInterception(Order = -10, ZiDingYi = "类属性")]//与放在接口成员上效果一致,Order支持负数
public int Id
{
get { return _id; }
set { _id = value; Console.WriteLine("设置了Id属性"); }//本例中赋值为负数时会被VerificationInterception打断,不会执行
}
[LogInterception(Order = 50, ZiDingYi = "类方法")]
public void Get()
{
Console.WriteLine("真实调用");
}
public void ThrowExpectionMethod()
{
Console.WriteLine("真实抛出异常");
throw new Exception("错了");
}
}
#endregion
#region 日志拦截,演示“同Handler多次注册”——Attribute挂哪都有效;Order也有效;以及不设置Order时的顺序
public class LogHandler : ICallHandler
{
public int Order { get; set; }
public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
{
Console.WriteLine($"Log: Order={Order}, {ZiDingYi}_前");//拦截器将输出自定义的语句
var r = getNext()(input, getNext);
Console.WriteLine($"Log: Order={Order}, {ZiDingYi}_后");
return r;
}
//演示自定义参数的使用
public string ZiDingYi { get; set; }
}
//以特性的方式,把拦截处理函数挂到目标上。它与ICallHandler一一对应
public class LogInterceptionAttribute : HandlerAttribute
{
//演示自定义参数
public string ZiDingYi;
public override ICallHandler CreateHandler(IUnityContainer container)
{
//return new LogCallHandler { ZiDingYi = ZiDingYi};//这样就是不为Order赋值,所有Order相同
return new LogHandler { ZiDingYi = ZiDingYi, Order = Order };//不要忘记赋值,Attribute和Handler没有继承关系
}
}
#endregion
#region 异常处理拦截,演示真实函数发生异常的情形——不会打断拦截处理链
public class HandleExceptionHandler : ICallHandler
{
public int Order { get; set; }
public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
{
Console.WriteLine($"Ex: Order={Order}, 前");
var r = getNext()(input, getNext);
if (r.Exception != null)//真实函数发生的未处理异常,它不会打断后续拦截处理链。
{
//这里可以直接获取反射信息
Console.WriteLine($"Ex: Order={Order}, 后。{input.Target}->{input.MethodBase.Name} Exception:{r.Exception.Message}");
}
else
Console.WriteLine($"Ex: Order={Order}, 后");
return r;
}
}
///
xml version="1.0" encoding="utf-8" ?>
configuration>
configSections>
section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Microsoft.Practices.Unity.Configuration"/>
configSections>
unity>
alias alias="MyClass" type="ConsoleApp1.MyClassForProxyInterception, ConsoleApp1"/>
alias alias="MyInterceptionBehavior" type="ConsoleApp1.MyInterceptionBehavior, ConsoleApp1"/>
sectionExtension type="Microsoft.Practices.Unity.InterceptionExtension.Configuration.InterceptionConfigurationExtension, Microsoft.Practices.Unity.Interception.Configuration"/>
container name="MyInterception">
extension type="Interception"/>
register type="MyClass">
interceptor type="TransparentProxyInterceptor"/>
interceptionBehavior name="MyBehavior" type="MyInterceptionBehavior"/>
policyInjection/>
register>
container>
unity>
startup>
supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" />
startup>
configuration>
上一篇:java 单例模式模式实现
下一篇:JAVA基础语法学习
文章标题:UnityInterception_With_ICallHandler
文章链接:http://soscw.com/index.php/essay/92727.html