Asp. net core Как зарегистрировать IHostedService, который также содержит настраиваемый интерфейс - PullRequest
0 голосов
/ 20 июня 2020

Как мне зарегистрировать свойство класса, который содержит как IHostedService, так и настраиваемый интерфейс, например IMyInterface?

Как в

class BackgroundTaskScheduler : BackgroundService, ITaskScheduler {...}

Если он настроен следующим образом:

services.AddHostedService<BackgroundTaskScheduler>();

А затем попробуйте ввести его в клиент, например:

public class Foo
{
    Foo(ITaskScheduler taskScheduler) {...}
}

Генерируется ошибка, указывающая, что ASP. net не могу разрешить BackgroundTaskScheduler, почему?

1 Ответ

0 голосов
/ 20 июня 2020

После прочтения множества идей, в том числе:

Но как заставить его работать, не требуя класса-оболочки? Я объединил идеи, обсужденные выше, в следующие два метода расширения.

Внедрение зависимостей интерфейса

Если вам нравится использовать интерфейс 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>();
        }

Наслаждайтесь!

...