【问题标题】:Dependency injection in an event事件中的依赖注入
【发布时间】:2021-11-28 17:12:49
【问题描述】:

我们有一个大量使用依赖注入的 .NET Core 应用程序。在我们的类中,我们有一个引发的事件,然而,在这个事件中,我们想要使用一个 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);
    }
}

任何建议或我应该寻找的地方将不胜感激。

【问题讨论】:

  • IMediator 的生命周期是多少?它是作用域,单例,...?
  • 我不能真正告诉你正确的答案,但我可以告诉你订阅 OnTableUpdate 不应该在处理程序中完成。要么将 OnTableUpdate1 代码拉入 Handle 方法,要么为该代码创建一个单独的处理程序
  • 当您说“不存在”时,您的意思是它为空吗?对于初学者,将构造函数更改为使用_mediator = mediator ?? throw new ArgumentNullException(nameof(mediator));,这样您就可以确保它的构造正确。其次检查这个实例的生命周期,它是否在调用处理程序之前被释放?

标签: c# asp.net-core .net-core dependency-injection


【解决方案1】:

问题很可能是_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 对象被重用,事件处理程序订阅将保持不变,并且将来可能会再次执行。

【讨论】:

    【解决方案2】:

    不确定这是否解决了问题,但您可以尝试在订阅时捕获 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);
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-12-02
      • 1970-01-01
      • 2020-11-27
      • 1970-01-01
      • 2014-04-03
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多