DI в ServiceFabrice Service Remoting - PullRequest
1 голос
/ 26 марта 2020

У меня есть приложение Service Fabri c с одним сервисом, доступ к которому предоставляется Inte rnet ( GatewayService ) через веб-API ASP. NET и несколько внутренних служб, которых нет выставлен Inte rnet (назовем один из них InternalService ). Пока что InternalService также является ASP. NET веб-API, поэтому InternalService.cs имеет метод CreateServiceInstanceListeners(), который выглядит следующим образом:

protected override IEnumerable<ServiceInstanceListener> CreateServiceInstanceListeners()
{
    return new[] {
        new ServiceInstanceListener(serviceContext =>
            new KestrelCommunicationListener(serviceContext, "ServiceEndpoint", (url, listener) =>
                WebHost.CreateDefaultBuilder()
                    .UseStartup<Startup>()
                    .ConfigureServices((context, services) => { services.AddSingleton(serviceContext); })
                    .UseServiceFabricIntegration(listener, ServiceFabricIntegrationOptions.None)
                    .UseUrls(url)
                    .Build()))
    };
}

Класс запуска (в Startup.cs) для InternalService настраивает некоторые службы, такие как добавление SQL DbContext в систему внедрения зависимостей и, конечно, настройка ASP. NET с помощью AddMvc() et c. У меня есть пара ApiControllers, которые предоставляют API.

Это работает, НО Я не получаю никакой реальной безопасности типов с этим, и это обычно делает разработку немного громоздкой, требующей десериализовать результат вручную в моем GatewayService, прежде чем манипулировать им. Поэтому я решил вместо этого go с Service Remoting SF получить метод CreateServiceInstanceListeners(), который выглядит следующим образом:

protected override IEnumerable<ServiceInstanceListener> CreateServiceInstanceListeners()
{
    return this.CreateServiceRemotingInstanceListeners();
}

Затем я скопировал все логи c из контроллеры в InternalService.cs тоже, но это приводит к проблеме: у меня больше нет доступа к моему DbContext, потому что он был внедрен в конструктор ApiController, инстанцированный ASP. NET в соответствии с правилами установить в класс Startup, который больше не используется.

  1. Можно ли таким же образом использовать Startup при использовании Service Remoting?
  2. Можно ли разделить API на несколько классов так же, как ApiControllers разделены на несколько классов? Я чувствую, что все открытые методы в одном и том же классе будут довольно неприятными.

Ответы [ 2 ]

1 голос
/ 29 апреля 2020

Я знаю, что это уже принятый ответ, но я хочу добавить свои два цента.

Как вы уже поняли, удаленное взаимодействие имеет два основных отличия от WebApi:

  1. При наличии интерфейса удаленного взаимодействия у вас есть один класс реализации

  2. Класс реализации удаленного взаимодействия является одноэлементным, поэтому, даже если вы используете DI, как объяснено в принятом ответе, вы все равно не можете внедрить DbContext для запроса.

Я могу дать вам несколько решений этих проблем:

  1. Это просто: создайте больше интерфейсов. Вы можете добавить столько интерфейсов удаленного взаимодействия, сколько захотите в одном сервисе fabri c. Таким образом, вы должны разбить ваш удаленный интерфейс API на меньшие интерфейсы с группами, которые имеют смысл (разделение интерфейса). Но я не думаю, что у вас их должно быть много, потому что это, вероятно, будет означать, что у вашего микросервиса слишком много обязанностей.

  2. Наивный подход к наличию зависимостей на запрос состоит в том, чтобы внедрить фабрики в класс remoting, так что вы можете разрешать и располагать зависимости в каждом методе, а не путем внедрения в конструктор. Но я нашел гораздо лучший подход с использованием Mediatr , который может показаться не тривиальным, но после настройки его очень легко использовать. Это работает так: вы создаете небольшой вспомогательный класс, который получает ILifetimeScope (как вы используете Autofa c) в конструкторе и предоставляет метод Execute. Этот метод создаст дочерний LifetimeScope, разрешит Mediatr и отправит WrapperRequest<TRequest> (обертка - хитрость, так что входные и выходные объекты удаленного взаимодействия не должны зависеть от Mediatr). Это позволит вам реализовать класс Handler для каждой операции удаленного взаимодействия, который будет разрешаться для каждого запроса, чтобы вы могли внедрить зависимости в конструктор, как это делается с контроллером WebApi.

Может показаться странным, если вы не знакомы с Mediatr и Autofa c. Если у меня будет время, я напишу в блоге об этом.

0 голосов
/ 26 марта 2020

Вы можете использовать Autofa c, есть целая страница , которая объясняет, как ее настроить:

  • Добавить Autofa c .ServiceFabri c пакет nuget
  • Настройка DI:

      // Start with the trusty old container builder.
      var builder = new ContainerBuilder();
    
      // Register any regular dependencies.
      builder.RegisterModule(new LoggerModule(ServiceEventSource.Current.Message));
    
      // Register the Autofac magic for Service Fabric support.
      builder.RegisterServiceFabricSupport();
    
      // Register a stateless service...
      builder.RegisterStatelessService<DemoStatelessService>("DemoStatelessServiceType");
    
      // ...and/or register a stateful service.
      // builder.RegisterStatefulService<DemoStatefulService>("DemoStatefulServiceType");
    
      using (builder.Build())
      {
        ServiceEventSource.Current.ServiceTypeRegistered(
          Process.GetCurrentProcess().Id,
          typeof(DemoStatelessService).Name);
    
        // Prevents this host process from terminating so services keep running.
        Thread.Sleep(Timeout.Infinite);
      }
    
  • проверить проект demo .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...