处理作用域方法

问题描述

BinanceSpotClient 实例化 BinanceClientBinanceSocketClient。当 LiveTradeManager 完成执行时,它们必须被处理。我在 dispose 方法上放置了一个断点,它当前没有执行。我是否必须通过让 LiveTradeManager 继承 Idisposable 然后调用 BinanceSpotClient.dispose 来手动调用它?

services.AddScoped<LiveTradeManager>();
services.AddScoped<PaperTradeManager>();
services.AddScoped<ITradeManagerFactory,TradeManagerFactory>();

services.AddScoped<IExchangeClientFactory,ExchangeClientFactory>();
public interface ITradeManager
{
    Task RunAsync();
}

public class LiveTradeManager : ITradeManager
{
    private readonly ILogger _logger;
    private readonly IExchangeClient _exchangeClient;

    public LiveTradeManager(ILogger logger,IExchangeClientFactory exchangeClientFactory)
    {
        _logger = logger;
        _exchangeClient = exchangeClientFactory.GetExchangeClient(exchangeOptions.Value.Exchange);
    }
    
    ...
}

public interface IExchangeClientFactory
{
    IExchangeClient GetExchangeClient(Exchange exchange);
}

public class ExchangeClientFactory : IExchangeClientFactory
{
    private readonly IServiceProvider _serviceProvider;

    public ExchangeClientFactory(IServiceProvider serviceProvider)
    {
        _serviceProvider = serviceProvider;
    }

    public IExchangeClient GetExchangeClient(Exchange exchange)
    {
        return exchange switch
        {
            Exchange.BinanceSpot => ActivatorUtilities.CreateInstance<BinanceSpotClient>(_serviceProvider) ?? throw new NullReferenceException(),_ => throw new ArgumentOutOfRangeException(nameof(exchange),exchange,null)
        };
    }
}

public class BinanceSpotClient : IExchangeClient,Idisposable
{
    private readonly ILogger _logger;
    private readonly IBinanceClient _client;
    private readonly IBinanceSocketClient _socketClient;

    public BinanceSpotClient(ILogger logger,IOptions<ExchangeOptions> exchangeOptions)
    {
        _logger = logger;

        _client = new BinanceClient(new BinanceClientOptions()
        {
            ApiCredentials = new ApiCredentials(exchangeOptions.Value.ApiKey,exchangeOptions.Value.SecretKey),AutoTimestamp = true,AutoTimestampRecalculationInterval = TimeSpan.FromMinutes(30),TradeRulesBehavIoUr = TradeRulesBehavIoUr.AutoComply
        });

        _socketClient = new BinanceSocketClient(new BinanceSocketClientOptions()
        {
            ApiCredentials = new ApiCredentials(exchangeOptions.Value.ApiKey,AutoReconnect = true,ReconnectInterval = TimeSpan.FromSeconds(15)
        });
    }
    
    private bool _disposed = false;

    public void dispose()
    {
        dispose(true);
        GC.SuppressFinalize(this);
    }

    protected virtual void dispose(bool disposing)
    {
        if (_disposed)
            return;

        if (disposing)
        {
            if (_client != null)
            {
                _client.dispose();
            }

            if (_socketClient != null)
            {
                _socketClient.UnsubscribeAll();
                _socketClient.dispose();
            }

            _subject.OnNext(Observable.Never<Unit>());
        }

        _disposed = true;
    }
}

解决方法

我是否必须通过让 LiveTradeManager 继承来手动调用它 IDisposable 然后调用 BinanceSpotClient.Dispose?

如果你不想在容器中注册 IExchangeClient,基本上可以。

考虑向 container 注册 IExchangeClient。如果容器不知道它,它就无法为您调用 Dispose。这意味着它成为你的工作。

显式工厂模式方法(您在此处使用)的一般问题正是您所遇到的。这就是为什么我更喜欢 Autofac 的方法 (https://autofaccn.readthedocs.io/en/latest/resolve/relationships.html / https://autofaccn.readthedocs.io/en/latest/advanced/delegate-factories.html) - 处理是容器的问题,所以你让容器成为工厂,这样它就知道什么时候需要处理

要理解的关键是,使用您当前的代码,容器知道工厂的情况,但知道工厂内部发生了什么。 可以查看代码并看到需要处理的内容,但容器不能。如果实现了IDisposable,容器将处理工厂 - 但不是工厂正在创建的东西

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...