У меня есть одна зарегистрированная зависимость следующим образом:
interface IDependency { }
class DependencyImpl : IDependency { }
Запуск:
services.AddScoped<IDependency, DependencyImpl>();
Это работает так, как я хочу, чтобы использовать один и тот же экземпляр в области действия моего WebЗапросы API.
Однако в одном фоновом сервисе я бы хотел сказать, к какому экземпляру он будет обращаться:
class MyBackgroundService
{
private readonly IServiceScopeFactory _scopeFactory; // set in ctor
public void DoStuff()
{
var itens = GetItens();
var dependencyInstance = new DependencyImpl();
Parallel.ForEach(itens, (item) =>
{
using(var scope = _scopeFactory.CreateScope())
{
scope.SwapDependencyForThisScopeOnly<IDependency>( () => dependencyInstance ); // something like this
var someOtherService = scope.ServiceProvider.GetRequiredService<ItemService(); // resolve subsequent services with provided dependencyInstance
someOtherService.Process(item);
}
});
}
}
Я не могу повторно использовать тот же Scope, потому что ItemService (и/ или его зависимости) использует другие сервисы с областью действия, которыми нельзя поделиться. Также я не хочу заменять разрешение зависимостей для всего приложения.
Можно ли здесь делать то, что я хочу? Имеет ли это смысл?
Я использую dotnet core 2.2 с контейнером IoC по умолчанию для этого.
Редактировать в ответ на @Steven: DependencyImpl содержит конфигурации для того, какпредмет будет обработан. Один из них включает относительно дорогой запрос. DependencyImpl также вводится в график более одного раза. Таким образом, в настоящее время он читает конфигурацию один раз, кэширует ее в частных свойствах и использует кэшированную версию при последующих чтениях. Поскольку я знаю, что здесь я буду повторно использовать одну и ту же конфигурацию для всех типов, я бы хотел избежать повторного чтения конфигурации для каждого параллельного выполнения.
Моя зависимость от реального мира больше похожа на эту:
interface IDependency
{
Task<Configuration> GetConfigurationAsync();
}
class DependencyImpl : IDependency
{
private readonly Configuration _configuration;
private readonly DbContext _dbContext;
ctor(DbContext dbContext)
{
_dbContext = dbContext;
}
public async Task<Configuration> GetConfigurationAsync()
{
if(_configuration is null)
{
// read configurations
}
return _configuration;
}
}
Я понимаю, что мой класс не является потокобезопасным. Я должен был бы заставить чтение в начале и / или добавить некоторую безопасность потока здесь.
Кроме того, те обработки, которые происходили во время жизненного цикла веб-запроса, и фоновая служба - это новое. Я бы предпочел изменить как можно меньше существующего кода, потому что тестов на месте немного, и, конечно, ограничения по времени зависят от возможностей.