LightInject типизированные фабрики с параметрами
В соответствии с документацией LightInject мы можем создать типизированную фабрику и передать ей значение следующим образом:
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);
}
}
И мы регистрируем это так:
container.Register<int, IFoo>((factory, value) => new Foo(value));
container.Register<IFooFactory, FooFactory>(new PerContainerLifetime());
И мы можем вызвать GetFoo так:
var typedFooFactory = container.GetInstance<IFooFactory>();
var foo = typedFooFactory.GetFoo(42);
Итак, теперь мой вопрос: мы явно создаем экземпляр foo при регистрации фабрично нового Foo(значения). Но что, если мы хотим сделать это в нашем методе GetFoo на основе значения?
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;
}
}
Я хочу иметь возможность вызывать GetFoo и получать правильную реализацию, основанную на "значении".
var typedFooFactory = container.GetInstance<IFooFactory>();
var foo = typedFooFactory.GetFoo(3);
Assert.AreEqual(foo.GetType(),typeof(AnotherFooThatImplementsIFoo));
1 ответ
Главное - помнить, что в методе GetFoo нашей фабрики мы не вызываем делегат, а только передаем ссылку на него. Вызов происходит, когда мы регистрируем фабрику (путем создания объекта Foo). Итак, я создал статический класс Factory, который генерирует реализации IFoo на основе "значения":
container.Register<int, IFoo>((factory, value) => FooFactory.GetInstance);
И мой FooFactory выглядит так:
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;
}
}
}
}
Поэтому я вызываю делегата следующим образом:
var typedFooFactory = container.GetInstance<IFooFactory>();
var foo = typedFooFactory.GetFoo(3);
И теперь мой объект foo имеет тип AnotherFooThatImplementsIFoo
Assert.AreEqual(foo.GetType(),typeof(AnotherFooThatImplementsIFoo));