<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())
还有线程相关,网络相关,外部控制的生命周期,暂未深究