通过fsharp 使用Enterprise Library Unity

<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">使用Ioc概念的Unity库的优点,简单的说就是进一步解耦系统各组件的依赖关系。客户端代码只需依赖需要使用的接口(服务)就可以快速的进行开发。</span>

1.基本流程,定义类-->配置container-->解析类,并使用-->析构(依策略)

2.注册的类型

注册实例,类似单件模式

注册类型,各种扩展

构造函数类

1.注册时InjectionConstructor声明类型,之前没有经过注册,无法解析;会在生成对象时产生错误。(可以在解析过程时化解)

let container = new UnityContainer()

type TenantStore() =
    interface ITenantStore with
        member this.Msg() = printfn "Hello, it's TenantStore"
    interface IDisposable with
        member this.Dispose() = printfn "TenantStore hase been cleaned"

type ManagementController(st:ITenantStore, _name:string) =
    member this.TStore = st
    member val Name = _name with get, set
    interface IDisposable with
        member this.Dispose() = printfn "Control %A hase been cleaned" this.Name

using(new TenantStore())(fun x ->
    (x:>ITenantStore).Msg())

container.RegisterType<ITenantStore, TenantStore>()
container.RegisterType<ManagementController>(new InjectionConstructor(typeof<ITenantStore>, typeof<string>))

using(container.Resolve<ManagementController>(new ParameterOverride("_name", (box "hello"))))(fun myctrl ->
    printfn "%A" myctrl.TStore)

2.函数中的参数可以在解析过程中(Resolve的过程中)重载。

3.泛型类注册,以参数形式表明注册类,可以在注册时忽略泛型类型,在解析时指定

使用typeof获得类型时会默认用obj替换泛型类,无法产生延时定义的效果。需要改用typedefof来获取带泛型的类型

[参考]http://stackoverflow.com/questions/6783284/how-to-get-generic-type-definition-for-crtp-type

type IMessage<'a> =
    abstract member Send : 'a -> unit

