как использовать простой инжектор для рабочей роли Azure

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

Ссылки

  1. Unity to Worker Role: https://alexandrebrisebois.wordpress.com/2013/04/14/building-windows-azure-services-without-compromising-testability/

  2. Приложение SimpleInjector для консоли: http://simpleinjector.readthedocs.io/en/latest/consoleintegration.html

Мои вопросы

  1. Ссылка-1, Unity использует using (var uc = new UnityContainer()){...}, но SimpleInjector имеет ThreadScopedLifestyle или AsyncScopedLifestyle. Какой из них я использую?

  2. Ссылка-2 имеет класс static Main, static readonly Container и static contructor. Нужно ли определять static Container для роли Worker? как насчет static constructor для регистрации зависимостей?

  3. Я реализовал, как показано ниже в разделе Моя реализация. Правильно ли реализован этот код?

Справочный код

ссылка 1;

static class Program
{
    static readonly Container container;

    static Program()
    {
        container = new Container();

        container.Register<IUserRepository, SqlUserRepository>();
        container.Register<MyRootType>();

        container.Verify();
    }

    static void Main()
    {
        var service = container.GetInstance<MyRootType>();
        service.DoSomething();
    }
}

ссылка 2;

public class WorkerRole : RoleEntryPoint
{
 public override void Run()
 {
     // This is a sample worker implementation. Replace with your logic.
     Trace.WriteLine("Worker entry point called", "Information");

     using (var uc = new UnityContainer())
     {
         uc.RegisterType<ILogger, TableStorageLogger>();
         uc.RegisterType<IEnumerable<IMessageHandler>, IMessageHandler[]>();

         var processor = uc.Resolve<MessageProcessor>();

         while (true)
         {
             processor.Process();
             Thread.Sleep(10000);
             Trace.WriteLine("Working", "Information");
         }
     }
 }

Моя реализация

Я подумал, что (1) Container может быть достаточно, чтобы быть static, (2) OnStart — хорошее место для регистрации служб, и (3) я предполагал, что экземпляры служб создаются и удаляются для каждого цикла.

public class WorkerRole : RoleEntryPoint
{
    static readonly Container container = new Container();

    public override void Run()
    {
        while (true)
        {
            using (ThreadScopedLifestyle.BeginScope(container))
            {
                var service = container.GetInstance<SomeService>();
                service.DoSomething();
            }
        }
    }

    public override bool OnStart(){
        // define.
        container.Register<SomeService>();
        container.Register<ProcessRecorderSetting>();
        container.Verify();
    } 
}

Примечание. Я не знаю, работает ли приведенный выше код.


person Youngjae    schedule 08.06.2017    source источник


Ответы (1)


Ссылка-1, Unity использует использование (var uc = new UnityContainer()){...}, но SimpleInjector имеет ThreadScopedLifestyle или AsyncScopedLifestyle. Какой из них я использую?

Если я не ошибаюсь, рабочая роль Azure — это недолговечное приложение, которое запускается для выполнения одной простой задачи, а затем быстро умирает, как и в случае с консольным приложением.

Учитывая DI, это делает разработку рабочей роли очень похожей на разработку консольного приложения. Это означает:

  • Приложение недолговечно
  • Будет выполняться только один запрос (по сравнению с параллельным выполнением нескольких запросов, как это происходит с веб-сервисами/приложениями).
  • Существует предельный набор зависимостей, которые необходимо зарегистрировать.

Это означает, что, поскольку приложение является однопоточным и недолговечным, нет необходимости использовать образ жизни с ограниченной областью действия (такой как ThreadScopedLifestyle или AsyncScopedLifestyle). Вместо этого вы можете легко зарегистрировать все зависимости как singleton, разрешить корень, вызвать его метод и удалить контейнер.

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

Reference-2 имеет статический основной класс, статический контейнер только для чтения и статический конструктор. Нужно ли определять статический контейнер для рабочей роли? как насчет статического конструктора для регистрации зависимостей?

Хотя статические конструкторы обеспечивают потокобезопасность и одноэлементное поведение бесплатно, они, тем не менее, усложняют отладку в случае возникновения исключения, поскольку реальная ошибка заключена в файл TypeInitializationException. Однако ваш cctor упрощает инициализацию вашего статического поля Container. Хорошо иметь Container в статическом поле.

Однако, поскольку эти типы приложений очень малы и имеют лишь небольшой набор зависимостей, контейнер должен не использовать контейнер внедрения зависимостей вообще. Вместо этого используйте Pure DI. Это может показаться странным советом от того, кто разрабатывает и поддерживает DI-контейнер, но я счел более практичным использовать Pure DI для небольших приложений, особенно когда все ваши регистры в любом случае одноэлементные. Преимущества:

  • У вас есть поддержка во время компиляции при построении вашего графа объектов.
  • Это предотвращает необходимость использования стороннего инструмента
  • Когда дело доходит до этапа инициализации приложения, использование DI-контейнеров сопряжено с большими накладными расходами, в то время как рабочие роли должны запускаться быстро.
  • Может быть значительно проще для небольших графов объектов.
person Steven    schedule 08.06.2017