事件中的依赖注入

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);
}