Зарегистрируйте обратный вызов в Autofac и снова создайте контейнер в обратном вызове - PullRequest
0 голосов
/ 29 октября 2018

У меня есть основное приложение dotnet. Мой Startup.cs регистрирует типы / реализации в Autofac. Для одной из моих регистраций требуется предыдущий доступ к услуге.

var containerBuilder = new ContainerBuilder();
containerBuilder.RegisterSettingsReaders(); // this makes available a ISettingsReader<string> that I can use to read my appsettings.json
containerBuilder.RegisterMyInfrastructureService(options => 
{
   options.Username = "foo" //this should come from appsettings
});
containerBuilder.Populate(services);
var applicationContainer = containerBuilder.Build();

Дилемма заключается в том, что к тому времени, когда мне нужно .RegisterMyInfrastructureService, мне нужно иметь доступ к ISettingsReader<string>, который был зарегистрирован как раз перед этим (контейнер Autofac еще не был построен).

Я читал о регистрации с помощью обратного вызова для выполнения чего-либо после того, как контейнер autofac был собран. Так что я мог бы сделать что-то вроде этого:

builder.RegisterBuildCallback(c =>
{
     var stringReader = c.Resolve<ISettingsReader<string>>();
     var usernameValue = stringReader.GetValue("Username");
     //now I have my username "foo", but I want to continue registering things! Like the following:
     containerBuilder.RegisterMyInfrastructureService(options => 
     {
         options.Username = usernameValue 
     });
     //now what? again build?
});

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

Могу ли я просто позвонить снова builder.Build() в конце моего обратного вызова, чтобы контейнер просто перестраивался без каких-либо проблем? Это кажется немного странным, потому что компоновщик уже собран (поэтому был выполнен обратный вызов).

Как лучше всего решить эту дилемму с помощью автофака?

ОБНОВЛЕНИЕ 1: Я читал, что такие вещи, как builder.Update (), теперь устарели, потому что контейнеры должны быть неизменяемыми. Что подтверждает мое подозрение, что сборка контейнера, добавление новых регистраций и сборка заново - не очень хорошая практика.

Другими словами, я могу понять, что использование обратного вызова для построения реестра не должно использоваться для регистрации дополнительных вещей. Но тогда остается вопрос: как бороться с этими проблемами?

1 Ответ

0 голосов
/ 02 ноября 2018

Эта проблема обсуждения объясняет многое, включая способы обойти необходимость обновления контейнера. Я подведу итоги здесь, но в этом выпуске есть много информации, которую не имеет смысла пытаться копировать повсюду.

  • Ознакомьтесь с всеми способами регистрации компонентов и передачи параметров . Не забывайте о таких вещах, как разрешенные параметры, модули, которые могут динамически размещать параметры, и т. Д.
  • Лямбда-регистрации решают почти все эти проблемы, которые мы видели. Если вам нужно зарегистрировать что-то, что обеспечивает конфигурацию, а затем, позже, использовать эту конфигурацию как часть другой регистрации - лямбды будут огромными.
  • Рассмотрим промежуточные интерфейсы, такие как создание IUsernameProvider с поддержкой ISettingsReader<string>. IUsernameProvider может быть лямбда-выражением (разрешить некоторые настройки, прочитать конкретную настройку и т. Д.), А затем нижестоящие компоненты могут получить IUsernameProvider напрямую.

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

Лично я обычно начну с лямбда-подхода.

...