type Message<'a>() =
    interface IMessage<'a> with
        member this.Send(msg:'a) =
            printfn "Send Message %A" msg

//Not work
//container.RegisterType(typeof<IMessage<_>>, typeof<Message<_>>)
container.RegisterType(typedefof<IMessage<_>>, typedefof<Message<_>>)

//观察注册类
container.Registrations |> Seq.iter (fun i -> printfn "Regist Type:%A" i.RegisteredType)

let y = container.Resolve<IMessage<int>>()
y.Send(413)                                     

let z = container.Resolve<IMessage<bool>>()
z.Send(true)     <span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">         </span>

4.属性注入

Fsharp的属性无法直接设为Null值,所以在进行属性注入的过程中需要用到一些技巧

如果是轻量级的对象可以默认给个对象实例做填充物,不过这肯定不是个好办法。

type MyClass() as x=
    let t = new TenantStore() :> ITenantStore
    [<Dependency>]
    member val PProperty: ITenantStore = t with get, set

附加一个null field做填充物。这个实现最接近c#,不过接口多了的话,未整理的零零碎碎的小东西怎么也是桩心事。

type MyClass() as x=
    [<DefaultValue>]
    val mutable t:ITenantStore
    [<Dependency>]
    member val PProperty: ITenantStore = x.t with get, set

其实null不是个好东西,异常之源!fsharp为了摆脱null给出了option的解决方案,这里能用么?我试了一下

type MyClass() as x=
    [<Dependency>]
    member val PProperty: ITenantStore option = None with get, set

结果还真行!漂亮多了不是么?而且绝对没有null的参与。我觉得面向对象的哲学里,所有的对象都应该有一个确定的身份。null只是一个系统遗留产物,少用为好。不过这里也有个缺点。获得PProperty时需要获得背后的值,多了一步。

五种声明周期探索

默认为

0.短时生命周期(Transient LifeTime)

生成不一样的对象

container.RegisterType<ITenantStore, TenantStore>()

let a = container.Resolve<ITenantStore>()
let b = container.Resolve<ITenantStore>()
printfn "Is a eqaul to b: %A" (a.Equals(b))
</pre>false1.容器生命周期(Container LifetimeManger)近似于单件模式<pre name="code" class="plain">container.RegisterType<ITenantStore, TenantStore>(new ContainerControlledLifetimeManager())

let a = container.Resolve<ITenantStore>()
let b = container.Resolve<ITenantStore>()
printfn "Is a eqaul to b: %A" (a.Equals(b))

true

2.层次生命周期(Hierarchical Life Time)

脑补一个树形图

container.RegisterType<ITenantStore, TenantStore>(new HierarchicalLifetimeManager())
let childcontainer = container.CreateChildContainer()

let a = container.Resolve<ITenantStore>()
let b = childcontainer.Resolve<ITenantStore>()
printfn "Is a eqaul to b: %A" (a.Equals(b))

false

3单独解生命周期(PreResolve Life Time)

理解为当多个不同类依赖于同一个类时(资源类),获取该对象时并不会重复解析该类。

一定要为三层以上的对象结构,单层产生不了这样的效果

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"

type ManagementController(st:ITenantStore, _name:string) =
    member this.TStore = st
    member val Name = _name with get, set
    interface IDisposable with
        member this.Dispose() = printfn "Control %A hase been cleaned" this.Name

type ExManagementController(st:ITenantStore, _name:string) =
    member this.TStore = st
    member val Name = _name with get, set
    interface IDisposable with
        member this.Dispose() = printfn "Control %A hase been cleaned" this.Name

type CombineManagement(m1:ManagementController, m2:ExManagementController) =
    member this.M1 = m1
    member this.M2 = m2

//注册
container.RegisterType<ITenantStore, TenantStore>(new PerResolveLifetimeManager())
container.RegisterType<ManagementController>(new InjectionConstructor(typeof<ITenantStore>, "xx"))
container.RegisterType<ExManagementController>(new InjectionConstructor(typeof<ITenantStore>, "yy"))
container.RegisterType<CombineManagement>()
//获取
let o = container.Resolve<CombineManagement>()
printfn "%d,%d" (o.M1.TStore.GetHashCode()) (o.M2.TStore.GetHashCode())

还有线程相关,网络相关,外部控制的生命周期,暂未深究

时间: 2024-11-10 07:02:40

通过fsharp 使用Enterprise Library Unity的相关文章

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

这篇就三种拦截模式进行一下探索. 特性总结   类型 特点 其它 InterfaceInterceptor Innstance 仅单接口 类内部函数互相引用无法引起拦截行为 TransparentProxyInterceptor           Instance 多接口(接口之间能够切换)  MarshalByRef 执行缓慢 接口类型(virtual, non-virtual, or interface) 类内部函数互相引用能够引起拦截行为 VirtualMethodInterceptor

通过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

通过fsharp探索Enterprise Library DataBase 1.2

上一次讲到Enterprise Library中Data Access 模块的配置以及简单SQL语句和存储过程的执行.在探索的过程中应用Fsharp语言和交互环境能够马上看到结果,这感觉真的是非常通透. 1.提高数据库操作的复杂性,加入参数的变化,这一点和ADO的操作没有太多的不同. SQL语句带参数 let sqlStatement = "select top 1 * from OrderList where State like @state" using(defaultDB.Ge

通过fsharp探索Enterprise Library 6 DataBase 1.3 Sqlite

使用Enterprise Library就是为了尽可能少的开发常用组件.数据库在选择的过程中常会面临部署,版权,个人喜好等诸多考量.最佳的处理方法就是添加一层数据抽象层,再切换Enterprise的过程中进行无缝衔接.由于我的笔记本跑的越来越慢,又想尝试一下使用Sqlite所以,就用Sqlite做例子. 我用的是Enterprise Library 6.0原本以为只需要简单的配置就可以进行实验,没想到GitHub上Sqlite提供的Sqlite兼容组件到Enterprise Library 4.

通过Fsharp探索Enterprise Library Exception

Exception怎么生成是一回事,怎么展示又是还有一回事了. Exception Block主要关注的点在于Exception信息的展示.Exception不同于一般的log信息,是系统设计者未考虑的错误情况.当异常出现时,错误的情况,或者暴露一些比較敏感的系统信息.或者将一些不怎么友好的信息显示给一些不怎么友好的客户.这时一个计算机异常就引入了一个客户异常,一个终极异常.所以异常处理的目标就是截断异常,进而恢复系统. 把合理的异常信息显示给相相应的用户. 因此主要的异常处理脉络也出现了.1.

Enterprise Library 5.0 系列教程

1. Microsoft Enterprise Library 5.0 系列教程(一) Caching Application Block (初级) 2. Microsoft Enterprise Library 5.0 系列教程(一) Caching Application Block (高级) 3. Microsoft Enterprise Library 5.0 系列教程(二) Cryptography Application Block (初级) 4. Microsoft Enterpr

Microsoft Enterprise Library 简介与请大家下载Microsoft Enterprise Li

什么是Enterprise Library     Enterprise Library是一组应用程序块(Application Block)的集合.他们是可重用的软件组件,被设计用来帮助开发者面对常用的企业级开发任务.用来解决我们在企业级开发中遇到常见问题,如配置管理.数据访问.缓存管理.记录操作日志.异常管理.加密解密.权限管理等.它是对很多有影响力的软件企业通过多年的开发实践积累下来的技术的整合当.前的版本是2006年1月发布的,基于.NET framework 2.0.这个版本包含了大量

在数据库访问项目中使用微软企业库Enterprise Library,实现多种数据库的支持

在我们开发很多项目中,数据访问都是必不可少的,有的需要访问Oracle.SQLServer.Mysql这些常规的数据库,也有可能访问SQLite.Access,或者一些我们可能不常用的PostgreSQL.IBM DB2.或者国产达梦数据库等等,这些数据库的共同特点是关系型数据库,基本上开发的模型都差不多,不过如果我们基于ADO.NET的基础上进行开发的话,那么各种数据库都有自己不同的数据库操作对象,微软企业库Enterprise Library是基于这些不同数据库的操作做的抽象模型,适合多数据