我正在尝试创建一个自定义管理器,它在调用时在控制器中传递,我在理解c#中新MVC5项目的当前实现时遇到了麻烦。
这是默认实现:
public AccountController(ApplicationUserManager userManager, ApplicationSignInManager signInManager )
{
UserManager = userManager;
SignInManager = signInManager;
}
首先是它们的声明:
public ApplicationSignInManager SignInManager
{
get
{
return _signInManager ?? HttpContext.GetOwinContext().Get<ApplicationSignInManager>();
}
private set
{
_signInManager = value;
}
}
public ApplicationUserManager UserManager
{
get
{
return _userManager ?? HttpContext.GetOwinContext().GetUserManager<ApplicationUserManager>();
}
private set
{
_userManager = value;
}
}
根据我的理解,当Startup.Auth.cs中第一次创建应用程序时,会创建SignInManager和UserManager,如下所示:
app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
app.CreatePerOwinContext<ApplicationSignInManager>(ApplicationSignInManager.Create);
所以现在每当我调用UserManager时,我都会得到第一次项目运行时创建的第一个实例。
我有2个问题。问题1是我上面说的任何错误,我对MVC5如何工作有错误的理解吗?
问题2:如何在控制器中生成并传递UserManager和SignInManager?创建管理器的第一个实例并将其传递给控制器的代码在哪里?我假设它是app.CreatePerOwnContext that does it
。如果是这样,那么我可以创建自己的经理,然后以相同的方式将其注册到Owin并在整个项目中重复使用吗?如果我这样做而不缓存它,我的代码是否会从数据库中获取最新数据?
答案 0 :(得分:4)
你所展示的代码来自IMO非常丑陋的MVC5模板,该模板开箱即用,但做了一些丑陋的事情。
这个构造函数:
public AccountController(ApplicationUserManager userManager,
ApplicationSignInManager signInManager)
让你觉得OWIN会自动为你注入经理人。但实际情况并非如此。这就是为什么模板带有您在问题中提供的丑陋属性。如果不对模板进行任何更改,则会调用默认构造函数(也存在于模板中)。要尝试它,只需删除或评论默认构造函数,您就会看到AccountController
无法再创建。
所以实际发生的情况是,两个管理人员都使用所提供属性的getter中的Service Locator anti pattern。
所以现在每当我调用UserManager时,我都会得到第一次项目运行时创建的第一个实例?
不是不是这样。这一行:
app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
确实是为两位经理的Create
方法创建委托。经理被缓存在Owin请求中。下一个请求再次调用代理,您将得到一个新的ApplicationUserManager
等。
为了更加冗长,这一行可以改写为:
Func<ApplicationUserManager> userManagerFactory = () => ApplicationUserMangager.Create();
app.CreatePerOwinContext<ApplicationUserManager>(userManagerFactory);
所以如果你在这里断点:
public ApplicationUserManager UserManager
{
get
{
// place breakpoint here
return _userManager ?? HttpContext.GetOwinContext().GetUserManager<ApplicationUserManager>();
}
// ....
您会看到在单步执行代码时,您将点击创建UserManagerFactory
的行,而Create()
将调用ApplicationUserManager
的{{1}}方法。
如何在控制器中生成并传递UserManager和SignInManager
不是!你需要使用依赖注入。
如果是这样,我可以创建自己的经理,然后以相同的方式将其注册到Owin并在整个项目中重复使用
是的,你可以。您可以完全重构您自己获得的ApplicationUserManager&#39;在模板中。只要您为&#39; CreatePerOwinContext&#39;提供工厂方法。扩展方法。
如果我这样做而不缓存,我的代码是否会从数据库中获取最新数据? 实例基于每个请求库进行缓存。所以每个请求你都会得到一个新的DbContext等。
我不确定你对dependency injection的熟悉程度,但MVC5是一个非常简单的框架,从它开始,IMO。
我曾写过blogpost如何配置我选择的DI容器(Simple Injector)以与MVC5模板一起使用。 我还在这里就这个模板写了几个答案:特别是这个one,你应该感兴趣。这个one也很有趣!