13 people like it.

Mini IoC Container

Minimal Inversion of Control (IoC) Container for Dependency Injection (DI) in under 100 lines of code. Implements the 3 Rs of DI: Register, Resolve, Release. Note: missing thread safety and fluent interface.

  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: 
 77: 
 78: 
 79: 
 80: 
 81: 
 82: 
 83: 
 84: 
 85: 
 86: 
 87: 
 88: 
 89: 
 90: 
 91: 
 92: 
 93: 
 94: 
 95: 
 96: 
 97: 
 98: 
 99: 
100: 
101: 
102: 
103: 
104: 
105: 
106: 
107: 
108: 
109: 
110: 
111: 
112: 
113: 
114: 
115: 
116: 
117: 
118: 
119: 
120: 
121: 
122: 
123: 
124: 
125: 
126: 
127: 
128: 
129: 
130: 
131: 
132: 
133: 
134: 
135: 
136: 
137: 
138: 
139: 
140: 
141: 
142: 
143: 
144: 
145: 
146: 
147: 
148: 
149: 
150: 
151: 
152: 
153: 
154: 
155: 
156: 
157: 
158: 
159: 
160: 
161: 
162: 
163: 
164: 
165: 
166: 
167: 
168: 
169: 
170: 
171: 
172: 
173: 
174: 
175: 
176: 
177: 
178: 
179: 
180: 
181: 
182: 
183: 
184: 
185: 
186: 
187: 
188: 
189: 
190: 
191: 
192: 
193: 
194: 
195: 
196: 
197: 
198: 
199: 
200: 
201: 
202: 
203: 
204: 
205: 
206: 
207: 
208: 
209: 
210: 
211: 
212: 
213: 
214: 
215: 
216: 
217: 
218: 
219: 
220: 
221: 
222: 
223: 
224: 
225: 
226: 
227: 
228: 
229: 
230: 
231: 
232: 
233: 
234: 
235: 
236: 
237: 
238: 
239: 
240: 
241: 
242: 
243: 
244: 
245: 
246: 
247: 
248: 
249: 
250: 
251: 
252: 
253: 
254: 
255: 
256: 
257: 
258: 
259: 
260: 
261: 
262: 
263: 
264: 
265: 
266: 
267: 
268: 
269: 
270: 
271: 
272: 
273: 
274: 
275: 
276: 
277: 
278: 
279: 
280: 
281: 
282: 
283: 
284: 
285: 
286: 
open System
open System.Collections.Generic
open System.Reflection
open Microsoft.FSharp.Reflection

type Message = string
exception TypeResolutionException of Message * Type
type Lifetime = Singleton | Transient
type AbstractType = Type
type ConcreteType = Type
type private Constructor = Reflected of ConcreteType | Factory of (unit -> obj)
let private (|FunType|_|) t =
    if FSharpType.IsFunction t then FSharpType.GetFunctionElements t |> Some
    else None
let private (|SeqType|_|) (t:Type) =
    if t.IsGenericType && t.GetGenericTypeDefinition() = typedefof<IEnumerable<_>>
    then t.GetGenericArguments().[0] |> Some
    else None
