通过fsharp 使用Enterprise Library Unity 3 - 三种拦截模式的探索
这篇就三种拦截模式进行一下探索。
特性总结
| 类型 | 特点 | 其它 | |
| InterfaceInterceptor | Innstance | 仅单接口 | 类内部函数互相引用无法引起拦截行为 |
| TransparentProxyInterceptor | Instance | 多接口(接口之间能够切换) MarshalByRef 执行缓慢 接口类型(virtual, non-virtual, or interface) | 类内部函数互相引用能够引起拦截行为 |
| VirtualMethodInterceptor | Type | 多接口 不能用在已有对象上,接口函数必须为virtual | 类内部函数互相引用也能引起拦截行为 |
回顾一下类的声明。两个接口,一个实现。
fsharp实现接口函数的方法与csharp并不全然一致,会造成一些实现上的困扰,这在后面会提到。
type ITenantStore =
abstract member Msg : unit->unit type TenantStore() as x=
//do printfn "new TenantStore %A" (x.GetHashCode())
interface ITenantStore with
member this.Msg() = printfn "Hello, it's TenantStore"
interface IDisposable with
member this.Dispose() = printfn "TenantStore hase been cleaned"
以下进行一些測试。
let showregistrations (container:UnityContainer) =
container.Registrations |> Seq.iter (fun i -> printfn "Regist Type:%A" i.RegisteredType) using(new UnityContainer())(fun ctner->
ctner.AddNewExtension<Interception>() |> ignore
ctner.RegisterType<ITenantStore, TenantStore>(new Interceptor<TransparentProxyInterceptor>(),//兴许对此注入策略进行切换
new InterceptionBehavior<LogingInterceptionBehavior>()) |> ignore
showregistrations ctner
let t = ctner.Resolve<ITenantStore>()
t.Msg())
showregistrations 显示已注冊的类型。用来展示注冊内部的信息。另外,在交互式代码中使用using相较于use更为的合适,FSI声明的对象的生命周期是全局的,在做试验的时候无法控制container。重复清环境不太方便。
TransparentProxyInterceptor的结果
Regist Type:Microsoft.Practices.Unity.IUnityContainer
Regist Type:Microsoft.Practices.Unity.InterceptionExtension.InjectionPolicy
Regist Type:FSI_0002+ITenantStore
From the logging interceptor: "Invoke method System.Type GetType():System.Object at 16:20:45"
From the logging interceptor: "Method System.Type GetType():System.Object returned FSI_0002+TenantStore at 16:20:45"
From the logging interceptor: "Invoke method Void Msg():FSI_0002+ITenantStore at 16:20:45"
Hello, it's TenantStore
From the logging interceptor: "Method Void Msg():FSI_0002+ITenantStore returned at 16:20:45"
val it : unit = ()
InterfaceInterceptor的结果
Regist Type:Microsoft.Practices.Unity.IUnityContainer
Regist Type:Microsoft.Practices.Unity.InterceptionExtension.InjectionPolicy
Regist Type:FSI_0002+ITenantStore
From the logging interceptor: "Invoke method Void Msg():FSI_0002+ITenantStore at 16:22:54"
Hello, it's TenantStore
From the logging interceptor: "Method Void Msg():FSI_0002+ITenantStore returned at 16:22:54"
val it : unit = ()
尽管对象有两个接口,IDiposable接口和ITenantStore接口。拦截仍然成功了,所以支持多对象指的是接口之间的切换,并不是不支持实现多对象的类。
VirtualMethodInterceptor的结果
Regist Type:Microsoft.Practices.Unity.IUnityContainer
Regist Type:Microsoft.Practices.Unity.InterceptionExtension.InjectionPolicy
Regist Type:FSI_0002+ITenantStore
Hello, it's TenantStore
val it : unit = ()
拦截失败。 研究后发觉是由于Fsharp中并不直接支持Virtual方法,Fsharp实现接口成员,默觉得显示(explicit)实现,想要申明Virtual方法须要一些技巧。
可參考http://cs.hubfs.net/topic/None/73936
再定义一个測试类来试试VirtualMethodInterceptor。
type testClass() =
abstract member Test : unit -> unit
default x.Test() =
printfn "hello " using(new UnityContainer())(fun ctner->
ctner.AddNewExtension<Interception>() |> ignore
ctner.RegisterType<testClass>(new Interceptor<VirtualMethodInterceptor>(),
new InterceptionBehavior<LogingInterceptionBehavior>()) |> ignore
showregistrations ctner
let t = ctner.Resolve<testClass>()
t.Test()
)
结果
Regist Type:Microsoft.Practices.Unity.IUnityContainer
Regist Type:Microsoft.Practices.Unity.InterceptionExtension.InjectionPolicy
Regist Type:FSI_0002+testClass
From the logging interceptor: "Invoke method Void Test():FSI_0002+testClass at 9:30:27"
hello
From the logging interceptor: "Method Void Test():FSI_0002+testClass returned at 9:30:27"
val it : unit = ()
拦截成功。
以下稍加改写原来的类定义。使接口都以virtural的形式暴露出来
type TenantStore() as x=
//do printfn "new TenantStore %A" (x.GetHashCode())
abstract Msg : unit -> unit
default x.Msg() =
printfn "Hello, it's TenantStore"
abstract Dispose : unit -> unit
default x.Dispose() =
printfn "TenantStore hase been cleaned"
interface ITenantStore with
member x.Msg() = x.Msg()
interface IDisposable with
member x.Dispose() = x.Dispose()
有些繁琐,接口实现的代码能够复用,不幸中的万幸。
以下的样例中我同一时候測试一下多接口之间转换的情况,看看VirtualMethodInterceptor是否也支持多接口。文档上没有明白表明。
測试代码
using(new UnityContainer())(fun ctner->
ctner.AddNewExtension<Interception>() |> ignore
ctner.RegisterType<ITenantStore, TenantStore>(new Interceptor<VirtualMethodInterceptor>(),
new InterceptionBehavior<LogingInterceptionBehavior>()) |> ignore
ctner.RegisterType<testClass>(new Interceptor<VirtualMethodInterceptor>(),
new InterceptionBehavior<LogingInterceptionBehavior>()) |> ignore
showregistrations ctner
let t = ctner.Resolve<ITenantStore>()
t.Msg()
let o = (box t) :? > IDisposable
o.Dispose()
)
TransparentProxyInterceptor
成功 结果
Regist Type:Microsoft.Practices.Unity.IUnityContainer
Regist Type:Microsoft.Practices.Unity.InterceptionExtension.InjectionPolicy
Regist Type:FSI_0002+ITenantStore
From the logging interceptor: "Invoke method System.Type GetType():System.Object at 9:38:47"
From the logging interceptor: "Method System.Type GetType():System.Object returned FSI_0010+TenantStore at 9:38:47"
From the logging interceptor: "Invoke method Void Msg():FSI_0002+ITenantStore at 9:38:47"
Hello, it's TenantStore
From the logging interceptor: "Method Void Msg():FSI_0002+ITenantStore returned at 9:38:47"
From the logging interceptor: "Invoke method System.Type GetType():System.Object at 9:38:47"
From the logging interceptor: "Method System.Type GetType():System.Object returned FSI_0010+TenantStore at 9:38:47"
From the logging interceptor: "Invoke method Void Dispose():System.IDisposable at 9:38:47"
TenantStore hase been cleaned
From the logging interceptor: "Method Void Dispose():System.IDisposable returned at 9:38:47"
val it : unit = ()
InterfaceInterceptor
失败 结果:
Regist Type:Microsoft.Practices.Unity.IUnityContainer
Regist Type:Microsoft.Practices.Unity.InterceptionExtension.InjectionPolicy
Regist Type:FSI_0002+ITenantStore
From the logging interceptor: "Invoke method Void Msg():FSI_0002+ITenantStore at 9:39:44"
Hello, it's TenantStore
From the logging interceptor: "Method Void Msg():FSI_0002+ITenantStore returned at 9:39:44"
System.InvalidCastException: 无法将类型为“DynamicModule.ns.Wrapped_ITenantStore_67632c824c8e42bbad5925d203ac819b”的对象强制转换为类型“System.IDisposable”。
在 FSI_0015.it@149-7.Invoke(UnityContainer ctner) 位置 E:\WorkHell\fsharp-practise\EnterpriseLibraryUnity\Program.fs:行号 157
在 Microsoft.FSharp.Core.Operators.Using[T,TResult](T resource, FSharpFunc`2 action)
在 <StartupCode$FSI_0015>.$FSI_0015.main@()
已因出错而停止
VirtualMethodInterceptor
成功 结果
Regist Type:Microsoft.Practices.Unity.IUnityContainer
Regist Type:Microsoft.Practices.Unity.InterceptionExtension.InjectionPolicy
Regist Type:FSI_0002+ITenantStore
Regist Type:FSI_0002+testClass
From the logging interceptor: "Invoke method Void Msg():FSI_0017+TenantStore at 9:42:01"
Hello, it's TenantStore
From the logging interceptor: "Method Void Msg():FSI_0017+TenantStore returned at 9:42:01"
From the logging interceptor: "Invoke method Void Dispose():FSI_0017+TenantStore at 9:42:01"
TenantStore hase been cleaned
From the logging interceptor: "Method Void Dispose():FSI_0017+TenantStore returned at 9:42:01"
val it : unit = ()
通过结果能够看到TransparentProxyInterceptor在构建的过程中多了一些步骤。翻了一下帮助文档。说这个代理是使用 TransparentProxy/RealProxy infrastructure生成的。因而速度最慢。
而另两个则是通过动态代码生成的(这是什么?反射?)。
这里能够有个小的结论了,InterfaceInterceptor最小巧有用,其它两个或多或少在使用上都要留意一下各自的特性。
再看看可替换性。
(box t) :?> TenantStore
结果
TransparentInterceptor 失败
VirtualMethodInterceptor 成功
InterfaceInterceptor 失败 和料想的一致
以上
通过fsharp 使用Enterprise Library Unity 3 - 三种拦截模式的探索的更多相关文章
- 通过fsharp 使用Enterprise Library Unity 2
接着Depandency Injection继续. 最想做的还是用现成的程序模块对程序进行行为注入.只是不急,在此之前自己写一个接口对象观察一下IInterceptionBehavior接口的功效. ...
- 【Tomcat】Tomcat Connector的三种运行模式【bio、nio、apr】
Tomcat Connector(Tomcat连接器)有bio.nio.apr三种运行模式 bio bio(blocking I/O,阻塞式I/O操作),表示Tomcat使用的是传统的Java I/O ...
- IOS开发之自定义Button(集成三种回调模式)
前面在做东西的时候都用到了storyboard,在今天的代码中就纯手写代码自己用封装个Button.这个Button继承于UIView类,在封装的时候用上啦OC中的三种回调模式:目标动作回调,委托回调 ...
- 云计算的三种服务模式:SaaS/PaaS/IaaS
转载http://blog.chinaunix.net/uid-22414998-id-3141499.html 定义 云计算主要分为三种服务模式,而且这个三层的分法重要是从用户体验的角度出发的: S ...
- DGbroker三种保护模式的切换
1.三种保护模式 – Maximum protection 在Maximum protection下, 可以保证从库和主库数据完全一样,做到zero data loss.事务同时在主从两边提交完成,才 ...
- 虚拟机安装Ubuntu三种网络模式
VMWare提供三种工作模式桥接(bridge).NAT(网络地址转换)和host-only(主机模式). NAT(网络地址转换) 在NAT模式下,虚拟系统需要借助NAT(网络地址转换)功能,通过宿主 ...
- 后勤模块数据源的增量队列(Delta-Queue)三种更新模式(Update Mode)
声明:原创作品,转载时请注明文章来自SAP师太技术博客( 博/客/园www.cnblogs.com):www.cnblogs.com/jiangzhengjun,并以超链接形式标明文章原始出处,否则将 ...
- VMWare提供了三种工作模式上网
VMWare提供了三种工作模式,它们是bridged(桥接模式).NAT(网络地址转换模式)和host-only(主机模式).要想在网络管理和维护中合理应用它们,你就应该先了解一下这三种工作模式. 1 ...
- 《ASP.NET MVC4 WEB编程》学习笔记------Entity Framework的Database First、Model First和Code Only三种开发模式
作者:张博出处:http://yilin.cnblogs.com Entity Framework支持Database First.Model First和Code Only三种开发模式,各模式的开发 ...
随机推荐
- unittest多线程生成报告(BeautifulReport)
前言 selenium多线程跑用例,这个前面一篇已经解决了,如何生成一个测试报告这个是难点,刚好在github上有个大神分享了BeautifulReport,完美的结合起来,就能生成报告了. 环境必备 ...
- ExtJs 滚动条问题
bodyStyle :'overflow-x:visible;overflow-y:scroll', //隐藏水平滚动条 通过这个方法可以显示或隐藏滚动条 var form = new Ext.for ...
- Boolean.valueOf("true")的用法
Boolean.valueOf(a);a为true时返回true不管大小写,a为其他值时都返回false:
- Leetcode 224.基本计算器
基本计算器 实现一个基本的计算器来计算一个简单的字符串表达式的值. 字符串表达式可以包含左括号 ( ,右括号 ),加号 + ,减号 -,非负整数和空格 . 示例 1: 输入: "1 + 1 ...
- php面向对象(设计模式 工厂模式)
//设计模式//单例模式//类的计划生育//让该类在外界无法造成对象//让外界可以造一个对象,做一个静态方法返回对象//在累里面可以通过静态变量控制返回对象只能有一个 //class Cat//{// ...
- UVA674-Coin Change,用动归思想来递推!
674 - Coin Change 题意:有1分,5分,10分,25分,50分共5种硬币,数量不限.给你一个n求有多少种方法凑齐n,注意:d[0]=1; 思路:推了前几组样例,可以发现直接用当前状态累 ...
- Codeforces Round #321 (Div. 2)-A. Kefa and First Steps,暴力水过~~
A. Kefa and First Steps time limit per test 2 seconds memory limit per test 256 megabytes input stan ...
- 什么是Kubernetes?
刚刚进学校实验室,第一次开会导师和小组同学说了n次Kubernetes,从来没听过,一脸懵逼. Kubernetes也有很多人把它叫K8S, 原文链接:http://omerio.com/2015/1 ...
- 【优先级队列】 Holedox Eating
https://www.bnuoj.com/v3/contest_show.php?cid=9154#problem/M [Accepted] #include<iostream> #in ...
- zookeeper学习0
参考文献: 5分钟让你了解 ZooKeeper 的功能和原理 Zookeeper专题——1.分布式事务(a概述) Zookeeper专题——2.分布式锁-基于Zookeeper的分布式锁