2

I have a Class called MyMailSender that binds to the asp.net controller called EmailController.

E.g.

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

This MyMailSender class also is dependant on a class called MessageSender.

Right now my process works without the injection by doing the following.

public class MyMailSender : IMailSender
{
    private IMessageSender messageSender;

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

How can I get this dependant class to bind to the MyMailSender class using Ninject?

MyMailSender initial binding is done via controller factory binding

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

I tried binding to the controller factory like:

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

but I suspect that I should not bind here for this type of binding. What are my options?

My error message is:

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.
Ruben Bartelink
  • 59,778
  • 26
  • 187
  • 249
Nate
  • 2,044
  • 4
  • 23
  • 47

1 Answers1

4

This looks fine. WithConstructorArgument is meant for those type of initializations (as long as those arguments don't change for the lifetime of aaplication/thread).

I would change MyMailSender like this to use constructor injection:

public class MyMailSender : IMailSender
{
    private IMessageSender _messageSender;

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

And then in your onLoad:

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

As a general tip, anytime you see a new somthing in your classes, take that as a smell. new should be found rarely in your code (like in factories etc.) when using any DI framework

Another suggestion is to load the address and port from some config/settings file rather than hard coding.

Mrchief
  • 75,126
  • 20
  • 142
  • 189
  • I tried MyMailSender to use constructor injection from the begging and got an error.--->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 – Nate Jul 23 '11 at 04:12
  • Sorry, see my update. You need to specify the param name and value when using `WithConstructorArgument()`. I assumed the param names but you get the idea. – Mrchief Jul 23 '11 at 04:21