2 people like it.
Like the snippet!
Parametric Dependency Injection
This is a simple IoC implementation that allows registration with optional parametrization.
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
|
type Mode = Singleton | Factory
type private DependencyContainer<'T> () =
// this implementation does not account for thread safety
// a good way to go would be to wrap the container map
// in an atom structure like the one in http://fssnip.net/bw
static let container : Map<string option, unit -> 'T> ref = ref Map.empty
static let t = typeof<'T>
static let morph mode (f : unit -> 'T) =
match mode with
| Singleton ->
let singleton = lazy(f ())
fun () -> singleton.Value
| Factory -> f
static member Register (mode, factory : unit -> 'T, param) =
if (!container).ContainsKey param then
match param with
| None -> failwithf "IoC : instance of type %s has already been registered" t.Name
| Some param -> failwithf "IoC : instance of type %s with parameter \"%s\" has already been registered" t.Name param
else container := (!container).Add(param, morph mode factory)
static member IsRegistered param = (!container).ContainsKey param
static member TryResolve param =
match (!container).TryFind param with
| None -> None
| Some f ->
try Some <| f ()
with e ->
match param with
| None -> failwithf "IoC : factory method for type %s has thrown an exception:\n %s" t.Name <| e.ToString()
| Some param ->
failwithf "IoC : factory method for type %s with parameter \"%s\" has thrown an exception:\n %s" t.Name param <| e.ToString()
static member Resolve param =
match DependencyContainer<'T>.TryResolve param with
| Some v -> v
| None ->
match param with
| None -> failwithf "IoC : no instace of type %s has been registered" t.Name
| Some param -> failwithf "IoC : no instance of type %s with parameter \"%s\" has been registered" t.Name param
type IoC =
static member Register<'T> (mode, factory, ?param) = DependencyContainer<'T>.Register(mode, factory, param)
static member RegisterValue<'T> (value, ?param) = DependencyContainer<'T>.Register(Factory, (fun () -> value), param)
static member TryResolve<'T> ?param = DependencyContainer<'T>.TryResolve param
static member Resolve<'T> ?param = DependencyContainer<'T>.Resolve param
static member IsRegistered<'T> ?param = DependencyContainer<'T>.IsRegistered param
// example
type IAnimal =
abstract Name : string
type Cat(name) =
member __.Purr() = printfn "purrr"
interface IAnimal with
member __.Name = name
IoC.Register<IAnimal>(Singleton, fun () -> new Cat("Mr. Bungle") :> IAnimal)
IoC.RegisterValue<IAnimal>( { new IAnimal with member __.Name = "Eirik" }, "me")
let cat = IoC.Resolve<IAnimal>() :?> Cat
let me = IoC.Resolve<IAnimal> "me"
cat.Purr()
me.Name
IoC.RegisterValue(42, "magic number")
IoC.Resolve<int> "magic number"
|
union case Mode.Singleton: Mode
union case Mode.Factory: Mode
Multiple items
type private DependencyContainer<'T> =
new : unit -> DependencyContainer<'T>
static member IsRegistered : param:string option -> bool
static member Register : mode:Mode * factory:(unit -> 'T) * param:string option -> unit
static member Resolve : param:string option -> 'T
static member TryResolve : param:string option -> 'T option
Full name: Script.DependencyContainer<_>
--------------------
private new : unit -> DependencyContainer<'T>
val container : Map<string option,(unit -> 'T)> ref
Multiple items
module Map
from Microsoft.FSharp.Collections
--------------------
type Map<'Key,'Value (requires comparison)> =
interface IEnumerable
interface IComparable
interface IEnumerable<KeyValuePair<'Key,'Value>>
interface ICollection<KeyValuePair<'Key,'Value>>
interface IDictionary<'Key,'Value>
new : elements:seq<'Key * 'Value> -> Map<'Key,'Value>
member Add : key:'Key * value:'Value -> Map<'Key,'Value>
member ContainsKey : key:'Key -> bool
override Equals : obj -> bool
member Remove : key:'Key -> Map<'Key,'Value>
...
Full name: Microsoft.FSharp.Collections.Map<_,_>
--------------------
new : elements:seq<'Key * 'Value> -> Map<'Key,'Value>
Multiple items
val string : value:'T -> string
Full name: Microsoft.FSharp.Core.Operators.string
--------------------
type string = System.String
Full name: Microsoft.FSharp.Core.string
type 'T option = Option<'T>
Full name: Microsoft.FSharp.Core.option<_>
type unit = Unit
Full name: Microsoft.FSharp.Core.unit
Multiple items
val ref : value:'T -> 'T ref
Full name: Microsoft.FSharp.Core.Operators.ref
--------------------
type 'T ref = Ref<'T>
Full name: Microsoft.FSharp.Core.ref<_>
val empty<'Key,'T (requires comparison)> : Map<'Key,'T> (requires comparison)
Full name: Microsoft.FSharp.Collections.Map.empty
val t : System.Type
val typeof<'T> : System.Type
Full name: Microsoft.FSharp.Core.Operators.typeof
val morph : (Mode -> (unit -> 'T) -> unit -> 'T)
val mode : Mode
val f : (unit -> 'T)
val singleton : Lazy<'T>
property System.Lazy.Value: 'T
static member private DependencyContainer.Register : mode:Mode * factory:(unit -> 'T) * param:string option -> unit
Full name: Script.DependencyContainer`1.Register
val factory : (unit -> 'T)
val param : string option
union case Option.None: Option<'T>
val failwithf : format:Printf.StringFormat<'T,'Result> -> 'T
Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.failwithf
property System.Reflection.MemberInfo.Name: string
union case Option.Some: Value: 'T -> Option<'T>
val param : string
static member private DependencyContainer.IsRegistered : param:string option -> bool
Full name: Script.DependencyContainer`1.IsRegistered
static member private DependencyContainer.TryResolve : param:string option -> 'T option
Full name: Script.DependencyContainer`1.TryResolve
val e : exn
System.Exception.ToString() : string
static member private DependencyContainer.Resolve : param:string option -> 'T
Full name: Script.DependencyContainer`1.Resolve
val v : 'T
type IoC =
static member IsRegistered : ?param:string -> bool
static member Register : mode:Mode * factory:(unit -> 'T) * ?param:string -> unit
static member RegisterValue : value:'T * ?param:string -> unit
static member Resolve : ?param:string -> 'T
static member TryResolve : ?param:string -> 'T option
Full name: Script.IoC
static member IoC.Register : mode:Mode * factory:(unit -> 'T) * ?param:string -> unit
Full name: Script.IoC.Register
static member IoC.RegisterValue : value:'T * ?param:string -> unit
Full name: Script.IoC.RegisterValue
val value : 'T
static member IoC.TryResolve : ?param:string -> 'T option
Full name: Script.IoC.TryResolve
static member IoC.Resolve : ?param:string -> 'T
Full name: Script.IoC.Resolve
static member IoC.IsRegistered : ?param:string -> bool
Full name: Script.IoC.IsRegistered
type IAnimal =
interface
abstract member Name : string
end
Full name: Script.IAnimal
abstract member IAnimal.Name : string
Full name: Script.IAnimal.Name
Multiple items
type Cat =
interface IAnimal
new : name:string -> Cat
member Purr : unit -> unit
Full name: Script.Cat
--------------------
new : name:string -> Cat
val name : string
member Cat.Purr : unit -> unit
Full name: Script.Cat.Purr
val printfn : format:Printf.TextWriterFormat<'T> -> 'T
Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.printfn
val __ : Cat
override Cat.Name : string
Full name: Script.Cat.Name
static member IoC.Register : mode:Mode * factory:(unit -> 'T) * ?param:string -> unit
static member IoC.RegisterValue : value:'T * ?param:string -> unit
val cat : Cat
Full name: Script.cat
static member IoC.Resolve : ?param:string -> 'T
val me : IAnimal
Full name: Script.me
member Cat.Purr : unit -> unit
property IAnimal.Name: string
Multiple items
val int : value:'T -> int (requires member op_Explicit)
Full name: Microsoft.FSharp.Core.Operators.int
--------------------
type int = int32
Full name: Microsoft.FSharp.Core.int
--------------------
type int<'Measure> = int
Full name: Microsoft.FSharp.Core.int<_>
More information