Использование Unity с ASP.NET MVC 3 для объекта, хранящегося в сеансе - PullRequest
2 голосов
/ 13 мая 2011

У меня есть контроллер MVC, который хранит объект в сеансе.Различные действия контроллера извлекают объект из Session, делают с ним что-то и сохраняют его обратно.

Я хотел бы использовать 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().Может быть, есть какой-то волшебный способ добавить параметр к Index(), который может использовать Unity?

Ответы [ 2 ]

2 голосов
/ 15 мая 2011

Если вы хотите использовать 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 manager для разрешения IState и настроить Unity для разрешения контроллеров и их зависимостей - имеется некоторая поддержка для разрешения в ASP.NET MVC 3 .

Unity не предоставляет PerSessionLifetime manager, поэтому вы должны создать свой собственный.

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>
0 голосов
/ 13 мая 2011

Возможно, вы захотите сделать это с помощью 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"];
    }
}

Тогда ваше действие Index будет выглядеть так:

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

Единственное, в чем я не уверен - откуда взялся твой ключ.

Я понимаю, что это не использует Unity, но, возможно, вам это не нужно.

...