处理作用域方法
Disposing scoped methods
BinanceSpotClient 实例化 BinanceClient
和 BinanceSocketClient
。当 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, exchangeOptions.Value.SecretKey),
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;
}
}
Do I have to manually call it by making LiveTradeManager inherit
IDisposable and then call 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
,容器将处理工厂——但不是工厂正在创建的东西.
BinanceSpotClient 实例化 BinanceClient
和 BinanceSocketClient
。当 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, exchangeOptions.Value.SecretKey),
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;
}
}
Do I have to manually call it by making LiveTradeManager inherit IDisposable and then call 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
,容器将处理工厂——但不是工厂正在创建的东西.