1
votes

I have an ASP.NET MVC 5 project where I need to use a custom web-service based e-mail service (long story! Can't change it, though).

I wrapped up the e-mail web service into a separate assembly and packaged all the dependencies in there.

In my ASP.NET MVC 5 app, I'm using Ninject for dependency injection, and it works really well inside the MVC project - the controllers get their dependencies injected "magically" , and it's a joy to use.

But now: for my e-mail sending component, I'd like to write a "mock" or simulator for use locally when doing development. So basically, I would need to be able to bind the IMailService to both the MailService (real implementation), as well as the MailServiceSimulator (my dummy implementation). Ninject supports that, no problem:

Bind<IMailService>().To<MailService>().Named("Production");
Bind<IMailService>().To<MailServiceSimulator>().Named("Simulator");

BUT: the problem is this: I register all the dependencies with Ninject in the MVC application (in the NinjectWebCommon class in App_Startup) - but I'd like to be able to have a factory class in my "mail service" project that can be told to return a real implementation - or the simulator - for the mail sending component. But how can I get access to the Ninject kernel in order to get the desired service?

Somehow, I'd need to be able to do either

return kernel.Get<IMailService>("Production");

if the real implementation is desired, or

return kernel.Get<IMailService>("Simulator");

if the development-time simulator for the IMailService should be used.

Since my MVC app already uses the "MailService" assembly as a reference, I cannot really make the "MailService" use the "MVC" project as a reference.... so how can I access the Ninject kernel (that gets created inside the "MVC" assembly at startup) from within a referenced "MailService" assembly?? Seems I'm going in circles, one assembly requiring the other and then the other requiring the first one again as a dependency.....

Any ideas?

1
I have been using smtp4dev.codeplex.com installed locally for this kind of stuff. There are others tools that do similar thing. I found it really useful, as I am also able to "verify" my emails and content is valid, spelt correctly, etc.... I'd probably not bother trying to moq/stub this ...Dai Bok
@DaiBok: as I said - I have to use a customer-provided mail service interface, I cannot use regular SMTP :...marc_s
@DaiBok: but I totally agree with you - if you're using "regular" SMTP, then something like smtp4dev is a great tool to help development!marc_s

1 Answers

2
votes

Accessing the Kernel, or doing DI business, in your MailService project seems like a leaky abstraction.

Assuming the "Production/Simulator" switch is located in the appSettings as a "MailSwitch" setting, you may leave out the named bindings and go for :

Bind<IMailService>().To<MailService>()
    .When(r => ConfigurationManager.AppSettings.Get("MailSwitch")=="Production");
Bind<IMailService>().To<MailServiceSimulator>()
    .When(r => ConfigurationManager.AppSettings.Get("MailSwitch")=="Simulator");