let private toOption = function Choice1Of2 x -> Some x | Choice2Of2 _ -> None
/// IoC Container
type Container () as container =
    let catalog = Dictionary<AbstractType, Constructor * Lifetime>()
    let singletons = Dictionary<ConcreteType,obj>()
    let rec tryResolve cs t =
        match catalog.TryGetValue t with
        | true, (Reflected u , lifetime) -> 
            tryObtain u (fun () -> tryReflect cs u) lifetime
        | true, (Factory f, lifetime) -> 
            tryObtain t (fun () -> f() |> Choice1Of2) lifetime
        | false, _ -> 
            tryObtain t (fun () -> tryReflect cs t) Singleton 
    and tryObtain t f lifetime =
        match singletons.TryGetValue t with
        | true, value -> Choice1Of2(value)
        | false, _ ->
            let result = f()
            result |> function Choice1Of2 value -> store t value lifetime | Choice2Of2 _ -> ()
            result
    and store t value = function Singleton -> singletons.Add(t,value) | Transient -> ()
    and tryReflect cs t =
        if cs |> List.exists ((=) t) 
        then Choice2Of2 "Cycle detected"
        else tryConstructors (t::cs) t
    and tryConstructors cs t =
        t.GetConstructors()
        |> Array.sortBy (fun c -> c.GetParameters().Length)
        |> Array.tryPick (tryConstructor cs >> toOption)
        |> function Some value -> Choice1Of2 value | None -> Choice2Of2 "Failed to find matching constructor"
    and tryConstructor cs ci =
        let ps = ci.GetParameters()
        let args = ps |> Array.choose (fun p -> tryResolveArgument cs p.ParameterType |> toOption)
        if args.Length = ps.Length then args |> ci.Invoke |> Choice1Of2
        else Choice2Of2 "Failed to resolve all parameters of constructor"
    and tryResolveArgument cs t =
        match t with
        | FunType(arg,result) when arg = typeof<unit> ->
            FSharpValue.MakeFunction(t,fun args -> container.Resolve(result)) |> Choice1Of2
        | SeqType t ->
            let interfaces = catalog.Keys |> Seq.filter (fun x -> x.GetInterfaces() |> Seq.exists ((=) t))
            let subTypes = catalog.Keys |> Seq.filter (fun x -> x.IsSubclassOf t)
            let values =
                Seq.append interfaces subTypes 
                |> Seq.choose (tryResolve cs >> toOption) 
                |> Seq.toArray
            let result = Array.CreateInstance(t, values.Length)
            Array.Copy(values, result, values.Length)
            result |> box |> Choice1Of2
        | t -> tryResolve cs t
    /// Register sequence of abstract types against specified concrete type
    member container.Register(abstractTypes:AbstractType seq, concreteType:ConcreteType) =
        for t in abstractTypes do catalog.Add(t, (Reflected concreteType, Singleton))
    /// Register abstract type against specified type instance
    member container.Register<'TAbstract>(instance:'TAbstract) =
        catalog.Add(typeof<'TAbstract>, (Reflected typeof<'TAbstract>, Singleton))
        singletons.Add(typeof<'TAbstract>, instance)
    /// Register abstract type against specified concrete type with given lifetime
    member container.Register<'TAbstract when 'TAbstract : not struct>
            (concreteType:ConcreteType, lifetime:Lifetime) =
        let abstractType = typeof<'TAbstract>
        if concreteType <> abstractType &&
           not (concreteType.IsSubclassOf(abstractType)) &&
           not (concreteType.GetInterfaces() |> Array.exists ((=) abstractType)) then
            invalidArg "concreteType" "Concrete type does not implement abstract type"
        catalog.Add(abstractType, (Reflected concreteType, lifetime))
    /// Register abstract type against specified factory with given lifetime
    member container.Register<'TAbstract when 'TAbstract : not struct>
            (f:unit->'TAbstract, lifetime:Lifetime) = 
        catalog.Add(typeof<'TAbstract>, (Factory(f >> box), lifetime))
    /// Resolve instance of specified abstract type
    member container.Resolve<'TAbstract when 'TAbstract : not struct>() =
        container.Resolve(typeof<'TAbstract>) :?> 'TAbstract
    /// Resolve instsance of specified abstract type
    member container.Resolve(abstractType:AbstractType) =
        match tryResolve [] abstractType with
        | Choice1Of2 value -> value
        | Choice2Of2 message -> TypeResolutionException(message,abstractType) |> raise
    /// Remove instance reference from container
    member container.Release(instance:obj) =
        singletons |> Seq.filter (fun pair -> pair.Value = instance) |> Seq.toList
        |> List.iter (fun pair -> singletons.Remove(pair.Key) |> ignore)

open NUnit.Framework

[<TestFixture>]
module ``Container Register, Resolve, Release Tests`` =
    
    [<AbstractClass>]
    type AbstractType () = do ()

    type ConcreteType () = inherit AbstractType()

    type IMarkerInterface = interface end

    type MarkedType () = interface IMarkerInterface
    
    let [<Test>] ``registering 2 instances of an abstract type in a single container should throw`` () =
        let container = Container()
        container.Register<AbstractType>(typeof<AbstractType>, Singleton)
        Assert.Throws<System.ArgumentException>(fun () ->
            container.Register<AbstractType>(typeof<AbstractType>, Singleton) |> ignore
        ) |> ignore

    let [<Test>] ``attempting to resolve an unregistered type should throw`` () =
        let container = Container()
        Assert.Throws<TypeResolutionException>(fun () ->  
            container.Resolve<AbstractType>() |> ignore
        ) |> ignore

    let [<Test>] ``resolving a registered abstract type should return an instance of the specified concrete type`` () =
        let container = Container()
        container.Register<AbstractType>(typeof<ConcreteType>, Singleton)
        let instance = container.Resolve<AbstractType>()
        Assert.True(instance :? ConcreteType)

    let [<Test>] ``resolving a type with a singleton lifetime should always return the same instance`` () =
        let container = Container()
        container.Register<AbstractType>(typeof<ConcreteType>, Singleton)
        let a = container.Resolve<AbstractType>()
        let b = container.Resolve<AbstractType>()
        Assert.True( Object.ReferenceEquals(a,b) )
        
    let [<Test>] ``resolving a type with a transient lifetime should a new instance each time`` () =
        let container = Container()
        container.Register<AbstractType>(typeof<ConcreteType>, Transient)
        let a = container.Resolve<AbstractType>()
        let b = container.Resolve<AbstractType>()
        Assert.AreNotSame(a,b)

    let [<Test>] ``resolving a registered instance of a type should return that instance`` () =
        let container = Container()
        let this = ConcreteType()
        container.Register<AbstractType>(this)
        let that = container.Resolve<AbstractType>()
        Assert.AreSame(this, that)

    let [<Test>] ``resolving a type registered as a factory should call the specified factory`` () =
        let called = ref false
        let factory = fun () -> called := true; ConcreteType() :> AbstractType
        let container = Container()
        container.Register<AbstractType>(factory, Singleton)
        container.Resolve<AbstractType>() |> ignore
        Assert.True( called.Value )

    let [<Test>] ``releasing a registered concrete instance then resolving the type should return a new concrete instance`` () =
        let container = Container()
        let this = ConcreteType()
        container.Register<ConcreteType>(this)
        container.Release(this)
        let that = container.Resolve<ConcreteType>()
        Assert.True( not <| Object.ReferenceEquals(this, that) )

    do
        ``registering 2 instances of an abstract type in a single container should throw`` ()
        ``attempting to resolve an unregistered type should throw`` ()
        ``resolving a registered abstract type should return an instance of the specified concrete type``  ()
        ``resolving a type with a singleton lifetime should always return the same instance`` ()
        ``resolving a type with a transient lifetime should a new instance each time`` ()
        ``resolving a registered instance of a type should return that instance`` ()
        ``resolving a type registered as a factory should call the specified factory`` ()
        ``releasing a registered concrete instance then resolving the type should return a new concrete instance`` ()

[<TestFixture>]
module ``Constructor Tests`` =
    
    [<AbstractClass>]
    type AbstractType () = do ()
   
    type ConstructorWithValueTypeArg (arg:int) = inherit AbstractType()

    let [<Test>] ``resolving type with value type dependency in constructor should throw`` () =
        let container = Container()
        container.Register<AbstractType>(typeof<ConstructorWithValueTypeArg>, Singleton)
        Assert.Throws<TypeResolutionException>(fun () ->
            container.Resolve<AbstractType>() |> ignore
        ) |> ignore

    type ReferenceType() = do ()
    type ConstructorWithReferenceTypeArg (arg:ReferenceType) = inherit AbstractType()

    let [<Test>] ``resolving type with reference type dependency in constructor should inject reference`` () =
        let container = Container()
        container.Register<AbstractType>(typeof<ConstructorWithReferenceTypeArg>, Singleton)
        let instance = container.Resolve<AbstractType>()
        Assert.NotNull(instance)

    type ConstructorWithSelfReferenceArg (arg:AbstractType) = inherit AbstractType()

    let [<Test>] ``resolving type with self type dependency in constructor should fail`` () =
        let container = Container()
        container.Register<AbstractType>(typeof<ConstructorWithSelfReferenceArg>, Singleton)
        Assert.Throws<TypeResolutionException>(fun () ->
                container.Resolve<AbstractType>() |> ignore
        ) |> ignore

    type ConstructorWithFunArg (arg:unit -> ReferenceType) = 
        inherit AbstractType()
        member this.Factory () = arg()

    let [<Test>] ``resolving type with fun type argument in constructor should inject factory`` () =
        let container = Container()
        container.Register<AbstractType>(typeof<ConstructorWithFunArg>, Singleton)
        let instance = container.Resolve<AbstractType>() :?> ConstructorWithFunArg
        let refValue = instance.Factory()
        Assert.NotNull(refValue)

    type SubType1 () = inherit AbstractType()
    type SubType2 () = inherit AbstractType()
    type ConstructorWithSeqArg (subTypes:AbstractType seq) =
        member this.SubTypes = subTypes

    let [<Test>] ``resolving type with seq type argument in constructor should inject sub types`` () =
        let container = Container()
        container.Register<SubType1>(typeof<SubType1>, Singleton)
        container.Register<SubType2>(typeof<SubType2>, Singleton)
        container.Register<ConstructorWithSeqArg>(typeof<ConstructorWithSeqArg>, Singleton)
        let instance = container.Resolve<ConstructorWithSeqArg>()
        let types = instance.SubTypes |> Seq.map (fun i -> i.GetType().Name) |> Set.ofSeq
        let types' = set [ typeof<SubType1>.Name; typeof<SubType2>.Name ]
        Assert.That((types = types'))

    type Marker = interface end
    type MarkedType1 () = interface Marker
    type MarkedType2 () = interface Marker
    type ConstructorWithInterfaceArg (markedTypes:Marker seq) =
        member this.MarkedTypes = markedTypes

    let [<Test>] ``resolving type with seq type argument in constructor should inject interfaces`` () =
        let container = Container()
        container.Register<MarkedType1>(typeof<MarkedType1>, Singleton)
        container.Register<MarkedType2>(typeof<MarkedType2>, Singleton)
        container.Register<ConstructorWithInterfaceArg>(typeof<ConstructorWithInterfaceArg>, Singleton)
        let instance = container.Resolve<ConstructorWithInterfaceArg>()
        let types = instance.MarkedTypes |> Seq.map (fun i -> i.GetType().Name) |> Set.ofSeq
        let types' = set [ typeof<MarkedType1>.Name; typeof<MarkedType2>.Name ]
        Assert.That((types = types'))

    do  ``resolving type with value type dependency in constructor should throw`` ()
        ``resolving type with reference type dependency in constructor should inject reference`` ()
        ``resolving type with self type dependency in constructor should fail`` ()
        ``resolving type with fun type argument in constructor should inject factory`` ()
        ``resolving type with seq type argument in constructor should inject sub types`` ()
        ``resolving type with seq type argument in constructor should inject interfaces`` ()

module Usage =

    type ICalculate =
        abstract member Incr : int -> int

    type Calculator () =
        interface ICalculate with
            member this.Incr(x:int) = x + 1
    
    let container = Container()

    // Register
    container.Register<ICalculate>(typeof<Calculator>, Singleton)

    // Resolve
    let calc = container.Resolve<ICalculate>()
    
    printfn "%d" (calc.Incr 1)
    
    // Release
    container.Release(calc)

    Console.ReadLine() |> ignore
namespace System
namespace System.Collections
namespace System.Collections.Generic
namespace System.Reflection
namespace Microsoft
namespace Microsoft.FSharp
namespace Microsoft.FSharp.Reflection
type Message = string

Full name: Script.Message
Multiple items
val string : value:'T -> string

Full name: Microsoft.FSharp.Core.Operators.string

--------------------
type string = String

Full name: Microsoft.FSharp.Core.string
exception TypeResolutionException of Message * Type

Full name: Script.TypeResolutionException
type Type =
  inherit MemberInfo
  member Assembly : Assembly
  member AssemblyQualifiedName : string
  member Attributes : TypeAttributes
  member BaseType : Type
  member ContainsGenericParameters : bool
  member DeclaringMethod : MethodBase
  member DeclaringType : Type
  member Equals : o:obj -> bool + 1 overload
  member FindInterfaces : filter:TypeFilter * filterCriteria:obj -> Type[]
  member FindMembers : memberType:MemberTypes * bindingAttr:BindingFlags * filter:MemberFilter * filterCriteria:obj -> MemberInfo[]
  ...

Full name: System.Type
type Lifetime =
  | Singleton
  | Transient

Full name: Script.Lifetime
union case Lifetime.Singleton: Lifetime
union case Lifetime.Transient: Lifetime
type AbstractType = Type

Full name: Script.AbstractType
type ConcreteType = Type

Full name: Script.ConcreteType
type private Constructor =
  | Reflected of ConcreteType
  | Factory of (unit -> obj)

Full name: Script.Constructor
union case Constructor.Reflected: ConcreteType -> Constructor
union case Constructor.Factory: (unit -> obj) -> Constructor
type unit = Unit

Full name: Microsoft.FSharp.Core.unit
type obj = Object

Full name: Microsoft.FSharp.Core.obj
val t : Type
type FSharpType =
  static member GetExceptionFields : exceptionType:Type * ?bindingFlags:BindingFlags -> PropertyInfo []
  static member GetFunctionElements : functionType:Type -> Type * Type
  static member GetRecordFields : recordType:Type * ?bindingFlags:BindingFlags -> PropertyInfo []
  static member GetTupleElements : tupleType:Type -> Type []
  static member GetUnionCases : unionType:Type * ?bindingFlags:BindingFlags -> UnionCaseInfo []
  static member IsExceptionRepresentation : exceptionType:Type * ?bindingFlags:BindingFlags -> bool
  static member IsFunction : typ:Type -> bool
  static member IsModule : typ:Type -> bool
  static member IsRecord : typ:Type * ?bindingFlags:BindingFlags -> bool
  static member IsTuple : typ:Type -> bool
  ...

Full name: Microsoft.FSharp.Reflection.FSharpType
static member FSharpType.IsFunction : typ:Type -> bool
static member FSharpType.GetFunctionElements : functionType:Type -> Type * Type
union case Option.Some: Value: 'T -> Option<'T>
union case Option.None: Option<'T>
property Type.IsGenericType: bool
Type.GetGenericTypeDefinition() : Type
val typedefof<'T> : Type

Full name: Microsoft.FSharp.Core.Operators.typedefof
type IEnumerable<'T> =
  member GetEnumerator : unit -> IEnumerator<'T>

Full name: System.Collections.Generic.IEnumerable<_>
Type.GetGenericArguments() : Type []
val private toOption : _arg1:Choice<'a,'b> -> 'a option

Full name: Script.toOption
union case Choice.Choice1Of2: 'T1 -> Choice<'T1,'T2>
val x : 'a
union case Choice.Choice2Of2: 'T2 -> Choice<'T1,'T2>
Multiple items
type Container =
  new : unit -> Container
  member Register : instance:'TAbstract -> unit
  member Register : abstractTypes:seq<AbstractType> * concreteType:ConcreteType -> unit
  member Register : concreteType:ConcreteType * lifetime:Lifetime -> unit
  member Register : f:(unit -> 'TAbstract) * lifetime:Lifetime -> unit (requires reference type)
  member Release : instance:obj -> unit
  member Resolve : unit -> 'TAbstract (requires reference type)
  member Resolve : abstractType:AbstractType -> obj

Full name: Script.Container


 IoC Container


--------------------
new : unit -> Container
val container : Container
val catalog : Dictionary<AbstractType,(Constructor * Lifetime)>
Multiple items
type Dictionary<'TKey,'TValue> =
  new : unit -> Dictionary<'TKey, 'TValue> + 5 overloads
  member Add : key:'TKey * value:'TValue -> unit
  member Clear : unit -> unit
  member Comparer : IEqualityComparer<'TKey>
  member ContainsKey : key:'TKey -> bool
  member ContainsValue : value:'TValue -> bool
  member Count : int
  member GetEnumerator : unit -> Enumerator<'TKey, 'TValue>
  member GetObjectData : info:SerializationInfo * context:StreamingContext -> unit
  member Item : 'TKey -> 'TValue with get, set
  ...
  nested type Enumerator
  nested type KeyCollection
  nested type ValueCollection

Full name: System.Collections.Generic.Dictionary<_,_>

--------------------
Dictionary() : unit
Dictionary(capacity: int) : unit
Dictionary(comparer: IEqualityComparer<'TKey>) : unit
Dictionary(dictionary: IDictionary<'TKey,'TValue>) : unit
Dictionary(capacity: int, comparer: IEqualityComparer<'TKey>) : unit
Dictionary(dictionary: IDictionary<'TKey,'TValue>, comparer: IEqualityComparer<'TKey>) : unit
val singletons : Dictionary<ConcreteType,obj>
val tryResolve : (ConcreteType list -> AbstractType -> Choice<obj,string>)
val cs : ConcreteType list
val t : AbstractType
Dictionary.TryGetValue(key: AbstractType, value: byref<Constructor * Lifetime>) : bool
val u : ConcreteType
val lifetime : Lifetime
val tryObtain : (ConcreteType -> (unit -> Choice<obj,string>) -> Lifetime -> Choice<obj,string>)
val tryReflect : (ConcreteType list -> ConcreteType -> Choice<obj,string>)
val f : (unit -> obj)
val t : ConcreteType
val f : (unit -> Choice<obj,string>)
Dictionary.TryGetValue(key: ConcreteType, value: byref<obj>) : bool
val value : obj
val result : Choice<obj,string>
val store : (ConcreteType -> obj -> Lifetime -> unit)
Dictionary.Add(key: ConcreteType, value: obj) : unit
Multiple items
type List<'T> =
  new : unit -> List<'T> + 2 overloads
  member Add : item:'T -> unit
  member AddRange : collection:IEnumerable<'T> -> unit
  member AsReadOnly : unit -> ReadOnlyCollection<'T>
  member BinarySearch : item:'T -> int + 2 overloads
  member Capacity : int with get, set
  member Clear : unit -> unit
  member Contains : item:'T -> bool
  member ConvertAll<'TOutput> : converter:Converter<'T, 'TOutput> -> List<'TOutput>
  member CopyTo : array:'T[] -> unit + 2 overloads
  ...
  nested type Enumerator

Full name: System.Collections.Generic.List<_>

--------------------
List() : unit
List(capacity: int) : unit
List(collection: IEnumerable<'T>) : unit
val exists : predicate:('T -> bool) -> list:'T list -> bool

Full name: Microsoft.FSharp.Collections.List.exists
val tryConstructors : (ConcreteType list -> ConcreteType -> Choice<obj,string>)
Type.GetConstructors() : ConstructorInfo []
Type.GetConstructors(bindingAttr: BindingFlags) : ConstructorInfo []
type Array =
  member Clone : unit -> obj
  member CopyTo : array:Array * index:int -> unit + 1 overload
  member GetEnumerator : unit -> IEnumerator
  member GetLength : dimension:int -> int
  member GetLongLength : dimension:int -> int64
  member GetLowerBound : dimension:int -> int
  member GetUpperBound : dimension:int -> int
  member GetValue : [<ParamArray>] indices:int[] -> obj + 7 overloads
  member Initialize : unit -> unit
  member IsFixedSize : bool
  ...

Full name: System.Array
val sortBy : projection:('T -> 'Key) -> array:'T [] -> 'T [] (requires comparison)

Full name: Microsoft.FSharp.Collections.Array.sortBy
val c : ConstructorInfo
MethodBase.GetParameters() : ParameterInfo []
val tryPick : chooser:('T -> 'U option) -> array:'T [] -> 'U option

Full name: Microsoft.FSharp.Collections.Array.tryPick
val tryConstructor : (ConcreteType list -> ConstructorInfo -> Choice<obj,string>)
val ci : ConstructorInfo
val ps : ParameterInfo []
val args : obj []
val choose : chooser:('T -> 'U option) -> array:'T [] -> 'U []

Full name: Microsoft.FSharp.Collections.Array.choose
val p : ParameterInfo
val tryResolveArgument : (ConcreteType list -> Type -> Choice<obj,string>)
property ParameterInfo.ParameterType: Type
property Array.Length: int
ConstructorInfo.Invoke(parameters: obj []) : obj
MethodBase.Invoke(obj: obj, parameters: obj []) : obj
ConstructorInfo.Invoke(invokeAttr: BindingFlags, binder: Binder, parameters: obj [], culture: Globalization.CultureInfo) : obj
MethodBase.Invoke(obj: obj, invokeAttr: BindingFlags, binder: Binder, parameters: obj [], culture: Globalization.CultureInfo) : obj
active recognizer FunType: Type -> (Type * Type) option

Full name: Script.( |FunType|_| )
val arg : Type
val result : Type
val typeof<'T> : Type

Full name: Microsoft.FSharp.Core.Operators.typeof
type FSharpValue =
  static member GetExceptionFields : exn:obj * ?bindingFlags:BindingFlags -> obj []
  static member GetRecordField : record:obj * info:PropertyInfo -> obj
  static member GetRecordFields : record:obj * ?bindingFlags:BindingFlags -> obj []
  static member GetTupleField : tuple:obj * index:int -> obj
  static member GetTupleFields : tuple:obj -> obj []
  static member GetUnionFields : value:obj * unionType:Type * ?bindingFlags:BindingFlags -> UnionCaseInfo * obj []
  static member MakeFunction : functionType:Type * implementation:(obj -> obj) -> obj
  static member MakeRecord : recordType:Type * values:obj [] * ?bindingFlags:BindingFlags -> obj
  static member MakeTuple : tupleElements:obj [] * tupleType:Type -> obj
  static member MakeUnion : unionCase:UnionCaseInfo * args:obj [] * ?bindingFlags:BindingFlags -> obj
  ...

Full name: Microsoft.FSharp.Reflection.FSharpValue
static member FSharpValue.MakeFunction : functionType:Type * implementation:(obj -> obj) -> obj
val args : obj
member Container.Resolve : unit -> 'TAbstract (requires reference type)


 Resolve instance of specified abstract type

member Container.Resolve : abstractType:AbstractType -> obj


 Resolve instsance of specified abstract type
active recognizer SeqType: Type -> Type option

Full name: Script.( |SeqType|_| )
val interfaces : seq<AbstractType>
property Dictionary.Keys: Dictionary`2.KeyCollection<AbstractType,(Constructor * Lifetime)>
module Seq

from Microsoft.FSharp.Collections
val filter : predicate:('T -> bool) -> source:seq<'T> -> seq<'T>

Full name: Microsoft.FSharp.Collections.Seq.filter
val x : AbstractType
Type.GetInterfaces() : Type []
val exists : predicate:('T -> bool) -> source:seq<'T> -> bool

Full name: Microsoft.FSharp.Collections.Seq.exists
val subTypes : seq<AbstractType>
Type.IsSubclassOf(c: Type) : bool
val values : obj []
val append : source1:seq<'T> -> source2:seq<'T> -> seq<'T>

Full name: Microsoft.FSharp.Collections.Seq.append
val choose : chooser:('T -> 'U option) -> source:seq<'T> -> seq<'U>

Full name: Microsoft.FSharp.Collections.Seq.choose
val toArray : source:seq<'T> -> 'T []

Full name: Microsoft.FSharp.Collections.Seq.toArray
val result : Array
Array.CreateInstance(elementType: Type, [<ParamArray>] lengths: int64 []) : Array
Array.CreateInstance(elementType: Type, [<ParamArray>] lengths: int []) : Array
Array.CreateInstance(elementType: Type, length: int) : Array
Array.CreateInstance(elementType: Type, lengths: int [], lowerBounds: int []) : Array
Array.CreateInstance(elementType: Type, length1: int, length2: int) : Array
Array.CreateInstance(elementType: Type, length1: int, length2: int, length3: int) : Array
Array.Copy(sourceArray: Array, destinationArray: Array, length: int64) : unit
Array.Copy(sourceArray: Array, destinationArray: Array, length: int) : unit
Array.Copy(sourceArray: Array, sourceIndex: int64, destinationArray: Array, destinationIndex: int64, length: int64) : unit
Array.Copy(sourceArray: Array, sourceIndex: int, destinationArray: Array, destinationIndex: int, length: int) : unit
val box : value:'T -> obj

Full name: Microsoft.FSharp.Core.Operators.box
member Container.Register : abstractTypes:seq<AbstractType> * concreteType:ConcreteType -> unit

Full name: Script.Container.Register


 Register sequence of abstract types against specified concrete type
val abstractTypes : seq<AbstractType>
Multiple items
val seq : sequence:seq<'T> -> seq<'T>

Full name: Microsoft.FSharp.Core.Operators.seq

--------------------
type seq<'T> = IEnumerable<'T>

Full name: Microsoft.FSharp.Collections.seq<_>
val concreteType : ConcreteType
Dictionary.Add(key: AbstractType, value: Constructor * Lifetime) : unit
member Container.Register : instance:'TAbstract -> unit

Full name: Script.Container.Register


 Register abstract type against specified type instance
val instance : 'TAbstract
member Container.Register : concreteType:ConcreteType * lifetime:Lifetime -> unit

Full name: Script.Container.Register


 Register abstract type against specified concrete type with given lifetime
val not : value:bool -> bool

Full name: Microsoft.FSharp.Core.Operators.not
val abstractType : Type
val exists : predicate:('T -> bool) -> array:'T [] -> bool

Full name: Microsoft.FSharp.Collections.Array.exists
val invalidArg : argumentName:string -> message:string -> 'T

Full name: Microsoft.FSharp.Core.Operators.invalidArg
member Container.Register : f:(unit -> 'TAbstract) * lifetime:Lifetime -> unit (requires reference type)

Full name: Script.Container.Register


 Register abstract type against specified factory with given lifetime
val f : (unit -> 'TAbstract) (requires reference type)
member Container.Resolve : unit -> 'TAbstract (requires reference type)

Full name: Script.Container.Resolve


 Resolve instance of specified abstract type
member Container.Resolve : abstractType:AbstractType -> obj

Full name: Script.Container.Resolve


 Resolve instsance of specified abstract type
val abstractType : AbstractType
val message : string
val raise : exn:Exception -> 'T

Full name: Microsoft.FSharp.Core.Operators.raise
member Container.Release : instance:obj -> unit

Full name: Script.Container.Release


 Remove instance reference from container
val instance : obj
val pair : KeyValuePair<ConcreteType,obj>
property KeyValuePair.Value: obj
val toList : source:seq<'T> -> 'T list

Full name: Microsoft.FSharp.Collections.Seq.toList
val iter : action:('T -> unit) -> list:'T list -> unit

Full name: Microsoft.FSharp.Collections.List.iter
Dictionary.Remove(key: ConcreteType) : bool
property KeyValuePair.Key: ConcreteType
val ignore : value:'T -> unit

Full name: Microsoft.FSharp.Core.Operators.ignore
namespace NUnit
namespace NUnit.Framework
Multiple items
type TestFixtureAttribute =
  inherit NUnitAttribute
  new : unit -> TestFixtureAttribute + 1 overload
  member Arguments : obj[] with get, set
  member Author : string with get, set
  member BuildFrom : typeInfo:ITypeInfo -> IEnumerable<TestSuite>
  member Category : string with get, set
  member Description : string with get, set
  member Explicit : bool with get, set
  member Ignore : string with get, set
  member IgnoreReason : string with get, set
  member Properties : IPropertyBag with get, set
  ...

Full name: NUnit.Framework.TestFixtureAttribute

--------------------
TestFixtureAttribute() : unit
TestFixtureAttribute([<ParamArray>] arguments: obj []) : unit
Multiple items
type AbstractClassAttribute =
  inherit Attribute
  new : unit -> AbstractClassAttribute

Full name: Microsoft.FSharp.Core.AbstractClassAttribute

--------------------
new : unit -> AbstractClassAttribute
Multiple items
type AbstractType =
  new : unit -> AbstractType

Full name: Script.Container Register, Resolve, Release Tests.AbstractType

--------------------
new : unit -> Container Register<...>.AbstractType
Multiple items
type ConcreteType =
  inherit AbstractType
  new : unit -> ConcreteType

Full name: Script.Container Register, Resolve, Release Tests.ConcreteType

--------------------
new : unit -> Container Register<...>.ConcreteType
type IMarkerInterface

Full name: Script.Container Register, Resolve, Release Tests.IMarkerInterface
Multiple items
type MarkedType =
  interface IMarkerInterface
  new : unit -> MarkedType

Full name: Script.Container Register, Resolve, Release Tests.MarkedType

--------------------
new : unit -> Container Register<...>.MarkedType
Multiple items
type TestAttribute =
  inherit NUnitAttribute
  new : unit -> TestAttribute
  member ApplyToTest : test:Test -> unit
  member Author : string with get, set
  member BuildFrom : method:IMethodInfo * suite:Test -> TestMethod
  member Description : string with get, set
  member ExpectedResult : obj with get, set
  member HasExpectedResult : bool with get, set
  member TestOf : Type with get, set

Full name: NUnit.Framework.TestAttribute

--------------------
TestAttribute() : unit
val ( registering 2 instances of an abstract type in a single container should throw ) : unit -> unit

Full name: Script.Container Register, Resolve, Release Tests.( registering 2 instances of an abstract type in a single container should throw )
member Container.Register : instance:'TAbstract -> unit


 Register abstract type against specified type instance

member Container.Register : abstractTypes:seq<AbstractType> * concreteType:ConcreteType -> unit


 Register sequence of abstract types against specified concrete type

member Container.Register : concreteType:ConcreteType * lifetime:Lifetime -> unit


 Register abstract type against specified concrete type with given lifetime

member Container.Register : f:(unit -> 'TAbstract) * lifetime:Lifetime -> unit (requires reference type)


 Register abstract type against specified factory with given lifetime
type Assert =
  static member AreEqual : expected:obj * actual:obj -> unit + 5 overloads
  static member AreNotEqual : expected:obj * actual:obj -> unit + 1 overload
  static member AreNotSame : expected:obj * actual:obj -> unit + 1 overload
  static member AreSame : expected:obj * actual:obj -> unit + 1 overload
  static member ByVal : actual:obj * expression:IResolveConstraint -> unit + 1 overload
  static member Catch : code:TestDelegate -> Exception + 5 overloads
  static member Contains : expected:obj * actual:ICollection -> unit + 1 overload
  static member DoesNotThrow : code:TestDelegate -> unit + 1 overload
  static member Equals : a:obj * b:obj -> bool
  static member Fail : unit -> unit + 2 overloads
  ...

Full name: NUnit.Framework.Assert
Assert.Throws<'TActual (requires 'TActual :> exn)>(code: TestDelegate) : 'TActual
Assert.Throws(expectedExceptionType: Type, code: TestDelegate) : exn
Assert.Throws(expression: Constraints.IResolveConstraint, code: TestDelegate) : exn
Assert.Throws<'TActual (requires 'TActual :> exn)>(code: TestDelegate, message: string, [<ParamArray>] args: obj []) : 'TActual
Assert.Throws(expectedExceptionType: Type, code: TestDelegate, message: string, [<ParamArray>] args: obj []) : exn
Assert.Throws(expression: Constraints.IResolveConstraint, code: TestDelegate, message: string, [<ParamArray>] args: obj []) : exn
Multiple items
type ArgumentException =
  inherit SystemException
  new : unit -> ArgumentException + 4 overloads
  member GetObjectData : info:SerializationInfo * context:StreamingContext -> unit
  member Message : string
  member ParamName : string

Full name: System.ArgumentException

--------------------
ArgumentException() : unit
ArgumentException(message: string) : unit
ArgumentException(message: string, innerException: exn) : unit
ArgumentException(message: string, paramName: string) : unit
ArgumentException(message: string, paramName: string, innerException: exn) : unit
val ( attempting to resolve an unregistered type should throw ) : unit -> unit

Full name: Script.Container Register, Resolve, Release Tests.( attempting to resolve an unregistered type should throw )
val ( resolving a registered abstract type should return an instance of the specified concrete type ) : unit -> unit

Full name: Script.Container Register, Resolve, Release Tests.( resolving a registered abstract type should return an instance of the specified concrete type )
val instance : Container Register<...>.AbstractType
Assert.True(condition: bool) : unit
Assert.True(condition: Nullable<bool>) : unit
Assert.True(condition: bool, message: string, [<ParamArray>] args: obj []) : unit
Assert.True(condition: Nullable<bool>, message: string, [<ParamArray>] args: obj []) : unit
val ( resolving a type with a singleton lifetime should always return the same instance ) : unit -> unit

Full name: Script.Container Register, Resolve, Release Tests.( resolving a type with a singleton lifetime should always return the same instance )
val a : Container Register<...>.AbstractType
val b : Container Register<...>.AbstractType
Multiple items
type Object =
  new : unit -> obj
  member Equals : obj:obj -> bool
  member GetHashCode : unit -> int
  member GetType : unit -> Type
  member ToString : unit -> string
  static member Equals : objA:obj * objB:obj -> bool
  static member ReferenceEquals : objA:obj * objB:obj -> bool

Full name: System.Object

--------------------
Object() : unit
Object.ReferenceEquals(objA: obj, objB: obj) : bool
val ( resolving a type with a transient lifetime should a new instance each time ) : unit -> unit

Full name: Script.Container Register, Resolve, Release Tests.( resolving a type with a transient lifetime should a new instance each time )
Assert.AreNotSame(expected: obj, actual: obj) : unit
Assert.AreNotSame(expected: obj, actual: obj, message: string, [<ParamArray>] args: obj []) : unit
val ( resolving a registered instance of a type should return that instance ) : unit -> unit

Full name: Script.Container Register, Resolve, Release Tests.( resolving a registered instance of a type should return that instance )
val this : Container Register<...>.ConcreteType
val that : Container Register<...>.AbstractType
Assert.AreSame(expected: obj, actual: obj) : unit
Assert.AreSame(expected: obj, actual: obj, message: string, [<ParamArray>] args: obj []) : unit
val ( resolving a type registered as a factory should call the specified factory ) : unit -> unit

Full name: Script.Container Register, Resolve, Release Tests.( resolving a type registered as a factory should call the specified factory )
val called : bool ref
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 factory : (unit -> Container Register<...>.AbstractType)
property Ref.Value: bool
val ( releasing a registered concrete instance then resolving the type should return a new concrete instance ) : unit -> unit

Full name: Script.Container Register, Resolve, Release Tests.( releasing a registered concrete instance then resolving the type should return a new concrete instance )
member Container.Release : instance:obj -> unit


 Remove instance reference from container
val that : Container Register<...>.ConcreteType
Multiple items
type AbstractType =
  new : unit -> AbstractType

Full name: Script.Constructor Tests.AbstractType

--------------------
new : unit -> AbstractType
Multiple items
type ConstructorWithValueTypeArg =
  inherit AbstractType
  new : arg:int -> ConstructorWithValueTypeArg

Full name: Script.Constructor Tests.ConstructorWithValueTypeArg

--------------------
new : arg:int -> ConstructorWithValueTypeArg
val arg : int
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<_>
val ( resolving type with value type dependency in constructor should throw ) : unit -> unit

Full name: Script.Constructor Tests.( resolving type with value type dependency in constructor should throw )
Multiple items
type ReferenceType =
  new : unit -> ReferenceType

Full name: Script.Constructor Tests.ReferenceType

--------------------
new : unit -> ReferenceType
Multiple items
type ConstructorWithReferenceTypeArg =
  inherit AbstractType
  new : arg:ReferenceType -> ConstructorWithReferenceTypeArg

Full name: Script.Constructor Tests.ConstructorWithReferenceTypeArg

--------------------
new : arg:ReferenceType -> ConstructorWithReferenceTypeArg
val arg : ReferenceType
val ( resolving type with reference type dependency in constructor should inject reference ) : unit -> unit

Full name: Script.Constructor Tests.( resolving type with reference type dependency in constructor should inject reference )
val instance : AbstractType
Assert.NotNull(anObject: obj) : unit
Assert.NotNull(anObject: obj, message: string, [<ParamArray>] args: obj []) : unit
Multiple items
type ConstructorWithSelfReferenceArg =
  inherit AbstractType
  new : arg:AbstractType -> ConstructorWithSelfReferenceArg

Full name: Script.Constructor Tests.ConstructorWithSelfReferenceArg

--------------------
new : arg:AbstractType -> ConstructorWithSelfReferenceArg
val arg : AbstractType
val ( resolving type with self type dependency in constructor should fail ) : unit -> unit

Full name: Script.Constructor Tests.( resolving type with self type dependency in constructor should fail )
Multiple items
type ConstructorWithFunArg =
  inherit AbstractType
  new : arg:(unit -> ReferenceType) -> ConstructorWithFunArg
  member Factory : unit -> ReferenceType

Full name: Script.Constructor Tests.ConstructorWithFunArg

--------------------
new : arg:(unit -> ReferenceType) -> ConstructorWithFunArg
val arg : (unit -> ReferenceType)
val this : ConstructorWithFunArg
member ConstructorWithFunArg.Factory : unit -> ReferenceType

Full name: Script.Constructor Tests.ConstructorWithFunArg.Factory
val ( resolving type with fun type argument in constructor should inject factory ) : unit -> unit

Full name: Script.Constructor Tests.( resolving type with fun type argument in constructor should inject factory )
val instance : ConstructorWithFunArg
val refValue : ReferenceType
member ConstructorWithFunArg.Factory : unit -> ReferenceType
Multiple items
type SubType1 =
  inherit AbstractType
  new : unit -> SubType1

Full name: Script.Constructor Tests.SubType1

--------------------
new : unit -> SubType1
Multiple items
type SubType2 =
  inherit AbstractType
  new : unit -> SubType2

Full name: Script.Constructor Tests.SubType2

--------------------
new : unit -> SubType2
Multiple items
type ConstructorWithSeqArg =
  new : subTypes:seq<AbstractType> -> ConstructorWithSeqArg
  member SubTypes : seq<AbstractType>

Full name: Script.Constructor Tests.ConstructorWithSeqArg

--------------------
new : subTypes:seq<AbstractType> -> ConstructorWithSeqArg
val this : ConstructorWithSeqArg
member ConstructorWithSeqArg.SubTypes : seq<AbstractType>

Full name: Script.Constructor Tests.ConstructorWithSeqArg.SubTypes
val ( resolving type with seq type argument in constructor should inject sub types ) : unit -> unit

Full name: Script.Constructor Tests.( resolving type with seq type argument in constructor should inject sub types )
val instance : ConstructorWithSeqArg
val types : Set<string>
property ConstructorWithSeqArg.SubTypes: seq<AbstractType>
val map : mapping:('T -> 'U) -> source:seq<'T> -> seq<'U>

Full name: Microsoft.FSharp.Collections.Seq.map
val i : AbstractType
Object.GetType() : Type
Multiple items
module Set

from Microsoft.FSharp.Collections

--------------------
type Set<'T (requires comparison)> =
  interface IComparable
  interface IEnumerable
  interface IEnumerable<'T>
  interface ICollection<'T>
  new : elements:seq<'T> -> Set<'T>
  member Add : value:'T -> Set<'T>
  member Contains : value:'T -> bool
  override Equals : obj -> bool
  member IsProperSubsetOf : otherSet:Set<'T> -> bool
  member IsProperSupersetOf : otherSet:Set<'T> -> bool
  ...

Full name: Microsoft.FSharp.Collections.Set<_>

--------------------
new : elements:seq<'T> -> Set<'T>
val ofSeq : elements:seq<'T> -> Set<'T> (requires comparison)

Full name: Microsoft.FSharp.Collections.Set.ofSeq
val types' : Set<string>
val set : elements:seq<'T> -> Set<'T> (requires comparison)

Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.set
Assert.That(condition: Func<bool>) : unit
Assert.That(condition: bool) : unit
Assert.That<'TActual>(actual: 'TActual, expression: Constraints.IResolveConstraint) : unit
Assert.That(code: TestDelegate, constraint: Constraints.IResolveConstraint) : unit
Assert.That<'TActual>(del: Constraints.ActualValueDelegate<'TActual>, expr: Constraints.IResolveConstraint) : unit
Assert.That(condition: Func<bool>, message: string, [<ParamArray>] args: obj []) : unit
Assert.That(condition: bool, message: string, [<ParamArray>] args: obj []) : unit
Assert.That<'TActual>(actual: 'TActual, expression: Constraints.IResolveConstraint, message: string, [<ParamArray>] args: obj []) : unit
Assert.That(code: TestDelegate, constraint: Constraints.IResolveConstraint, message: string, [<ParamArray>] args: string []) : unit
Assert.That<'TActual>(del: Constraints.ActualValueDelegate<'TActual>, expr: Constraints.IResolveConstraint, message: string, [<ParamArray>] args: obj []) : unit
type Marker

Full name: Script.Constructor Tests.Marker
Multiple items
type MarkedType1 =
  interface Marker
  new : unit -> MarkedType1

Full name: Script.Constructor Tests.MarkedType1

--------------------
new : unit -> MarkedType1
Multiple items
type MarkedType2 =
  interface Marker
  new : unit -> MarkedType2

Full name: Script.Constructor Tests.MarkedType2

--------------------
new : unit -> MarkedType2
Multiple items
type ConstructorWithInterfaceArg =
  new : markedTypes:seq<Marker> -> ConstructorWithInterfaceArg
  member MarkedTypes : seq<Marker>

Full name: Script.Constructor Tests.ConstructorWithInterfaceArg

--------------------
new : markedTypes:seq<Marker> -> ConstructorWithInterfaceArg
val markedTypes : seq<Marker>
val this : ConstructorWithInterfaceArg
member ConstructorWithInterfaceArg.MarkedTypes : seq<Marker>

Full name: Script.Constructor Tests.ConstructorWithInterfaceArg.MarkedTypes
val ( resolving type with seq type argument in constructor should inject interfaces ) : unit -> unit

Full name: Script.Constructor Tests.( resolving type with seq type argument in constructor should inject interfaces )
val instance : ConstructorWithInterfaceArg
property ConstructorWithInterfaceArg.MarkedTypes: seq<Marker>
val i : Marker
module Usage

from Script
type ICalculate =
  interface
    abstract member Incr : int -> int
  end

Full name: Script.Usage.ICalculate
abstract member ICalculate.Incr : int -> int

Full name: Script.Usage.ICalculate.Incr
Multiple items
type Calculator =
  interface ICalculate
  new : unit -> Calculator

Full name: Script.Usage.Calculator

--------------------
new : unit -> Calculator
val this : Calculator
override Calculator.Incr : x:int -> int

Full name: Script.Usage.Calculator.Incr
val x : int
val container : Container

Full name: Script.Usage.container
val calc : ICalculate

Full name: Script.Usage.calc
val printfn : format:Printf.TextWriterFormat<'T> -> 'T

Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.printfn
abstract member ICalculate.Incr : int -> int
type Console =
  static member BackgroundColor : ConsoleColor with get, set
  static member Beep : unit -> unit + 1 overload
  static member BufferHeight : int with get, set
  static member BufferWidth : int with get, set
  static member CapsLock : bool
  static member Clear : unit -> unit
  static member CursorLeft : int with get, set
  static member CursorSize : int with get, set
  static member CursorTop : int with get, set
  static member CursorVisible : bool with get, set
  ...

Full name: System.Console
Console.ReadLine() : string

More information

Link:http://fssnip.net/9g
Posted:12 years ago
Author:Phillip Trelford
Tags: di , ioc , dependency injection , container