Мой сценарий:
- Контроллер (необходимо репо)
- Репо (необходимо
IUnitOfWork
) - Фильтр действий (нужен
IUnitOfWork
также)
Проблема:
DI в действии фильтра меня беспокоит некоторое время.Мне нравится подход Джозефа , мне действительно нравится.Создание моей единицы работы (или начало) перед каждым запросом кажется мне естественным.Поскольку фильтры действий могут кэшироваться, они не используют ту же область зависимости, что и контроллеры. Следовательно, требуется установка Setter.
Решение:
Сконфигурируйте Structuremap так же, как если бы у меня не было фильтров действий.Примерно так:
public class NHibernateRegistry : Registry
{
public NHibernateRegistry()
{
For<ISessionFactory>).Singleton().Use(
NhSessionFactoty.Instance.SessionFactory);
For<IUnitOfWork>().HybridHttpOrThreadLocalScoped().Use<NhUnitOfWork>();
For(typeof(IBaseRepository<,>)).Use(typeof(BaseRepository<,>));
}
}
NhSessionFactoty
инкапсулирует мою конфигурацию гибернации и позволяет получить один ISessionFactory
для использования в моем приложении.NhUnitOfWork
реализует мой IUnitOfWork
интерфейс и управляет сессией и управлением транзакциями.
Атрибут фильтра действий (адаптирован из ответ Джозефа ):
public class UnitOfWorkAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(HttpActionContext actionContext)
{
/* Check this line, it's a problem solver!! */
var uow = (IUnitOfWork)actionContext.Request.GetDependencyScope()
.GetService(typeof(IUnitOfWork));
uow.Begin();
}
public override void OnActionExecuted(
HttpActionExecutedContext actionExecutedContext)
{
var uow = (IUnitOfWork)actionExecutedContext.Request.GetDependencyScope()
.GetService(typeof(IUnitOfWork));
try
{
if (actionExecutedContext.Exception == null)
uow.Commit();
else
uow.Rollback();
}
catch
{
uow.Rollback();
throw;
}
/*finally
{
uow.Dispose();
}*/ // Resources are released in Application_EndRequest (Globals.cs)
}
}
инаконец, мой базовый контроллер:
[UnitOfWork]
public class ControllerBaseUow : ApiController {}
/* Then, in my case, I inject Repositories via contructor */
Он работает, потому что в OnActionExecuting
мы получаем ту же область зависимости, которая используется в контроллерах.
, тогда вы работаете, как обычно, с DI:)