简体   繁体   中英

DI Chaining Dependencies with Ninject

Consider the following code snip where we implement ILogger with all applications using BaseLogger . But then we have a scenario where we need to log somewhere specific for a customer, such as a database or to some enterprise App monitor so we have CustomerSpecificLogger that also implements ILogger

The cTor for CustomerSpecificLogger requires a type of ILogger be passed in, in this case we want an instance of BaseLogger passed in to perform both logging functions.

I know how to bind ILogger with Ninject, but how do you bind two different ILoggers and tell Ninject when to use each?

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

I've tried searching around for this but I'm struggling with what this would be called. So alas, I'm coming up empty handed.

Update If I try to bind both, hoping that it uses some type of index to do the binding, it errors out:

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

Error: More than one matching bindings are available.

Update 2 This is called ContextualBinding in Ninject and is documented here

I think I have this figured out now.

WithConstructorArgument(name, value) sounds like not?

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!");
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM