DI链与Ninject的依赖关系

时间:2015-01-25 15:42:20

标签: c# inversion-of-control ninject

考虑以下代码片段,我们使用ILogger对所有应用程序实施BaseLogger。但是,我们有一个场景,我们需要记录特定于客户的某个地方,例如数据库或某个企业应用程序监视器,因此我们CustomerSpecificLogger也实现了ILogger

CustomerSpecificLogger的cTor需要传入一种ILogger,在这种情况下,我们希望传入BaseLogger的实例来执行两种日志记录功能。

我知道如何将ILogger绑定到Ninject,但是如何绑定两个不同的ILogger并告诉Ninject何时使用它们?

interface ILogger
    {
        void Log(string msg);
    }

    class BaseLogger : ILogger
    {
        public void Log(string msg)
        {
            Console.WriteLine(msg);
        }
    }

    class CustomerSpecificLogger : ILogger
    {
        private ILogger BaseLogger { get; set; }

        CustomerSpecificLogger(ILogger baseLogger)
        {
            BaseLogger = baseLogger;
        }

        public void Log(string msg)
        {
            //Log to somewhere specific per customer request
            BaseLogger.Log(msg);
        }
    }

我试图四处寻找,但我正在努力解决这个问题。唉,我空手而归。

更新 如果我尝试绑定两者,希望它使用某种类型的索引来进行绑定,则会出错:

Bind<ILogger>().To<BaseLogger>();
Bind<ILogger>().To<CustomerSpecificLogger>();

错误:有多个匹配的绑定可用。

更新2 这在Ninject中称为ContextualBinding,并记录在案here

我想我现在已经弄明白了。

1 个答案:

答案 0 :(得分:0)

WithConstructorArgument(名称,值)听起来不是吗?

using System;
using System.Reflection;
using Ninject;
using Ninject.Modules;

public interface ILogger
{
    void Log(string msg);
}

public class BaseLogger : ILogger
{
    public void Log(string msg)
    {
        Console.WriteLine(msg);
    }
}

public class CustomerSpecificLogger : ILogger
{
    private ILogger BaseLogger { get; set; }

    public CustomerSpecificLogger(ILogger baseLogger)
    {
        BaseLogger = baseLogger;
    }

    public void Log(string msg)
    {
        //Log to somewhere specific per customer request
        BaseLogger.Log(msg);
    }
}

// kernel.Load() in Program.Main() automatically load and bind this.
public class Bindings : NinjectModule
{
    public override void Load()
    {
#if true // or some App.config, anything...
        Bind<ILogger>().To<BaseLogger>().InSingletonScope();
#else
        Bind<ILogger>().To<CustomerSpecificLogger>().InSingletonScope().WithConstructorArgument("baseLogger", new BaseLogger());
#endif
    }
}

class Program
{
    static void Main(string[] args)
    {
        var kernel = new StandardKernel();
        kernel.Load(Assembly.GetExecutingAssembly());

        var logger = kernel.Get<ILogger>();

        logger.Log("Hello!");
    }
}