После прочтения множества идей, в том числе:
Но как заставить его работать, не требуя класса-оболочки? Я объединил идеи, обсужденные выше, в следующие два метода расширения.
Внедрение зависимостей интерфейса
Если вам нравится использовать интерфейс DI, как в Bar.Bar(IFoo foo)
, тогда используйте этот:
/// <summary>
/// Used to register <see cref="IHostedService"/> class which defines an referenced <typeparamref name="TInterface"/> interface.
/// </summary>
/// <typeparam name="TInterface">The interface other components will use</typeparam>
/// <typeparam name="TService">The actual <see cref="IHostedService"/> service.</typeparam>
/// <param name="services"></param>
public static void AddHostedApiService<TInterface, TService>(this IServiceCollection services)
where TInterface : class
where TService : class, IHostedService, TInterface
{
services.AddSingleton<TInterface, TService>();
services.AddSingleton<IHostedService>(p => (TService) p.GetService<TInterface>());
}
Использование:
public void ConfigureServices(IServiceCollection services)
{
services.AddHostedApiService<ITaskScheduler, BackgroundTaskScheduler>();
}
Внедрение зависимости конкретного класса
Если вы хотите использовать внедрение конкретного класса, как в Bar.Bar(Foo foo)
, используйте:
/// <summary>
/// Used to register <see cref="IHostedService"/> class which defines an interface but will reference the <typeparamref name="TService"/> directly.
/// </summary>
/// <typeparam name="TService">The actual <see cref="IHostedService"/> service.</typeparam>
public static void AddHostedApiService<TService>(this IServiceCollection services)
where TService : class, IHostedService
{
services.AddSingleton<TService>();
services.AddSingleton<IHostedService>(p => p.GetService<TService>());
}
Использование:
public void ConfigureServices(IServiceCollection services)
{
services.AddHostedApiService<BackgroundTaskScheduler>();
}
Наслаждайтесь!