Sunday, May 23, 2010

A Simple Inversion of Control (IoC) Container in F#

In this post I will show how to build a simple Inversion of Control (IoC) container in F#.  If you are new to IoC containers I would recommend getting acquainted by reading and

The Code:
namespace FSharpIoC

open System
open System.Collections.Generic
open System.Reflection

module FSharpIoCModule = 
    let rec Resolve requestedType (typeContainer:Dictionary<Type,Type>) =
        let newType = typeContainer.[requestedType]
        let constructors = newType.GetConstructors() 
                           |> Array.sortBy (fun c -> c.GetParameters().Length) 
                           |> Array.rev
        let theConstructor = constructors.[0]
        match theConstructor.GetParameters() with
        | cstorParams when cstorParams.Length = 0 -> Activator.CreateInstance(newType)
        | cstorParams -> cstorParams 
                         |> (paramInfo:ParameterInfo) -> 
                                (Resolve paramInfo.ParameterType typeContainer)) 
                         |> Seq.toArray 
                         |> theConstructor.Invoke

type Container =
    val typeContainer : Dictionary<Type, Type>
    new () = {typeContainer = new Dictionary<Type, Type>()}
    member x.Register<'a,'b> () =        
        x.typeContainer.Add(typeof<'a>, typeof<'b>)
    member x.Resolve(requestedType) =
        FSharpIoCModule.Resolve requestedType x.typeContainer
    member x.Resolve<'a> () =
        FSharpIoCModule.Resolve typeof<'a> x.typeContainer :?> 'a
Using Our IoC Container From F#:

The code below is not exactly a "real world" example, but it does show how our IoC container could be used in an F# application:
module FSharpIoCExample

open System
open FSharpIoC

type Person =
    { FirstName : string
      LastName : string}

type IPersonFactory =
    abstract CreatePerson : unit -> Person

type PersonFactory() = 
    interface IPersonFactory with
        member x.CreatePerson () = 
            {FirstName = "TestFirst"; LastName = "TestLast"}

type PersonService = 
    val personFactory : IPersonFactory
    new (personFactory) = {personFactory = personFactory}
    member x.GetPerson () = 

let iocContainer = new Container()
do iocContainer.Register<IPersonFactory, PersonFactory>()
do iocContainer.Register<PersonService, PersonService>()
let personService = iocContainer.Resolve<PersonService>()
let person = personService.GetPerson()
do Console.WriteLine("The person's name is {0} {1}", person.FirstName, person.LastName)
do Console.ReadLine()
Using Our IoC Container From C#:

Here is the same example in C#:
using System;
using FSharpIoC;

namespace CSharpIoCExample
    class Program
        static void Main(string[] args)
            var iocContainer = new Container();
            iocContainer.Register<IPersonFactory, PersonFactory>();
            iocContainer.Register<PersonService, PersonService>();
            var personService = iocContainer.Resolve<PersonService>();
            var person = personService.GetPerson();
            Console.WriteLine("The person's name is {0} {1}", person.FirstName, person.LastName);

    public class Person
        public string FirstName { get; set; }
        public string LastName { get; set; }

    public interface IPersonFactory
        Person CreatePerson();

    public class PersonFactory : IPersonFactory
        public Person CreatePerson()
            return new Person { FirstName = "TestFirst", LastName = "TestLast" };

    public class PersonService
        protected readonly IPersonFactory _personFactory;
        public PersonService(IPersonFactory personFactory)
            _personFactory = personFactory;

        public Person GetPerson()
            return _personFactory.CreatePerson();

As you can see, it doesn't take much to build a slim featured IoC container in F#. You can find the full source at


  1. Great post - it's really helpful to have posts connecting terminology and code like this.

    BTW why not use implicit construction for PersonService?

    type PersonService(personFactory: IPersonFactory) =
    member x.GetPerson () = personFactory.CreatePerson()

  2. That's a great point! Implicit construction is a more succinct way to accomplish this functionality.

  3. That's a great point! Implicit construction is a more succinct way to accomplish this functionality.