使用 Ninject 基于字符串创建对象
Creating objects based on a string using Ninject
我需要根据从数据库中获取的字符串创建共享公共接口 (IFoo) 的对象。我有 "A",我需要实例化 AFoo,我得到 "B",我需要生产 BFoo,等等。我首先想到的是一个 工厂 。但是创建的对象(AFoo、BFoo)需要注入它们的依赖项(这些依赖项需要更多的依赖项,甚至一些参数)。对于所有注入,我使用 Ninject,它本身似乎是一个奇特的工厂。为了在我的工厂中创建对象,我 通过构造函数注入 Ninject 的内核 。这是理想的方式吗?
interface IBar { }
class Bar : IBar {
public Bar(string logFilePath) { }
}
interface IFoo { }
class AFoo : IFoo {
public AFoo(IBar bar) { }
}
class BFoo : IFoo { }
class FooFactory : IFooFactory {
private IKernel _ninjectKernel;
public FooFactory(IKernel ninjectKernel) {
_ninjectKernel = ninjectKernel;
}
IFoo GetFooByName(string name) {
switch (name) {
case "A": _ninjectKernel.Get<AFoo>();
}
throw new NotSupportedException("Blabla");
}
}
class FooManager : IFooManager {
private IFooFactory _fooFactory;
public FooManager(IFooFactory fooFactory) {
_fooFactory = fooFactory;
}
void DoNastyFooThings(string text) {
IFoo foo = _fooFactory.GetFooByName(text);
/* use foo... */
}
}
class Program {
public static void Main() {
IKernel kernel = new StandardKernel();
kernel.Bind<IBar>.To<Bar>();
kernel.Bind<IFooManager>.To<FooManager>();
kernel.Bind<IFooFactory>.To<FooFactory>();
IFooManager manager = kernel.Get<IFooManager>(new ConstructorArgument("ninjectKernel", kernel, true));
manager.DoNastyFooThings("A");
}
}
Ninject 的 IKernel
的 Get<T>()
方法有一个重载,它采用名称参数来获取命名实例。
用法为:
public int Main()
{
IKernel kernel = new StandardKernel();
kernel.Bind<IFoo>().To<AFoo>().Named("AFoo");
kernel.Bind<IFoo>().To<BFoo>().Named("BFoo");
//returns an AFoo instance
var afoo = kernel.Get<IFoo>("AFoo");
//returns an BFoo instance
var bfoo = kernel.Get<IFoo>("BFoo");
}
关于你关于将 Ninject 的 IKernel
注入 Factory
的构造函数的问题,我认为应该没有任何问题。
你的工厂应该是这样的:
public interface IFooFactory
{
IFoo GetFooByName(string name);
}
public class FooFactory : IFooFactory
{
private readonly IKernel _kernel;
public FooFactory(IKernel kernel)
{
_kernel = kernel;
}
public IFoo GetFooByName(string name)
{
return _kernel.Get<IFoo>(name);
}
}
您也可以像这样向 IKernel
添加绑定:
kernel.Bind<IKernel>().ToConstant(kernel);
我需要根据从数据库中获取的字符串创建共享公共接口 (IFoo) 的对象。我有 "A",我需要实例化 AFoo,我得到 "B",我需要生产 BFoo,等等。我首先想到的是一个 工厂 。但是创建的对象(AFoo、BFoo)需要注入它们的依赖项(这些依赖项需要更多的依赖项,甚至一些参数)。对于所有注入,我使用 Ninject,它本身似乎是一个奇特的工厂。为了在我的工厂中创建对象,我 通过构造函数注入 Ninject 的内核 。这是理想的方式吗?
interface IBar { }
class Bar : IBar {
public Bar(string logFilePath) { }
}
interface IFoo { }
class AFoo : IFoo {
public AFoo(IBar bar) { }
}
class BFoo : IFoo { }
class FooFactory : IFooFactory {
private IKernel _ninjectKernel;
public FooFactory(IKernel ninjectKernel) {
_ninjectKernel = ninjectKernel;
}
IFoo GetFooByName(string name) {
switch (name) {
case "A": _ninjectKernel.Get<AFoo>();
}
throw new NotSupportedException("Blabla");
}
}
class FooManager : IFooManager {
private IFooFactory _fooFactory;
public FooManager(IFooFactory fooFactory) {
_fooFactory = fooFactory;
}
void DoNastyFooThings(string text) {
IFoo foo = _fooFactory.GetFooByName(text);
/* use foo... */
}
}
class Program {
public static void Main() {
IKernel kernel = new StandardKernel();
kernel.Bind<IBar>.To<Bar>();
kernel.Bind<IFooManager>.To<FooManager>();
kernel.Bind<IFooFactory>.To<FooFactory>();
IFooManager manager = kernel.Get<IFooManager>(new ConstructorArgument("ninjectKernel", kernel, true));
manager.DoNastyFooThings("A");
}
}
Ninject 的 IKernel
的 Get<T>()
方法有一个重载,它采用名称参数来获取命名实例。
用法为:
public int Main()
{
IKernel kernel = new StandardKernel();
kernel.Bind<IFoo>().To<AFoo>().Named("AFoo");
kernel.Bind<IFoo>().To<BFoo>().Named("BFoo");
//returns an AFoo instance
var afoo = kernel.Get<IFoo>("AFoo");
//returns an BFoo instance
var bfoo = kernel.Get<IFoo>("BFoo");
}
关于你关于将 Ninject 的 IKernel
注入 Factory
的构造函数的问题,我认为应该没有任何问题。
你的工厂应该是这样的:
public interface IFooFactory
{
IFoo GetFooByName(string name);
}
public class FooFactory : IFooFactory
{
private readonly IKernel _kernel;
public FooFactory(IKernel kernel)
{
_kernel = kernel;
}
public IFoo GetFooByName(string name)
{
return _kernel.Get<IFoo>(name);
}
}
您也可以像这样向 IKernel
添加绑定:
kernel.Bind<IKernel>().ToConstant(kernel);