Как ссылаться на размещенный сервис в .Net Core 3? - PullRequest
2 голосов
/ 27 октября 2019

Вернувшись в .net core 2, я создал размещенный сервис с настраиваемым свойством, таким как:

 public class MyService : BackgroundService 
{
public bool IsRunning {get;set;}
...

, которое можно настроить в файле startup.cs, например:

public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton<IHostedService,HostedServices.MyService>();
...

И тогда я мог бы сослаться на это в другом месте на странице бритвы, как:

public class IndexModel : PageModel
{
    private readonly IHostedService _mySrv;
    public IndexModel(IHostedService mySrv) => _mySrv = mySrv;

    [BindProperty]
    public bool IsRunning { get; set; }

    public void OnGet() => IsRunning = ((HostedServices.MyService)_mySrv).IsRunning;
}

Теперь, когда я обновился до .net core 3, мой запуск изменился на:

services.AddHostedService<HostedServices.MyService>();

Номоя ссылка DI в IndexModel больше не дает мне мой MyService, вместо этого он дает мне объект типа GenericWebHostService, из которого я не могу понять, как получить мой пользовательский MyService. Изменение 'IHostedService' на 'MyService' в IndexModel также не работает, я получаю ошибку 'Не удается разрешить службу'.

Как получить экземпляр MyService обратно из внедрения зависимости?

1 Ответ

4 голосов
/ 27 октября 2019

В версии 2.2, с которой вы работали, в основном случайно. Всякий раз, когда вы регистрируете несколько реализаций для службы, последняя из них является «выигравшей». Например, возьмите следующий код:

services.AddSingleton<IHostedService, HostedService1>();
services.AddSingleton<IHostedService, HostedService2>();

// ...

public IndexModel(IHostedServie hostedService) { }

Реализация IHostedService, которая вводится в IndexModel, является HostedService2;последний зарегистрированный. Если бы IndexModel было обновлено до IEnumerable<IHostedService>, оно получило бы обе реализации в порядке регистрации:

public IndexModel(IEnumerable<IHostedService> hostedServices) { }

Когда я сказал "случайно", яозначает, что в вашем примере only HostedServices.MyService регистрируется, поэтому он также является последним зарегистрированным и, следовательно, он "выигрывает".

В 3.0 при использовании Generic Host , реализация IHostedService, GenericWebHostService, обрабатывает веб-запросы. Это создает проблему, поскольку GenericWebHostService зарегистрировано после HostedServices.MyService. Я надеюсь, что к настоящему времени ясно, что именно по этой причине IHostedService, который вы запрашиваете в IndexModel, не соответствует ожидаемому.

С точки зрения решения, я предлагаю выполнить две регистрации:

services.AddSingleton<HostedServices.MyService>();
services.AddHostedService(sp => sp.GetRequiredService<HostedServices.MyService>());

Затем обновите IndexModel, чтобы он требовал вашей конкретной реализации:

public IndexModel(HostedServices.MyService myService) { }

Это позволит вам настроить вашу конкретную реализацию на IHostedService. Он регистрируется дважды для двух разных типов сервисов, но создается только один экземпляр.

...