【问题标题】:Creating objects based on a string using Ninject使用 Ninject 基于字符串创建对象
【发布时间】:2015-06-20 12:17:23
【问题描述】:

我需要根据从数据库中获取的字符串创建共享通用接口 (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");
    }
}

【问题讨论】:

    标签: c# dependency-injection ninject


    【解决方案1】:

    Ninject 的 IKernelGet&lt;T&gt;() 方法有一个重载,它采用名称参数来获取命名实例。

    用法是:

    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);
    

    【讨论】:

    • 应该使用更窄的接口IResolutionRoot,而不是注入IKernel。内核是IKernel : IResolutionRoot, IBindingRoot。也没有必要为其创建绑定。
    • 你说得对@BatteryBackupUnit,最好使用IResolutionRoot 而不是IKernel。我没有注意到该接口的原因是因为我有自己的接口定义方法T Get&lt;T&gt;() 以从我的核心项目中删除对Ninject 的依赖关系。
    • 当您说return _kernel.Get&lt;AFoo&gt;(name); 时,您的意思是return _kernel.Get&lt;IFoo&gt;(name);IFoo 而不是AFoo
    • 是的@IsmailS,你是对的。我修好了,谢谢你发现它。
    猜你喜欢
    • 1970-01-01
    • 2011-01-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-25
    相关资源
    最近更新 更多