2015-01-25 2 views
0

Рассмотрим следующий код, где мы реализуем ILogger со всеми приложениями, используя BaseLogger. Но тогда у нас есть сценарий, где мы должны войти где-то специфичные для клиента, например, базы данных или какой-либо предприятия App монитор таким образом, мы имеем CustomerSpecificLogger, который также реализует ILoggerDI Chaining Dependencies with Ninject

В CTOR для CustomerSpecificLogger требует тип ILogger быть принят in, в этом случае нам нужен экземпляр BaseLogger для выполнения обеих функций ведения журнала.

Я знаю, как связать ILogger с Ninject, но как вы связываете два разных ILoggers и рассказываете 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); 
     } 
    } 

Я пробовал искать для этого, но я борюсь с тем, что это будет называться. Так увы, я прихожу с пустыми руками.

Update Если я пытаюсь связать как, в надежде, что он использует некоторый тип индекса делать обязательные характер, ошибки из:

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

Ошибка: Более одного согласования привязок доступны.

Update 2 Это называется ContextualBinding в Ninject и документально here

Я думаю, что я это понял, сейчас.

+2

Это может помочь. https://github.com/ninject/Ninject/wiki/Contextual-Binding – Andrew

ответ

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

Это не работает - по-прежнему возникает ошибка множественных привязок во время выполнения. Я вижу, что вы собираетесь делать, но эта модель кажется, что она сломается, если у меня будет более двух экземпляров ILogger и вам нужно объединить их все вместе. – Wjdavis5

+0

Действительно? Я ограничил только один интерфейс, ограничив прагматическое закрытие. Ничто не удалось ... – masaki

+0

Если вы хотел именованных привязок, используйте ... общественного переопределение аннулируются Load() { Bind () .Чтобы () .InSingletonScope() Названный ("BaseLogger"). Bind () .To () .InSingletonScope(). Именованный («CustomerSpecificLogger»). WithConstructorArgument («baseLogger», новый BaseLogger()); }} класс Программа { статической силы Main (string [] арг) { вар ядро ​​= новый StandardKernel(); kernel.Load (Assembly.GetExecutingAssembly()); var logger = kernel.Get ("CustomerSpecificLogger"); logger.Log («Hello!»); } } – masaki

Смежные вопросы