13 people like it.
Like the snippet!
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