【问题标题】:Using ASP.NET Session for Lifetime Management (Unity)使用 ASP.NET 会话进行生命周期管理 (Unity)
【发布时间】:2010-10-16 23:13:32
【问题描述】:

我正在考虑使用 Unity 来管理自定义用户类实例的生命周期。我计划使用自定义 ASP.NET 会话管理器来扩展 LifetimeManager。我想要做的是从我的自定义类中存储和检索当前登录的用户对象,并让 Unity 从 ASP.NET 中的会话对象中获取 User 的实例,或者(在 Win32 项目中)检索它静态或从当前线程。

到目前为止,我最好的解决方案是在启动时创建我的 Unity 容器的静态实例,并使用 Resolve 方法从我的每个类中获取我的用户对象。但是,这似乎在我的其他类中创建了对统一容器的依赖。实现这一目标的更“团结”的方式是什么?我希望能够从任何类中读取/替换当前的用户实例。

【问题讨论】:

  • “自定义 ASP.NET 会话管理器”是什么意思?你说的是 NHibernate Session 还是 Data/ObjectContext?

标签: c# asp.net session unity-container


【解决方案1】:

与 ASP.Net MVC 而不是普通的旧 ASP.Net 项目一起使用时,Unity 将获得最佳效果。 ASP.Net MVC 允许您使用 Unity 之类的容器来管理用户对象、控制器、模型等。如果可能,请在您的项目中使用 MVC 而不是 ASP.net Web 表单。

如果我正确理解了您的问题,您可能希望使用 Unity 来维护每个会话的对象生命周期。您需要实现一个扩展 LifetimeManager 的 SessionLifetimeManager。代码非常简单,大致如下:

public class SessionLifetimeManager : LifetimeManager
{
    private string _key = Guid.NewGuid().ToString();

    public override object GetValue()
    {
          return HttpContext.Current.Session[_key];
    }

    public override void SetValue(object value)
    {
          HttpContext.Current.Session[_key] = value;
    }

    public override void RemoveValue()
    {
          HttpContext.Current.Session.Remove(_key);
    }
}

你也可以为 PerWebRequest 生命周期管理写一个类似的。

【讨论】:

  • 据我所知,框架从不调用 Remove 方法。它在那里,供编码人员使用。为什么框架定义了一个合同而不使用合同中的一种方法?它让我发疯。
【解决方案2】:

为什么不使用缓存对象...那么你可以在win和web中使用它。像这样:

    IUnityContainer container= HttpRuntime.Cache.Get("Unity") as IUnityContainer;

    if (container == null)
    {
        container= // init container

        HttpRuntime.Cache.Add("Unity",
            container,
            null,
            Cache.NoAbsoluteExpiration,
            Cache.NoSlidingExpiration,
            CacheItemPriority.NotRemovable,
            null);
    }

    // return container or something

HttpRuntime.Cache 在 win 和 web 中都可以工作

【讨论】:

    【解决方案3】:

    我认为您需要通过统一公开的两项服务(或一项同时执行这两种操作的服务)。

    不是存储用户对象,而是存储一个接口实现,它公开一个方法/属性,为您获取用户对象。在 ASP.NET 案例中,您从会话中检索用户。在 WinForm 解决方案(或其他)中,您可以从执行线程中获取它。

    您还将拥有一个 set 方法/属性,用于设置用户。

    【讨论】:

    • 你能提供一个伪代码示例吗?我不明白您的响应如何使用 Unity,或者它如何允许单个类检索用户而不知道该类是在 ASP.NET 还是 WinForm 中使用。
    【解决方案4】:

    听起来你实际上需要的是 Registry 模式,而不是 Unity。

    http://martinfowler.com/eaaCatalog/registry.html

    【讨论】:

      【解决方案5】:

      也许我想多了,但我认为您应该将 AoP 与 IoC 一起使用。这真是一个美丽的配对。本质上,我要做的是劫持您正在解析的类的构造函数,否则称为创建方面。然后,您可以在进入构造函数时将用户注入到类中,但无论解决该类的什么,都不必显式地提供给用户,从而阻止与 Unity 本身的配对。

      PostSharp 是一个优秀的 AoP 框架恕我直言。

      现在你的应用最终将依赖于 AoP 框架,但是根据你的环境,完全解耦的应用可能是不现实的。您可能会惊讶于 AoP 和 IoC 的组合有多么有用。

      【讨论】:

        【解决方案6】:

        如果通过“自定义 ASP.NET 会话管理器”您谈论的是 NHibernate 会话或 Data/ObjectContext,听起来您需要的是注入到构造函数或属性设置器中的 IUserRepository,您可以从中检索用户对象。 IUserRepository 的实现可以是从数据库访问到后端缓存等的任何内容。如果您直接在容器上使用 .Resolve() ,那么您将遵循Service Locator 模式并且没有正确使用 Unity 提供的所有功能。

        然后您可以使用Ravi's answer 来管理存储库的生命周期。

        【讨论】:

          【解决方案7】:

          如果这不是很正确,我很抱歉,但是......

          Unity 是一个游戏开发平台,因此我假设您正在构建一个 3D 应用或游戏,您打算用它来做一些很酷的事情(例如,使其成为多人游戏/使用服务器跟踪用户进度)。

          为什么不让每个用户都登录,那么您可以使用 MembershipProvider 和 Formsauthentication 类来获得对用户 id/name 的访问权限。

          在您的服务器上,您只需将所有信息链接到用户的信息,即可轻松撤回与情况/用户请求相关的(简单的 ajax / 普通 http 请求)数据。

          我不确定这一点,但我相信统一是部署客户端的东西,因此不需要在服务器上完成与它的集成。

          只需请求您需要的内容并在客户端进行处理。

          这样您就可以坚持经典的 n 层设计模式,让您将逻辑与数据存储和用户界面分开。

          希望这会有所帮助...

          【讨论】:

          • 抱歉,您的回答只是指向了一条完全不同的路径,而不是为一个非常简洁的问题提供解决方案。
          • Unity 错误,请查看unity.codeplex.com。这是一个依赖注入库。
          猜你喜欢
          • 2016-04-12
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-05-27
          • 2011-08-21
          • 2016-11-21
          相关资源
          最近更新 更多