Skip to content

Instantly share code, notes, and snippets.

@vietnt
Created September 6, 2011 04:22
Show Gist options
  • Save vietnt/1196575 to your computer and use it in GitHub Desktop.
Save vietnt/1196575 to your computer and use it in GitHub Desktop.
simple ioc
open System
open System.Linq
open System.Collections.Generic
open System.Collections.Concurrent
open Microsoft.FSharp.Collections
open System.Reflection
type Container() =
let _map = new HashMultiMap<Type,Type>(HashIdentity.Structural)
let _activated = new ConcurrentDictionary<Type, obj>()
member x.Add(contract, impl) =
_map.Add(contract, impl)
member x.Add<'A,'B>() =
x.Add(typeof<'A>, typeof<'B>)
member x.New(impl: Type, traces: Stack<Type>) =
let con = impl.GetConstructors().[0]
let ps = con.GetParameters()
let args : obj array = Array.zeroCreate ps.Length
traces.Push(impl)
for i = 0 to ps.Length - 1 do
let pt = ps.[i]
args.[i] <- x.Get (pt.ParameterType, traces)
ignore(traces.Pop())
con.Invoke(args)
member x.InternalGet(impl, traces) =
_activated.GetOrAdd (impl, fun k -> x.New(impl, traces))
member x.GetAll (t, traces) =
let list = _map.FindAll t
[|for tmp in list do
yield x.InternalGet(tmp, traces)|]
member x.Get(contract, traces) =
let list = _map.FindAll contract
match list.IsEmpty with
| true ->
if contract.IsArray
then
let elementType = contract.GetElementType()
let all = x.GetAll(elementType, traces)
all.CastTo(elementType) :> obj
else null
| false -> x.InternalGet(list.Head, traces)
member x.Get(contract) =
x.Get(contract, new Stack<Type>())
member x.Get<'T>() =
x.Get(typeof<'T>) :?> 'T
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment