Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

IUserStore[Models.ApplicationUser] is not resolved by Unity Interface to Class, but resolved with InjectionConstructor

When I am trying to invoke Accounts controller, I am getting this error back,

[InvalidOperationException: The current type, Microsoft.AspNet.Identity.IUserStore`1[Proj1.Web.Models.ApplicationUser], is an interface and cannot be constructed. Are you missing a type mapping?]

But after searching through I got it working by ;

container.RegisterType<AccountController>(new InjectionConstructor());

But why this error in first place?

Account controller has a parameter less constructor ,

  public AccountController(ApplicationUserManager userManager, ApplicationSignInManager signInManager )
        {
            UserManager = userManager;
            SignInManager = signInManager;
        }

and then ApplicationUserManager has following parameter less constructor.

public ApplicationUserManager(IUserStore<ApplicationUser> store)
            : base(store)
        {
        }

So the dependency is IUserStore.

Now, as my standard practice , I would be doing something like following:

  container.RegisterType<IUserStore<ApplicationUser>,UserStore<ApplicationUser>>();

But instead we are doing , which kind of feels like magic

container.RegisterType<AccountController>(new InjectionConstructor());

What does above line means?

like image 816
Simsons Avatar asked Aug 01 '17 04:08

Simsons


1 Answers

The reason for the InvalidOperationException is that Unity, by default, will select the constructor with the most number of arguments as the constructor to use to instantiate the object.

In this case that would be

public AccountController(ApplicationUserManager userManager,
                         ApplicationSignInManager signInManager)

which depends on ApplicationUserManager which depends on an implementation of IUserStore<ApplicationUser>. It seems that there is no registration in Unity mapping an IUserStore to a concrete class so Unity throws an exception.

The reason why

container.RegisterType<AccountController>(new InjectionConstructor());

works is that this registration with an "empty" InjectionConstructor tells Unity to use the parameterless constructor: public AccountController() when instantiating the AccountController. This works fine since there are no additional dependencies to resolve.

Whether this is what you want or not will depend on your implementation but usually you want to explicitly inject the dependencies into the constructor and not use the parameterless constructor.

Also note that in the case of

container.RegisterType<IUserStore<ApplicationUser>,UserStore<ApplicationUser>>(); 

you could also register using open generics so that any IUserStore<T> can be resolved without registering all of the possible types of T.

container.RegisterType(typeof(IUserStore<>), typeof(UserStore<>));
// Will resolve both concrete types
var userStore1 = container.Resolve<IUserStore<ApplicationUser>>();
var userStore2 = container.Resolve<IUserStore<OtherApplicationUser>>();
like image 92
Randy supports Monica Avatar answered Nov 01 '22 16:11

Randy supports Monica