Ninject 工厂根据枚举创建 T
Ninject factory create T based on enum
我想让 Ninject 根据特定的枚举输入值解析 T 的实例。
我读过 Ninject 的工厂扩展,但我找不到任何让工厂根据枚举解析特定 class 的示例。
每个 class 都派生自一个基础 class,派生的 class 有多个不同的接口,Ninject 也必须解析这些接口。
例如,界面应该是这样的:
public interface IProcessFactory
{
T Create<T>(ProcessIndex processIndex) where T : BaseProcess;
}
如何实现?
开箱即用不支持。您可以通过编写自己的 IInstanceProvider(also see ninject Wiki entry 实现来自定义它。然后为您的特定工厂配置它:
kernel.Bind<IFooFactory>()
.ToFactory(() => new MyCustomInstanceProvider());
或者,如果您想更改所有 .ToFactory()
绑定的行为:加载后重新绑定 IInstanceProvider
Ninject.Extensions.Factory
:
kernel.Rebind<IInstanceProvider>().To<MyCustomInstanceProvider>();
但是,如果它不是您经常需要的东西,我会考虑手动编写一个工厂实现 @composition root。
无论如何,在这两种情况下,您都需要知道如何创建条件绑定。 Ninject 称之为 Contextual Binding。
一种方法是使用 Binding-Metadata:
const string EnumKey = "EnumKey";
Bind<IFoo>().To<AFoo>()
.WithMetadata(EnumKey, MyEnum.A);
IResolutionRoot.Get<IFoo>(x => x.Get<MyEnum>(EnumKey) == MyEnum.A);
另一种方法是创建自定义 IParameter 并在条件绑定中使用:
Bind<IFoo>().To<AFoo>()
.When(x => x.Parameters.OfType<MyParameter>().Single().Value == A);
有几个选项可用于使用 DI (Ninject) 实现 AbstractFactory。
经过分析选项,我想出了Mark Seemann提供的解决方案,见http://blog.ploeh.dk/2012/03/15/ImplementinganAbstractFactory/
Container Based Factory 解决方案是我选择的解决方案,因为:
- 性能:按需 DI 按请求解析,构造函数中没有加载实例
- 易于重构:当我们想要将当前的 DI 框架 (Ninject) 替换为具有(几乎甚至更好的)功能集的更好的性能时,唯一需要更改的地方是工厂内部的调用而不是在 NinjectModules/Composition 根目录中。
另见 SO:
Simple Injector:Factory classes that need to create classes with dependencies
我想让 Ninject 根据特定的枚举输入值解析 T 的实例。
我读过 Ninject 的工厂扩展,但我找不到任何让工厂根据枚举解析特定 class 的示例。
每个 class 都派生自一个基础 class,派生的 class 有多个不同的接口,Ninject 也必须解析这些接口。
例如,界面应该是这样的:
public interface IProcessFactory
{
T Create<T>(ProcessIndex processIndex) where T : BaseProcess;
}
如何实现?
开箱即用不支持。您可以通过编写自己的 IInstanceProvider(also see ninject Wiki entry 实现来自定义它。然后为您的特定工厂配置它:
kernel.Bind<IFooFactory>()
.ToFactory(() => new MyCustomInstanceProvider());
或者,如果您想更改所有 .ToFactory()
绑定的行为:加载后重新绑定 IInstanceProvider
Ninject.Extensions.Factory
:
kernel.Rebind<IInstanceProvider>().To<MyCustomInstanceProvider>();
但是,如果它不是您经常需要的东西,我会考虑手动编写一个工厂实现 @composition root。
无论如何,在这两种情况下,您都需要知道如何创建条件绑定。 Ninject 称之为 Contextual Binding。 一种方法是使用 Binding-Metadata:
const string EnumKey = "EnumKey";
Bind<IFoo>().To<AFoo>()
.WithMetadata(EnumKey, MyEnum.A);
IResolutionRoot.Get<IFoo>(x => x.Get<MyEnum>(EnumKey) == MyEnum.A);
另一种方法是创建自定义 IParameter 并在条件绑定中使用:
Bind<IFoo>().To<AFoo>()
.When(x => x.Parameters.OfType<MyParameter>().Single().Value == A);
有几个选项可用于使用 DI (Ninject) 实现 AbstractFactory。
经过分析选项,我想出了Mark Seemann提供的解决方案,见http://blog.ploeh.dk/2012/03/15/ImplementinganAbstractFactory/
Container Based Factory 解决方案是我选择的解决方案,因为:
- 性能:按需 DI 按请求解析,构造函数中没有加载实例
- 易于重构:当我们想要将当前的 DI 框架 (Ninject) 替换为具有(几乎甚至更好的)功能集的更好的性能时,唯一需要更改的地方是工厂内部的调用而不是在 NinjectModules/Composition 根目录中。
另见 SO: Simple Injector:Factory classes that need to create classes with dependencies