将 Unity 与 ASP.NET MVC 3 结合使用来存储在 Session 中的对象

发布于 2024-11-06 16:32:57 字数 735 浏览 2 评论 0原文

我有一个 MVC 控制器,它在会话中存储一个对象。不同的控制器操作从会话中检索对象,对其进行操作,然后将其保存回来。

我想使用 Unity,以便控制器只处理接口,但我不确定如何实现这一点(我对整个依赖项注入还很陌生)。这是一些示例代码:

public class MyController : Controller
{
   [HttpGet]
   public ActionResult Index()
   {
      var state = new State();
      // do stuff with state
      Session[Key] = state;
      return View();
   }

   [HttpPost]
   public ActionResult Change()
   {
      var state = Session[Key] as State;
      // do stuff with state
      Session[Key] = state;
      return View();
   }
}

所以基本上我想使用 IState 而不是 State。但是Unity在哪里/如何注入具体的实现呢?似乎它不可能在构造函数中发生,因为我只需要在 Index() 操作中实例化一个新对象。是否有一些神奇的方法可以将参数添加到 Unity 可以使用的 Index() 中?

I've got an MVC controller that stores an object in Session. Different controller actions retrieve the object from Session, do stuff with it, and save it back.

I'd like to use Unity so that the controller just deals with an interface, but I'm not sure how to achieve this (I'm fairly new to the whole dependency injection thing). Here's some sample code:

public class MyController : Controller
{
   [HttpGet]
   public ActionResult Index()
   {
      var state = new State();
      // do stuff with state
      Session[Key] = state;
      return View();
   }

   [HttpPost]
   public ActionResult Change()
   {
      var state = Session[Key] as State;
      // do stuff with state
      Session[Key] = state;
      return View();
   }
}

So basically I want to use IState instead of State. But where/how does Unity inject the concrete implementation? It seems like it can't happen in the constructor, because I only need to instantiate a new object in the Index() action. Is there maybe some magic way I can add a parameter to Index() that Unity can use?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

伴我老 2024-11-13 16:32:57

如果你想使用 Unity,你必须稍微改变你的实现。您必须将控制器定义为:

public class MyController : Controller
{
   private IState _state;

   public MyController(IState state)
   {
       _state = state;
   }

   [HttpGet]
   public ActionResult Index()
   {
      // Fill the state but you cannot change instance!
      _state.A = ...;
      _state.B = ...;

      return View();
   }

   [HttpPost]
   public ActionResult Change()
   {
      // Fill the state but you cannot change instance!
      _state.A = ...;
      _state.B = ...;

      return View();
   }
}

现在您需要两个额外的步骤。您必须使用 PerSessionLifetime 管理器进行 IState 解析,并且必须配置 Unity 来解析控制器及其依赖项 - 有一些 内置支持 ASP.NET MVC 3 中的解析

Unity 不提供 PerSessionLifetime 管理器,因此您必须构建自己的管理器。

public class PerSessionLifetimeManager : LifetimeManager
{
    private readonly Guid _key = Guid.NewGuid();

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

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

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

您可以在配置控制器时使用此生命周期,也可以在统一配置中配置扩展并定义您的 IState

<configuration>
  <configSections>
    <section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Microsoft.Practices.Unity.Configuration" />
  </configSections>
  <unity xmlns="http://schemas.microsoft.com/practices/2010/unity">
    <alias alias="perSession" type="NamespaceName.PerSessionLifetimeManager, AssemblyName"/>
    <alias alias="IState" type="NamespaceName.IState, AssemblyName" />
    <alias alias="State" type="NamespaceName.State, AssemblyName" />
    <container name="Web">
      <register type="IState" mapTo="State" >
        <lifetime type="perSession" />
      </register>
    </container>
  </unity>
</configuration>

If you want to use Unity you must change your implementation little bit. You must define your controller as:

public class MyController : Controller
{
   private IState _state;

   public MyController(IState state)
   {
       _state = state;
   }

   [HttpGet]
   public ActionResult Index()
   {
      // Fill the state but you cannot change instance!
      _state.A = ...;
      _state.B = ...;

      return View();
   }

   [HttpPost]
   public ActionResult Change()
   {
      // Fill the state but you cannot change instance!
      _state.A = ...;
      _state.B = ...;

      return View();
   }
}

Now you need two additional step. You must use PerSessionLifetime manager for your IState resolving and you must configure Unity to resolve controllers and their dependencies - there is some build in support for resolving in ASP.NET MVC 3.

Unity doesn't provide PerSessionLifetime manager so you must build your own.

public class PerSessionLifetimeManager : LifetimeManager
{
    private readonly Guid _key = Guid.NewGuid();

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

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

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

You can use this lifetime when configuring controller or you can configure extension in unity configuration and define your IState:

<configuration>
  <configSections>
    <section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Microsoft.Practices.Unity.Configuration" />
  </configSections>
  <unity xmlns="http://schemas.microsoft.com/practices/2010/unity">
    <alias alias="perSession" type="NamespaceName.PerSessionLifetimeManager, AssemblyName"/>
    <alias alias="IState" type="NamespaceName.IState, AssemblyName" />
    <alias alias="State" type="NamespaceName.State, AssemblyName" />
    <container name="Web">
      <register type="IState" mapTo="State" >
        <lifetime type="perSession" />
      </register>
    </container>
  </unity>
</configuration>
痴情换悲伤 2024-11-13 16:32:57

您可能想使用 ActionFilter 来执行此操作。 ActionFilter 可以从会话状态中获取对象(如果需要的话实例化它),并将其添加到 ActionParameters 集合中。

public class IncludeStateAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(...)
    {
        var currentState = filterContext.HttpContext.Session[Key] as State;
        if (currentState == null)
        {
            currentState = new State();
        }

        filterContext.ActionParameters["state"] = currentState
    }

    public override void OnActionExecuted(...)
    {
        filterContext.HttpContext.Session[Key] = filterContext.ActionParameters["state"];
    }
}

然后,您的索引操作如下所示:

[HttpGet]
[IncludeState]
public ActionResult Index(State state)
{
    // do stuff with state
    return View();
}

我唯一不确定的是您的密钥来自哪里。

我意识到这不使用 Unity,但也许您不需要它。

You might want to do this with an ActionFilter. The ActionFilter could grab the object from session state (instantiating it if needed), and add it to your ActionParameters collection.

public class IncludeStateAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(...)
    {
        var currentState = filterContext.HttpContext.Session[Key] as State;
        if (currentState == null)
        {
            currentState = new State();
        }

        filterContext.ActionParameters["state"] = currentState
    }

    public override void OnActionExecuted(...)
    {
        filterContext.HttpContext.Session[Key] = filterContext.ActionParameters["state"];
    }
}

Then, your Index action looks like this:

[HttpGet]
[IncludeState]
public ActionResult Index(State state)
{
    // do stuff with state
    return View();
}

The only thing I'm unsure about is where your key comes from.

I realize that this doesn't use Unity, but maybe you don't need it.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文