我遵循了这个article并且除了依赖注入(部分)之外一切正常。在我的项目中,我正在使用unity,我正在尝试创建一个自定义Transaction属性,其目的是在执行操作之前启动NHibernate事务,并在方法执行后提交/回滚事务。
这是我的属性的定义: -
this.svgContainer.append('rect')
.attr('x', 0)
.attr('y', 0)
.attr('width', '100%')
.attr('height', this.maxHeight)
.attr('clip-path', `url(#${this.options.selectionAreaClipId})`)
.classed('selectionArea', true);
以下是我的TransactionFilter的定义
public class TransactionAttribute : Attribute
{
}
我创建了一个自定义过滤器提供程序,它使用unity来构造此过滤器。
public class TransactionFilter : IActionFilter
{
private readonly IUnitOfWork _unitOfWork;
public TransactionFilter(IUnitOfWork uow) {
_unitOfWork = uow;
}
public Task<HttpResponseMessage> ExecuteActionFilterAsync(HttpActionContext actionContext, CancellationToken cancellationToken, Func<Task<HttpResponseMessage>> continuation) {
var transAttribute = actionContext.ActionDescriptor.GetCustomAttributes<TransactionAttribute>().SingleOrDefault();
if (transAttribute == null) {
return continuation();
}
var transaction = uow.BeginTransaction();
return continuation().ContinueWith(t =>
{
try{
transaction.Commit();
return t.Result;
}
catch(Exception e)
{
transaction.Rollback();
return new ExceptionResult(ex, actionContext.ControllerContext.Controller as ApiController).ExecuteAsync(cancellationToken).Result;
}
}
}
}
我在UnityWebApiActivator中注册了UnityActionFilterProvider(我使用的是Unity.AspNet.WebApi包),如下所示
public class UnityActionFilterProvider
: ActionDescriptorFilterProvider,
IFilterProvider
{
private readonly IUnityContainer container;
public UnityActionFilterProvider(IUnityContainer container)
{
this.container = container;
}
public new IEnumerable<FilterInfo> GetFilters(HttpConfiguration configuration, HttpActionDescriptor actionDescriptor)
{
foreach (IActionFilter actionFilter in container.ResolveAll<IActionFilter>())
{
// TODO: Determine correct FilterScope
yield return new FilterInfo(actionFilter, FilterScope.Global);
}
}
}
问题是,对于任何操作的第一个请求,一切正常,但后续对同一操作的请求不会重新创建TransactionFilter,这意味着它不会调用构造函数来分配新的UOW。我不认为我可以禁用动作过滤器缓存。
我现在唯一的选择是使用服务定位器模式并使用ExecuteActionFilterAsync中的容器获取UOW实例,在我看来,这样做会破坏我的目的,我最好实现自定义ActionFilterAttribute。
有什么建议吗?
答案 0 :(得分:1)
就我多年来的情况而言,Web应用程序启动代码中发生的事情基本上具有Singleton生命周期。该代码只运行一次。
这意味着每个过滤器只有一个实例。这对性能有好处,但不适合您的场景。
这个问题的最简单的解决方案,虽然有点漏洞,但是注入抽象工厂而不是依赖本身:
public class TransactionFilter : IActionFilter
{
private readonly IFactory<IUnitOfWork> _unitOfWorkFactory;
public TransactionFilter(IFactory<IUnitOfWork> uowFactory) {
_unitOfWorkFactory = uowFactory;
}
// etc...
然后使用ExecuteActionFilterAsync
方法中的工厂:
var transaction = _unitOfWorkFactory.Create().BeginTransaction();
在我看来,更优雅的解决方案是使用适应TransactionFilter
的{{3}},但上述答案可能更容易理解。