在 asp.net mvc 3 中管理每个会话和请求的 AutoFac 生命周期范围 [英] Managing AutoFac lifetime scopes per session and request in asp.net mvc 3

查看:38
本文介绍了在 asp.net mvc 3 中管理每个会话和请求的 AutoFac 生命周期范围的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想在 Web 应用程序中使用 AutoFac.我有根容器,每个会话有一个子容器,每个请求有一个子容器.我试图弄清楚管理这些生命周期范围的最佳方法是什么.在 Global.asax.cs 中,我添加了以下内容:

I want to use AutoFac in a web application. I have the root container, a child container per session and a child container per request. I'm trying to figure out what the/a best way is to manage these lifetime scopes. In the Global.asax.cs I have added the following:

protected void Application_Start(object sender, EventArgs e)
{
    var container = ...;
}

protected void Session_Start(object sender, EventArgs e)
{
    var sessionScope = container.BeginLifetimeScope("session");

    Session["Autofac_LifetimeScope"] = sessionScope;
}

protected void Application_BeginRequest(object sender, EventArgs e)
{
    var sessionScope = (ILifetimeScope) Session["Autofac_LifetimeScope"];
    var requestScope = sessionScope.BeginLifetimeScope("httpRequest");

    HttpContext.Current.Items["Autofac_LifetimeScope"] = requestScope;
}

protected void Application_EndRequest(object sender, EventArgs e)
{
    var requestScope = (ILifetimeScope)HttpContext.Current.Items["Autofac_LifetimeScope"];
    requestScope.Dispose();
}

protected void Session_End(object sender, EventArgs e)
{
    var sessionScope = (ILifetimeScope)Session["Autofac_LifetimeScope"];

    sessionScope.Dispose();
}

protected void Application_End(object sender, EventArgs e)
{
    container.Dispose();
}

  1. 如何告诉 AutoFac 使用我的 requestScope 作为获取依赖项的起点,以便使用我的 requestScope 解析我注册为 InstancePerLifetimeScope 的实现?

  1. How can I tell AutoFac to use my requestScope as the starting point for getting dependencies, so that the implementations I register as InstancePerLifetimeScope will be resolved using my requestScope?

如果这是不可能的,我可以让 AutoFac 在我的 sessionScope 之外创建其每个请求的生命周期范围吗?

If that is not possible, can I get AutoFac to create its per-request lifetime scope out of my sessionScope?

还是我在这里走错了路?有没有其他方法可以让 AutoFac 了解这个层次结构?

Or am I on the wrong track here? Could there be an other way of making AutoFac aware of this hierarchy?

感谢任何帮助或其他评论.

Any help or other comments are appreciated.

回应史蒂文.

我仍处于原型设计的早期阶段,但您可能在 sessionScope 中拥有的东西:

I'm still in the early stages of prototyping, but possible things you could have in the sessionScope:

  • 用户偏好
  • 身份验证和授权上下文(例如用户身份和角色)

与我将要构建的应用程序无关,但在电子商务环境中,购物车可能是会话范围的.这可能是最好的具体例子.您希望它比请求的寿命更长,但比应用程序更短.

Not related to the application I'm going to build, but in a e-commerce environment, the shopping cart could be session scoped. This is probably the best concrete example. It is something that you expect to live longer than a request, but shorter than the application.

可能不止这些,但如果我有针对 UserPreferences、Authentication 和 Authorization 的策略,那么该策略也可以应用于稍后将创建的其他组件.

There could be more than this, but if I have a strategy for the UserPreferences, Authentication and Authorization, then that strategy could also be applied to other components that will be created later.

一个可能的替代方法是在请求开始时获取所有必要的信息,并将这些配置的组件放在请求范围内.它会给我我期望的结果,但它与我脑海中关于应用程序->会话->请求层次结构的模型不匹配.我希望创建一个有意义的系统,因为我绝对不是要维护它的人.

A possible alternative is to get all the necessary information at the beginning of the request and place these configured components in the request scope. It will give me the result I expect, but it doesn't match the model I have in my mind about application->session->request hierarchy. I'm hoping to create a system that makes sense, since I'm definitely not the one that is going to maintain it.

推荐答案

您需要做的是实现您自己的 Autofac.Integration.Mvc.ILifetimeScopeProvider.此接口控制如何/在何处生成请求生命周期范围.默认的 Autofac.Integration.Mvc.RequestLifetimeScopeProvider 处理基于每个请求的生命周期范围的创建、处置和维护.

What you'll need to do is implement your own Autofac.Integration.Mvc.ILifetimeScopeProvider. This interface is what governs how/where request lifetime scopes get generated. The default one, Autofac.Integration.Mvc.RequestLifetimeScopeProvider, handles creation, disposal, and maintenance of lifetime scopes on a per-request basis.

