Per documentation of LightInject we can create a typed factory and pass a value to it like this:
public class Foo : IFoo
{
public Foo(int value)
{
Value = value;
}
public int Value { get; private set; }
}
public interface IFooFactory
{
IFoo GetFoo(int value);
}
public class FooFactory : IFooFactory
{
private Func<int, IFoo> createFoo;
public FooFactory(Func<int, IFoo> createFoo)
{
this.createFoo = createFoo;
}
public IFoo GetFoo(int value)
{
return createFoo(value);
}
}
And we register it like this:
container.Register<int, IFoo>((factory, value) => new Foo(value));
container.Register<IFooFactory, FooFactory>(new PerContainerLifetime());
And we can call GetFoo like this:
var typedFooFactory = container.GetInstance<IFooFactory>();
var foo = typedFooFactory.GetFoo(42);
So now my question is: we instantiate foo explicitly when we are registering the factory new Foo(value). But what if we want to do it within our GetFoo method based on the value?
public IFoo GetFoo(int value)
{
switch (value)
{
case 1: return new Foo(1);
case 2: return new FooThatImplementsIFoo(2);
case 3: return new AnotherFooThatImplementsIFoo(3);
default: return null;
}
}
I want to be able to call GetFoo and get the proper implementation based on "value".
var typedFooFactory = container.GetInstance<IFooFactory>();
var foo = typedFooFactory.GetFoo(3);
Assert.AreEqual(foo.GetType(),typeof(AnotherFooThatImplementsIFoo));
The key is to remember that within GetFoo method of our factory, we are not invoking the delegate, but only passing around the reference to it. The invocation is when we are registering the factory (by instantiating a Foo object). So what I did was to create a static Factory class that generates implementations of IFoo based on "value":
container.Register<int, IFoo>((factory, value) => FooFactory.GetInstance);
And my FooFactory looks like this:
public static class FooFactory
{
public static IFoo GetInstance(IServiceFactory serviceFactory, int value)
{
switch (value)
{
case 1:
{
return serviceFactory.GetInstance<Foo>();
}
case 2:
{
return serviceFactory.GetInstance<FooThatImplementsIFoo>();
}
case 3:
{
return serviceFactory.GetInstance<AnotherFooThatImplementsIFoo>();
}
default:
{
return null;
}
}
}
}
So I invoke the delegate by doing this:
var typedFooFactory = container.GetInstance<IFooFactory>();
var foo = typedFooFactory.GetFoo(3);
And now my foo object is of Type AnotherFooThatImplementsIFoo
Assert.AreEqual(foo.GetType(),typeof(AnotherFooThatImplementsIFoo));