This project is read-only.

One public constructor, not three

Nov 13, 2013 at 4:42 AM
I'm using a library called Postal that allows me to send emails with Views as the body. The library has an interface I can inject into my controller: IEmailService.

So my controller has two dependencies: IWebSecurity and IEmailService

When I try to register this IEmailService I get:

"For the container to be able to create EmailService, it should contain exactly one public constructor, but it has 3."

I'm attempting to register like so:

container.Register<IEmailService, EmailService>();

Can register the IEmailService for use with my Controller even though this Postal library has 3 constructors (one is a no parameter)?

Thanks -
Coordinator
Nov 13, 2013 at 8:21 AM
I've written the multiple constructor anti-pattern. In this article I state:

> Prevent using your container’s auto-wiring facility when registering 3rd party types.

So instead of doing:
container.Register<IEmailService, EmailService>(); 
you should do:
container.Register<IEmailService>(() => new EmailService([your constructor arguments])); 
Also note that from a architectural point of view you might want to minimize the amount of coupling of your application with external libraries. Even though you're coupling to an interface, you're still coupling to an interface of an external library. This still makes it harder to replace the framework later on and could make it harder to use and test, because that interface might contain much more methods than your application needs.

You can prevent your application from taking a dependency on that framework by creating a proxy class that presents its own (by you defined) abstraction and wraps uses the EmailService internally.
Marked as answer by dot_NET_Junkie on 2/26/2014 at 1:16 PM
Nov 13, 2013 at 3:36 PM
Edited Nov 13, 2013 at 3:37 PM
This did the trick!

And also thank you for the advice on the proxy class, I'll look into adding this over the library.
Mar 5, 2015 at 5:09 PM
My scenario is similar. I'm trying to set up ASP.net Identity via IoC instead of how the sample apps use OWIN. The problem I have is that my DbContext has multiple constructors, but so do the classes that depend on it.
container.RegisterPerWebRequest<EntityContext>(() => new EntityContext("Name=MyAppConnStringName"));

/* These two take an EntityContext in a constructor, but they have multiple constructors. How do you register these to make sure they use the same shared context? */
container.RegisterPerWebRequest<IUserStore<User, int>, UserStore>(/* What goes here for shared context created above? */);
container.RegisterPerWebRequest<IRoleStore<Role, int>, RoleStore>(/* What goes here for shared context created above? */);
Coordinator
Mar 5, 2015 at 5:52 PM
Hi Sweeperq,

Your specific case is discussed in much detail in this thread. Basically, since UserStore and RoleStore are framework types, you should prevent them from being auto-wired (as discussed here). The thread gives the following examples:
container.RegisterPerWebRequest<IUserStore<ApplicationUser>>(
    () => new UserStore<ApplicationUser>(
        container.GetInstance<ApplicationDbContext>()));

container.RegisterPerWebRequest<IRoleStore<IdentityRole, string>>(
        () => new RoleStore<IdentityRole>(
              container.GetInstance<ApplicationDbContext>()));
For more information, please see the referenced thread.