可以浏览代码对于 RequestLifetimeScopeProvider 此处,如果您打算进行此操作,我强烈建议您这样做.这是我能想到的最好的示例,其中包含显示其中一项职责的工作代码.

You can browse the code for RequestLifetimeScopeProvider here, which I highly recommend doing if you plan on undertaking this. It's the best sample I can think of containing working code showing the responsibility of one of these things.

ILifetimeScopeProvider 的实现将用于获取会话子容器,从中生成请求容器,并在请求结束时清理请求容器.如果会话容器不存在,您可能还想在其中创建会话容器.处理会话容器的清理/处置在那里可能会很棘手,但从设计的角度来看,如果所有这些都在一个地方而不是在提供者中的某个地方,有些在您的应用程序类中,那就太好了.

Your implementation of ILifetimeScopeProvider will be where you grab the session child container, spawn the request container from that, and, at the end of the request, clean up the request container. You may also want to create the session container in there if it doesn't exist. Handling cleanup/disposal of the session container may be tricky in there, but from a design perspective, it'd be nice if it was all in one place rather than some in the provider, some in your application class.

拥有 ILifetimeScopeProvider 后,您将在设置依赖项解析器时使用它.

Once you have your ILifetimeScopeProvider you'll use it when you set up your dependency resolver.

var scopeProvider = new MyCustomLifetimeScopeProvider(container, configAction);
var resolver = new AutofacDependencyResolver(container, scopeProvider);
DependencyResolver.SetResolver(resolver);

关于会话级范围概念的几句警告:

A couple of words of warning about the notion of a session-level scope:

  1. 您的内存占用量可能很大.您最终将拥有系统上每个用户的终生范围.虽然请求生命周期突然出现并很快消失,但这些会话级范围可能会存在很长时间.如果您有很多会话范围的项目,那么每个用户都会有相当大的内存使用量.如果人们在没有正确注销的情况下放弃"他们的会话,那么这些东西的生命就会更长.
  2. 生命周期范围及其内容不可序列化.查看 LifetimeScope 的代码,是未标记 [Serializable]... 即使是,存在于其中的已解析对象不一定都标记为可序列化.这很重要,因为这意味着您的会话级生命周期范围可能适用于具有内存中会话的单个框,但是如果您使用 SQL 会话或会话服务部署到场,则由于会话无法序列化,事情将分崩离析您的存储范围.如果您选择不序列化范围,那么您在机器上为每个用户拥有不同的范围 - 这也是一个潜在问题.
  3. 会话并不总是补充水分.如果正在访问的处理程序(例如 Web 表单)没有实现 IRequiresSessionState,会话不会再水化(无论是否在进程中).Web 表单和 MvcHandler 在默认情况下实现它,因此您不会查看任何问题,但如果您有需要注入的自定义处理程序,您会遇到一些障碍,因为这些请求不存在会话".
  4. Session_End 并不总是触发.根据 SessionStateModule.End 上的文档,如果你用完了-of-proc 会话状态,您实际上不会获得 Session_End 事件,因此您将无法清理.
  1. Your memory footprint could be huge. You're going to end up with a lifetime scope for every user on your system. While a request lifetime pops up and goes away pretty quickly, these session-level scopes will live potentially a long time. If you have a lot of session-scoped items, you're going to have a pretty good sized memory usage for each user. If people "abandon" their sessions without properly logging out, that's all the longer these things will live.
  2. Lifetime scopes and their contents aren't serializable. Looking at the code for LifetimeScope, it's not marked [Serializable]... and even if it was, the resolved objects living in there are not necessarily all marked serializable. This is important because it means your session-level lifetime scope might work on a single box with in-memory session, but if you deploy to a farm with SQL session or a session service, things will fall apart because the session can't serialize your stored scope. If you choose not to serialize the scope, then you have a different scope for each user across machines - also a potential problem.
  3. Session isn't always rehydrated. If the handler being accessed (e.g., the web form) doesn't implement IRequiresSessionState, the session won't be rehydrated (whether it's in-proc or not). Web forms and the MvcHandler implement that by default so you won't see any issues, but if you have custom handlers that require injection you'll hit some snags since "Session" won't exist for those requests.
  4. Session_End doesn't always fire. Per the docs on SessionStateModule.End, if you use out-of-proc session state you won't actually get the Session_End event, so you won't be able to clean up.

鉴于限制,尽量远离会话存储的范围通常是好的.但是……如果这就是您要做的,ILifetimeScopeProvider 就是这样做的方法.

Given the restrictions, it's generally good to try to stay away from session-stored scopes. However... if that's what you're going to do, the ILifetimeScopeProvider is the way to do it.

这篇关于在 asp.net mvc 3 中管理每个会话和请求的 AutoFac 生命周期范围的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