我的场景:
- 控制器(需要 repo)
- 仓库(需要
IUnitOfWork
)
- 操作过滤器(同样需要
IUnitOfWork
)
问题:
动作过滤器中的 DI 一直困扰着我。我喜欢 Joseph的方法,真的很喜欢。在每个请求之前创建(或启动)我的工作单元对我来说似乎很自然。由于操作过滤器可能会被缓存,它们不使用与控制器相同的依赖关系范围。因此,需要 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<,>));
}
}
NhSessionFactory
封装了我的 Hibernate 配置,并允许获取单个 ISessionFactory
在应用程序中使用。
NhUnitOfWork
实现了我的 IUnitOfWork
接口,并处理会话和事务管理。
动作筛选器属性(改编自 Joseph's answer):
public class UnitOfWorkAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(HttpActionContext actionContext)
{
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;
}
}
}
最后是我的基础控制器:
[UnitOfWork]
public class ControllerBaseUow : ApiController {}
它能够工作是因为在OnActionExecuting
中,我们使用了与控制器相同的依赖范围。
然后像通常使用 DI 一样工作即可 :)