事件中的依赖注入
Dependency injection in an event
我们有一个大量使用依赖注入的 .NET Core 应用程序。在我们的 class 中,我们有一个引发的事件,但是,在这个事件中,我们想要使用 DI 对象的实例之一。然而这并不存在,这是可以理解的。
我们如何在活动中使用这个实例?
public class GetSQLDependancyHandler : IRequestHandler<SQLDependancyQuery>
{
private readonly ISqlDependancy _sqlDependancy;
private readonly IMapper _autoMapper;
private readonly IMediator _mediator;
private CancellationToken _cancellationToken;
public GetSQLDependancyHandler( IMapper autoMapper,
ISqlDependancy sqlDependancy,
IMediator mediator)
{
_autoMapper = autoMapper;
_sqlDependancy = sqlDependancy;
_mediator = mediator;
}
public async Task<Unit> Handle(SQLDependancyQuery request, CancellationToken cancellationToken)
{
await _sqlDependancy.IngnightSQLDependancy("ObservationAdmission", "ServiceBroker");
_sqlDependancy.OnTableUpdate += _sqlDependancy_OnTableUpdate1;
_cancellationToken = cancellationToken;
return Unit.Value;
}
private void _sqlDependancy_OnTableUpdate1(object sender, BroadCast e)
{
// THIS IS THE PART THAT DOESN'T EXIST
_mediator.Publish(new SQLDependancyDTO { Id = 1, Date = DateTime.Now, Message = "testmessage" }, _cancellationToken);
}
}
任何建议或我应该寻找的地方将不胜感激。
问题很可能是 _mediator
的生命周期:OnTableUpdate
事件可能会在任何使用 GetSQLDependancyHandler
完成并且对象被清理后很长时间内触发。
常见的解决方案是注入一个 IServiceScopeFactory
对象(这是一个单例),然后您可以在事件处理程序中使用它:
private void _sqlDependancy_OnTableUpdate1(object sender, BroadCast e)
{
using var scope = serviceScopeFactory.CreateScope();
var mediator = scope.ServiceProvider.GetRequiredService<IMediator>();
mediator.Publish(new SQLDependancyDTO { Id = 1, Date = DateTime.Now, Message = "testmessage" }, _cancellationToken);
}
在任何情况下,在处理程序中订阅注入对象的事件可能是不安全的:如果 _sqlDependancy
对象被重用,事件处理程序订阅会保留并且可能会令人惊讶地再次执行未来。
不确定这是否解决了问题,但您可以尝试在订阅时捕获 closure 中的依赖关系。
public async Task<Unit> Handle(SQLDependancyQuery request, CancellationToken cancellationToken)
{
await _sqlDependancy.IngnightSQLDependancy("ObservationAdmission", "ServiceBroker");
_sqlDependancy.OnTableUpdate += (s,e) => _sqlDependancy_OnTableUpdate1(s,e,_mediator);
_cancellationToken = cancellationToken;
return Unit.Value;
}
private void _sqlDependancy_OnTableUpdate1(object sender, BroadCast e, IMediator mediator)
{
mediator.Publish(new SQLDependancyDTO { Id = 1, Date = DateTime.Now, Message = "testmessage" }, _cancellationToken);
}
我们有一个大量使用依赖注入的 .NET Core 应用程序。在我们的 class 中,我们有一个引发的事件,但是,在这个事件中,我们想要使用 DI 对象的实例之一。然而这并不存在,这是可以理解的。
我们如何在活动中使用这个实例?
public class GetSQLDependancyHandler : IRequestHandler<SQLDependancyQuery>
{
private readonly ISqlDependancy _sqlDependancy;
private readonly IMapper _autoMapper;
private readonly IMediator _mediator;
private CancellationToken _cancellationToken;
public GetSQLDependancyHandler( IMapper autoMapper,
ISqlDependancy sqlDependancy,
IMediator mediator)
{
_autoMapper = autoMapper;
_sqlDependancy = sqlDependancy;
_mediator = mediator;
}
public async Task<Unit> Handle(SQLDependancyQuery request, CancellationToken cancellationToken)
{
await _sqlDependancy.IngnightSQLDependancy("ObservationAdmission", "ServiceBroker");
_sqlDependancy.OnTableUpdate += _sqlDependancy_OnTableUpdate1;
_cancellationToken = cancellationToken;
return Unit.Value;
}
private void _sqlDependancy_OnTableUpdate1(object sender, BroadCast e)
{
// THIS IS THE PART THAT DOESN'T EXIST
_mediator.Publish(new SQLDependancyDTO { Id = 1, Date = DateTime.Now, Message = "testmessage" }, _cancellationToken);
}
}
任何建议或我应该寻找的地方将不胜感激。
问题很可能是 _mediator
的生命周期:OnTableUpdate
事件可能会在任何使用 GetSQLDependancyHandler
完成并且对象被清理后很长时间内触发。
常见的解决方案是注入一个 IServiceScopeFactory
对象(这是一个单例),然后您可以在事件处理程序中使用它:
private void _sqlDependancy_OnTableUpdate1(object sender, BroadCast e)
{
using var scope = serviceScopeFactory.CreateScope();
var mediator = scope.ServiceProvider.GetRequiredService<IMediator>();
mediator.Publish(new SQLDependancyDTO { Id = 1, Date = DateTime.Now, Message = "testmessage" }, _cancellationToken);
}
在任何情况下,在处理程序中订阅注入对象的事件可能是不安全的:如果 _sqlDependancy
对象被重用,事件处理程序订阅会保留并且可能会令人惊讶地再次执行未来。
不确定这是否解决了问题,但您可以尝试在订阅时捕获 closure 中的依赖关系。
public async Task<Unit> Handle(SQLDependancyQuery request, CancellationToken cancellationToken)
{
await _sqlDependancy.IngnightSQLDependancy("ObservationAdmission", "ServiceBroker");
_sqlDependancy.OnTableUpdate += (s,e) => _sqlDependancy_OnTableUpdate1(s,e,_mediator);
_cancellationToken = cancellationToken;
return Unit.Value;
}
private void _sqlDependancy_OnTableUpdate1(object sender, BroadCast e, IMediator mediator)
{
mediator.Publish(new SQLDependancyDTO { Id = 1, Date = DateTime.Now, Message = "testmessage" }, _cancellationToken);
}