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)
上面的线是什么意思?
的原因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)