• 通过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:WorkHellfsharp-practiseEnterpriseLibraryUnityProgram.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 失败   和料想的一致

    以上
  • 相关阅读:
    Search in Rotated Sorted Array
    排序
    Find Peak Element
    Search a 2D Matrix II
    Search a 2D Matrix
    Search for a Range
    nodejs编译sass模块包 node-compass,与gulp包gulp-sass使用方法
    canvas基础学习
    决定整理一下canvas的基础学习
    网页宽高clientWidth clientHeight获得数值不对的问题
  • 原文地址:https://www.cnblogs.com/jzssuanfa/p/6820275.html
Copyright © 2020-2023  润新知