Настройка внедрения зависимостей в Service Fabric с использованием стандартного контейнера ASP.NET Core DI

Я хотел бы использовать контейнер DI по умолчанию в ASP.NET Core для настройки DI для моего проекта Service Fabric.

//This is what I've got so far, and it works great
ServiceRuntime.RegisterServiceAsync(
  "MyServiceType",
  context => new MyService(context, new MyMonitor()
).GetAwaiter().GetResult();

//This is how I use it
public MyService(StatefulServiceContext context, IMonitor myMonitor)
  : base(context)
{
  this._myMonitor = myMonitor;           
}

Как бы я настроить DI, если MyMonitor класс зависит от ConfigProvider класс, как это:

public MyMonitor(IConfigProvider configProvider)
{
  this._configProvider = configProvider;
}

2 ответа

Решение

Я думаю, что этот вопрос даст вам некоторый свет: почему ServiceRuntime.RegisterServiceAsync возвращает до завершения функции serviceFactory?

Технически, ServiceRuntime.RegisterServiceAsync() это регистрация зависимостей, она требует, чтобы вы передали serviceTypeName и фабричный метод, отвечающий за создание сервисов Func<StatelessServiceContext, StatelessService> serviceFactory

Фабричный метод получает контекст и возвращает сервис (с сохранением состояния или без сохранения состояния).

Для DI вы должны заранее зарегистрировать все зависимости и вызвать службы разрешения для создания конструктора, например:

var provider = new ServiceCollection()
            .AddLogging()
            .AddSingleton<IFooService, FooService>()
            .AddSingleton<IMonitor, MyMonitor>()
            .BuildServiceProvider();

ServiceRuntime.RegisterServiceAsync("MyServiceType",
    context => new MyService(context, provider.GetService<IMonitor>());
}).GetAwaiter().GetResult();

PS:

  • Никогда не регистрируйте контекст (StatelessServiceContext\StatefulServiceContext) в DI, в подходе с общим процессом несколько разделов могут быть размещены в одном процессе и будут иметь несколько контекстов.
  • Этот фрагмент кода не тестировался, я использовал в прошлом, не имею доступа к проверке, если совпадает с тем же кодом, но очень близок к используемому подходу, возможно, потребуются некоторые изменения.

Привет @OscarCabreraRodríguez

Я работаю над проектом, который упрощает разработку надежных сервисов Service Fabric и имеет отличную встроенную поддержку сценариев внедрения зависимостей.

Вы можете найти страницу общей информации о проекте, вики и конкретную информацию о внедрении зависимостей здесь.

Идея в том, что проект отвлекает вас от работы с Service экземпляр, вместо этого предоставляя вам набор более конкретных объектов.

Вот простой пример приложения ASP.NET Core:

public static void Main(string[] args)
{
  new HostBuilder()
    .DefineStatefulService(
      serviceBuilder =>
      {
        serviceBuilder
          .UseServiceType("ServiceType")
          .DefineAspNetCoreListener(
            listenerBuilder =>
            {
              listenerBuilder
                .UseEndpoint("ServiceEndpoint")
                .UseUniqueServiceUrlIntegration()
                .ConfigureWebHost(
                  webHostBuilder => 
                  { 
                    webHostBuilder
                      .ConfigureServices(
                        services =>
                        {
                          // You can configure as usual.
                          services.AddTransient<IMyService, MyService>();
                        })
                      .UseStartup<Startup>(); 
                  });
            });
      })
      .Build()
      .Run();

[Route("api")]
public class ApiController : Controller
{
  public ApiController(IMyService service) { }

  [HttpGet]
  [Route("value")]
  public string GetValue()
  {
    return $"Value from {nameof(ApiController)}";
  }
}

Надеюсь, я правильно понимаю ваш вариант использования и эта информация актуальна.

Другие вопросы по тегам