通过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”。
   在 [email protected](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>[email protected]()
已因出错而停止

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 失败   和料想的一致

以上

时间: 2024-11-05 19:26:30

通过fsharp 使用Enterprise Library Unity 3 - 三种拦截模式的探索的相关文章

通过fsharp 使用Enterprise Library Unity

<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">使用Ioc概念的Unity库的优点,简单的说就是进一步解耦系统各组件的依赖关系.客户端代码只需依赖需要使用的接口(服务)就可以快速的进行开发.</span> 1.基本流程,定义类-->配置container-->解析类,并使用-->析构(依策略) 2.注册的

通过fsharp 使用Enterprise Library Unity 4 - Policy Interjection

policy interception Interception class拦截器还可以用Policy 以一种更高效的方式进行加载使用.拦截和被拦截对象的关系常见的是一对多,因为被拦截的主要是对象的方法所以有时数量巨大.Policy具有定义匹配模式的功能,所以可以简化这一匹配工作,不用一一添加被拦截对象.匹配的模式有 ? Assembly name ? Namespace ? Type ? Tag attribute ? Custom attribute ? Member name ? Meth

通过fsharp 使用Enterprise Library Unity 2

接着Depandency Injection继续. 最想做的还是用现成的程序模块对程序进行行为注入.只是不急,在此之前自己写一个接口对象观察一下IInterceptionBehavior接口的功效. type LogingInterceptionBehavior() = let WriteLog message = printfn "From the logging interceptor: %A" message interface IInterceptionBehavior wit

unity中三种调用其他脚本函数的方法

第一种,被调用脚本函数为static类型,调用时直接用  脚本名.函数名().很不实用-- 第二种,GameObject.Find("脚本所在物体名").SendMessage("函数名");  此种方法可以调用public和private类型函数 第三种,GameObject.Find("脚本所在物体名").GetComponent<脚本名>().函数名();此种方法只可以调用public类型函数 unity中三种调用其他脚本函数的

Vmware虚拟机三种网络模式用途

为了更深层次的对Vmware虚拟机三种网络模式的理解,http://www.3lian.com/edu/2012/03-29/24049.htm 在网上查一些资料,通过对资料的理解,将此总结如下. 1.Bridged模式 在这种模式下,虚拟网卡和物理网卡同在一个IP网段,能够互相通信,并且能够浏览外网(前提是物理网卡能够浏览外网).它用的是Vmnet 0网络,在这里Vmnet 0网络充当了虚拟交换机的用途. 2.Host Only模式 在这种模式下,虚拟网卡只能和物理网卡进行通信,不能够浏览外网

VMware虚拟机三种工作模式

工作模式 VMWare提供了三种工作模式,它们是bridged(桥接模式).NAT(网络地址转换模式)和host-only(主机模式).要想在网络管理和维护中合理应用它们,就应该先了解一下这三种工作模式. bridged(桥接模式) 在这种模式下,VMWare虚拟出来的操作系统就像是局域网中的一台独立的主机,它可以访问网内任何一台机器.在桥接模式下,你需要手工为虚拟系统配置IP地址.子网掩码,而且还要和宿主机器处于同一网段,这样虚拟系统才能和宿主机器进行通信.同时,由于这个虚拟系统是局域网中的一

后勤模块数据源的增量队列(Delta-Queue)三种更新模式(Update Mode)

声明:原创作品,转载时请注明文章来自SAP师太技术博客:www.cnblogs.com/jiangzhengjun,并以超链接形式标明文章原始出处,否则将追究法律责任!原文链接:http://www.cnblogs.com/jiangzhengjun/p/4296684.html 数据的更新(同步)有三种方式:V1.V2.V3: V1 - Synchronous update,同步更新,数据会立即更新到目的地(如应用数据表Application Tables.增强队列Delta-Queue),数

vsftpd服务程序的三种认证模式

vsftpd服务程序的三种认证模式的配置方法--匿名开放模式.本地用户模式以及虚拟用户模式.了解PAM可插拔认证模块的原理.作用以及实战配置方法,通过实战课程进一步继续学习SELinux服务的配置方法,扩展学习TFTP简单文件传输协议理论及实操课程 文件传输协议 一般来讲,人们将电脑联网的首要需求就是获取资料,而文件传输是其中非常重要的方式之一,21世纪的互联网是由几千万台个人电脑.工作站.小型机.大型机等等不同型号.架构的物理设备共同组成的,即便是个人电脑上也可能会装有诸如Linux.Wind

vmware虚拟机三种网络模式详解_转

原文来自http://note.youdao.com/share/web/file.html?id=236896997b6ffbaa8e0d92eacd13abbf&type=note 由于Linux目前很热门,越来越多的人在学习linux,但是买一台服务放家里来学习,实在是很浪费.那么如何解决这个问题?虚拟机软件是很好的选择,常用的虚拟机软件有vmware workstations和virtual box等.在使用虚拟机软件的时候,很多初学者都会遇到很多问题,而vmware的网络连接问题是大家