Подробнее
Я попытался создать структуру фоновой обработки, используя рекомендованный интерфейс IHostedService
в ASP.NET 2.1. Я регистрирую услуги следующим образом:
services.AddSingleton<AbstractProcessQueue<AbstractImportProcess>>();
services.AddHostedService<AbstractBackgroundProcessService<AbstractImportProcess>>();
services.AddSignalR();
AbstractProcessQueue
- это просто оболочка вокруг BlockingCollection
процессов, которые можно ставить в очередь и снимать с очереди. AbstractBackgroundProcessService
реализует интерфейс IHostedService
и ищет в очереди новые процессы, которые он может запустить.
Теперь проблема начинается, когда внутри хаба SignalR
я пытаюсь получить ссылку на службу фоновой обработки через механизмы Dependency Injection
. Я пробовал следующие решения, но ни одно из них не работает должным образом:
Вариант 1:
public HubImportClient(IServiceProvider provider)
{
//This returns null.
var service = provider.GetService<AbstractBackgroundProcessService<AbstractImportProcess>>();
}
Вариант 2:
public HubImportClient(IServiceProvider provider)
{
//This returns null.
var service = (AbstractBackgroundProcessService<AbstractImportProcess>) provider.GetService(typeof(AbstractBackgroundProcessService<AbstractImportProcess>>));
}
Вариант 3:
public HubImportClient(IServiceProvider provider)
{
//This throws an exception, because the service is missing.
var service = provider.GetRequiredService<AbstractBackgroundProcessService<AbstractImportProcess>>();
}
Вариант 4:
public HubImportClient(IServiceProvider provider)
{
//This throws an exception, because the service is missing.
var service = (AbstractBackgroundProcessService<AbstractImportProcess>) provider.GetRequiredService(typeof(AbstractBackgroundProcessService<AbstractImportProcess>);
}
Вариант 5:
public HubImportClient(IServiceProvider provider)
{
//This returns a correct service, but prevents me from adding additional AbstractBackgroundProcessService implementations with different type parameters.
//Additionally, it seems like this reference was newly created, and not the instance that was created on application startup (i.e. the hash codes are different, and the constructor is called an additional time).
var service = provider.GetService<IHostedService>();
if(service is AbstractBackgroundProcessService<AbstractProcessService>)
{ this.Service = (AbstractBackgroundProcessService<AbstractProcessService>) service;}
}
Вариант 6:
public HubImportClient(IServiceProvider provider)
{
//This works similarly to the previous option, and allows multiple implementations, but the constructor is still called twice and the instances thus differ.
AbstractBackgroundProcessService<AbstractImportProcess> service = null;
foreach(IHostedService service in provider.GetServices<IHostedService>())
{
if(service is AbstractBackgroundProcessService<AbstractImportProcess>)
{
service = (AbstractBackgroundProcessService<AbstractImportProcess>) service;
break;
}
}
}
Вариант 7:
public HubImportClient(IServiceProvider provider)
{
//This just skips the for each loop all together, because no such services could be found.
AbstractBackgroundProcessService<AbstractImportProcess> service = null;
foreach(AbstractBackgroundProcessService<AbstractImportProcess> current in provider.GetServices<AbstractBackgroundProcessService<AbstractImportProcess> >())
{
service = current;
break;
}
}
Вариант 8:
//This works, but prevents multiple implementations again.
public HubImportClient(IHostedService service)
{
this.Service = service;
}
Вариант 9:
//This does not work again.
public HubImportClient(AbstractBackgroundProcessService<AbstractImportProcess> service)
{
this.Service = service;
}
Вопрос
Итак, у меня остается вопрос: как мне получить ссылку на реализацию IHostedService
, чтобы:
(a): я могу ввести несколько экземпляров службы, которые отличаются только параметром типа (например, размещенная служба для AbstractImportProcess
es и одна для AbstractExportProcess
es)
(b): существует только один экземпляр IHostedService
для этого конкретного параметра типа.
Заранее спасибо за любую помощь!