我正在尝试创建一个自定义管理器,该管理器在调用时传递到控制器中,并且无法理解 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;
}
}
现在根据我的理解,SignInManager和UserManager是在Startup.Auth中首次创建应用程序时创建的.cs如下所示:
app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
app.CreatePerOwinContext<ApplicationSignInManager>(ApplicationSignInManager.Create);
所以现在每当我调用UserManager时,我都会得到项目第一次运行时创建的第一个实例。
我有两个问题。 问题 1 是我上面所说的任何内容都是错误的吗,我对 MVC5 的工作原理有错误的理解吗?
问题 2:如何在控制器中生成和传递用户管理器和登录管理器? 创建管理器的第一个实例并将其传递到控制器中的代码在哪里? 我假设它是app.CreatePerOwnContext that does it
. 如果是这样,我是否可以创建自己的管理器,然后以相同的方式向 Owin 注册它并在整个项目中重复使用? 如果我这样做而不缓存它,我的代码是否会从数据库中获取最新数据?
您显示的代码来自IMO非常丑陋的MVC5模板,该模板开箱即用,但做了一些丑陋的事情。
此构造函数:
public AccountController(ApplicationUserManager userManager,
ApplicationSignInManager signInManager)
让你认为OWIN自动为你注入经理。但事实并非如此。这就是为什么模板带有您在问题中提供的丑陋属性的原因。如果不对模板进行任何更改,则会调用默认构造函数(模板中也存在)。要尝试它,只需删除或注释默认构造函数,您将看到无法再创建AccountController
。
因此,实际发生的是,两个管理器都在所提供属性的获取器中使用服务定位器反模式进行定位。
所以现在每当我调用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
的行,而该行又将调用ApplicationUserManager
的Create()
方法。
如何在控制器中生成和传递用户管理器和登录管理器
不是!为此,您需要使用依赖注入。
如果是这样,那么我是否可以创建自己的管理器,然后以相同的方式向 Owin 注册它并在整个项目中重复使用
是的,你可以。您可以完全重构您在模板中"免费"获得的应用程序用户管理器。只要您为"CreatePerOwinContext"扩展方法提供工厂方法。
如果我这样做而不缓存它,我的代码是否会从数据库中获取最新数据? 实例按请求基础进行缓存。因此,每个请求您都会得到一个新的请求,一个新的 DbContext 等。
我不确定您对依赖注入有多熟悉,但 MVC5 是一个非常容易开始使用它的框架,IMO。
我曾经写过一篇博客文章,如何配置我选择的 DI 容器(简单注入器)以与 MVC5 模板一起使用。我还在这里写了几个关于这个模板的答案:特别是这个,你应该感兴趣。这个也很有趣!