带参数的 LightInject 类型工厂
LightInject typed factories with parameters
根据 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);
所以现在我的问题是:我们在注册 factory new Foo(value) 时显式实例化了 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 并根据 "value" 获得正确的实现。
var typedFooFactory = container.GetInstance<IFooFactory>();
var foo = typedFooFactory.GetFoo(3);
Assert.AreEqual(foo.GetType(),typeof(AnotherFooThatImplementsIFoo));
关键是要记住,在我们工厂的 GetFoo 方法中,我们没有调用委托,而只是传递对它的引用。调用是在我们注册工厂时(通过实例化 Foo 对象)。
所以我所做的是创建一个静态工厂 class,它根据 "value":
生成 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));
根据 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);
所以现在我的问题是:我们在注册 factory new Foo(value) 时显式实例化了 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 并根据 "value" 获得正确的实现。
var typedFooFactory = container.GetInstance<IFooFactory>();
var foo = typedFooFactory.GetFoo(3);
Assert.AreEqual(foo.GetType(),typeof(AnotherFooThatImplementsIFoo));
关键是要记住,在我们工厂的 GetFoo 方法中,我们没有调用委托,而只是传递对它的引用。调用是在我们注册工厂时(通过实例化 Foo 对象)。 所以我所做的是创建一个静态工厂 class,它根据 "value":
生成 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));