IUserStore [Models.ApplicationUser]不会由Unity接口解析为Class,而是由InjectionConstructor解析

Sim*_*ons 3 c# asp.net-mvc dependency-injection inversion-of-control unity-container

当我尝试调用Accounts控制器时,我得到了该错误,

[InvalidOperationException:当前类型Microsoft.AspNet.Identity.IUserStore`1 [Proj1.Web.Models.ApplicationUser]是一个接口,无法构造。您是否缺少类型映射?]

但是经过搜索我得到了它的支持;

container.RegisterType<AccountController>(new InjectionConstructor());
Run Code Online (Sandbox Code Playgroud)

但是,为什么这个错误排在首位呢?

帐户控制器的参数少了构造函数,

  public AccountController(ApplicationUserManager userManager, ApplicationSignInManager signInManager )
        {
            UserManager = userManager;
            SignInManager = signInManager;
        }
Run Code Online (Sandbox Code Playgroud)

然后ApplicationUserManager具有以下参数较少的构造函数。

public ApplicationUserManager(IUserStore<ApplicationUser> store)
            : base(store)
        {
        }
Run Code Online (Sandbox Code Playgroud)

因此,依赖项为IUserStore。

现在,作为我的标准做法,我将执行以下操作:

  container.RegisterType<IUserStore<ApplicationUser>,UserStore<ApplicationUser>>();
Run Code Online (Sandbox Code Playgroud)

但是相反,我们在做,感觉就像魔术

container.RegisterType<AccountController>(new InjectionConstructor());
Run Code Online (Sandbox Code Playgroud)

上面的线是什么意思?

Ran*_*ica 5

的原因InvalidOperationException是,默认情况下,Unity将选择参数数量最多的构造函数作为用于实例化对象的构造函数。

在这种情况下

public AccountController(ApplicationUserManager userManager,
                         ApplicationSignInManager signInManager)
Run Code Online (Sandbox Code Playgroud)

取决于ApplicationUserManager哪个取决于的实现IUserStore<ApplicationUser>。似乎在Unity中没有注册,无法将映射IUserStore到具体类,因此Unity会引发异常。

之所以

container.RegisterType<AccountController>(new InjectionConstructor());
Run Code Online (Sandbox Code Playgroud)

起作用的是,使用“空”进行的注册InjectionConstructor告诉Unity public AccountController()在实例化AccountController时使用无参数构造函数:由于没有其他要解决的依赖关系,因此可以正常工作。

是否需要它取决于您的实现,但是通常您希望将依赖项显式注入到构造函数中,而不使用无参数构造函数。

另请注意,在

container.RegisterType<IUserStore<ApplicationUser>,UserStore<ApplicationUser>>(); 
Run Code Online (Sandbox Code Playgroud)

您也可以使用开放式泛型进行注册,以便IUserStore<T>无需注册所有可能的T类型就可以解决任何问题。

container.RegisterType(typeof(IUserStore<>), typeof(UserStore<>));
// Will resolve both concrete types
var userStore1 = container.Resolve<IUserStore<ApplicationUser>>();
var userStore2 = container.Resolve<IUserStore<OtherApplicationUser>>();
Run Code Online (Sandbox Code Playgroud)