Обязательный вопрос для ASP.NET MVC и Ninject 2.0 - PullRequest
2 голосов
/ 23 июля 2011

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

* 1003 Е.Г. *

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.

1 Ответ

4 голосов
/ 23 июля 2011

Это выглядит хорошо. 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

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

...