Обязательный вопрос ASP.NET MVC и Ninject 2.0

У меня есть класс под названием MyMailSender, который привязывается к контроллеру asp.net с именем EmailController.

E.g.

public EmailController(IMailSender sender)
    {
        //MyMailSender
        this.sender = sender;
    }

Этот класс MyMailSender также зависит от класса с именем MessageSender.

Прямо сейчас мой процесс работает без инъекции, делая следующее.

public class MyMailSender : IMailSender
{
    private IMessageSender messageSender;

    public MyMailSender()
    {
        messageSender = new SmtpMessageSender("mail.address.com", 25);
    }
}

Как я могу заставить этот зависимый класс привязываться к классу MyMailSender с помощью Ninject?

MyMailSender начальная привязка выполняется через заводскую привязку контроллера

public override void Load()
        {
                 Bind<IMailSender>()
                .To<MyMailSender>();            
        }

Я попытался привязаться к фабрике контроллера, например:

  Bind<IMessageSender>()
       .To<SmtpMessageSender>().WithConstructorArgument("mail.address.com", 25);

но я подозреваю, что не стоит привязываться сюда для такого типа привязки. Каковы мои варианты?

Мое сообщение об ошибке:

Error activating string
No matching bindings are available, and the type is not self-bindable.
Activation path:

  4) Injection of dependency string into parameter hostname of constructor of type SmtpMessageSender

  3) Injection of dependency IMessageSender into parameter messageSender of constructor of type MyMailSender

  2) Injection of dependency IMailSender into parameter sender of constructor of type EmailController

  1) Request for EmailController


Suggestions:
  1) Ensure that you have defined a binding for string.

  2) If the binding was defined in a module, ensure that the module has been loaded into the kernel.

  3) Ensure you have not accidentally created more than one kernel.

  4) If you are using constructor arguments, ensure that the parameter name matches the constructors parameter name.

  5) If you are using automatic module loading, ensure the search path and filters are correct.

person Nate    schedule 23.07.2011    source источник


Ответы (1)


Это выглядит хорошо. WithConstructorArgument предназначен для такого типа инициализации (пока эти аргументы не меняются в течение времени существования приложения/потока).

Я бы изменил MyMailSender таким образом, чтобы использовать внедрение конструктора:

public class MyMailSender : IMailSender
{
    private IMessageSender _messageSender;

    public MyMailSender(IMessageSender messageSender)
    {
        _messageSender = messageSender;
    }
}

И затем в вашем onLoad:

public override void Load()
{                     
  Bind<IMessageSender>()
       .To<SmtpMessageSender>()
       .WithConstructorArgument("hostname", "mail.address.com")
       .WithConstructorArgument("port", 25);
  Bind<IMailSender>()
       .To<MyMailSender>();     
}

Общий совет: каждый раз, когда вы видите что-то new на своих занятиях, воспринимайте это как запах. new следует редко встречать в вашем коде (например, на фабриках и т. д.) при использовании любого DI-фреймворка.

Другое предложение - загрузить адрес и порт из какого-либо файла конфигурации/настроек, а не жестко кодировать.

person Mrchief    schedule 23.07.2011
comment
Я попытался использовать MyMailSender для использования внедрения конструктора с самого начала и получил ошибку. --->Ошибка активации строки. Нет доступных привязок, и тип не является самопривязываемым. Путь активации: 4) Внедрение строки зависимости в параметр hostname конструктора типа SmtpMessageSender - person Nate; 23.07.2011
comment
Извините, смотрите мое обновление. Вам необходимо указать имя и значение параметра при использовании WithConstructorArgument(). Я предположил имена параметров, но вы поняли. - person Mrchief; 23.07.2011