Разрешение зависимостей AutoFac внутри класса модуля

Я новичок в AutoFac и в настоящее время использую пользовательские модули внутри моего приложения, чтобы загружать некоторые основные системы F #. Код, который я использую,

var builder = new ContainerBuilder();
builder.RegisterType<DefaultLogger>().As<IDefaultLogger>();
builder.RegisterModule(new ConfigurationSettingsReader("autofac"));
builder.Build();

И внутри моей конфигурации приложения у меня есть соответствующая логика для запуска соответствующих систем. Я хотел бы иметь доступ к DefaultLogger внутри моих модулей. Для метаданных базового класса модуля доступны следующие параметры:

protected virtual void AttachToComponentRegistration(IComponentRegistry componentRegistry, IComponentRegistration registration);

protected virtual void AttachToRegistrationSource(IComponentRegistry componentRegistry, IRegistrationSource registrationSource);

public void Configure(IComponentRegistry componentRegistry);

protected virtual void Load(ContainerBuilder builder);

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

Ответ 1

Ответ оказался невероятно простым. Я просто добавил IComponentContext в качестве зависимости от моей реализации модуля.

public class LocalActorSystemModule : Module {
    private IComponentContext m_ComponentContext; // A service for resolving dependencies required by this module

    public LocalActorSystemModule(IComponentContext componentContext) { 
        m_ComponentContext = componentContext;
    }

И пусть AutoFac вставляет мне IComponentContext. Таким образом, я могу разрешить любые зависимости, которые требуются внутри модуля.

Ответ 2

При регистрации чего-либо внутри ваших модулей с помощью autofac вместо использования метода RegisterType вы можете использовать метод Register:

builder.Register(c =>
   {
       IComponentContext ctx = c.Resolve<IComponentContext();
       IDefaultLogger logger = ctx.Resolve<IDefaultLogger>();
       ...do something with logger...
       return ...return object you want to register...;
    });

Ответ 3

Правило для использования каждого контейнера IoC/DI: Разрешить один раз! = > , тогда вы получите все зависимости, разрешенные для вашего запрошенного объекта. Если вы пытаетесь разрешить несколько раз, зарегистрируйте другие объекты (тем временем), которые вы застряли в аду. В самом деле. Если вы хотите получать объекты для разных целей в разных местах и ​​временных точках (разрешенные из центральной регистрации), вы можете искать шаблон локатора служб (но это часто описывается как Anti-Pattern).

Модули имеют целью связать связанные регистрации (условно) как statet в документации Autofac:

Модуль - это небольшой класс, который может быть использован для объединения набора связанных компонентов за "фасадом" для упрощения конфигурации и развертывание.

... так что, если они всего лишь сумма регистрации и контейнер еще не создан, вы не сможете сразу же решить (даже ранее зарегистрированный) компонент (за исключением вызова метода на самом регистранте через OnActivate * перехватывает или при использовании регистрации экземпляра, но я думаю, что это не так для вашего примера). Компоненты находятся только в состоянии регистрации, но полный контекст не готов к разрешению. Что произойдет, если вы переопределите регистрацию в другом модуле? Тогда вы бы ввели разные объекты... плохая идея. Возможно, вам следует пересмотреть свой дизайн приложения и какие объекты имеют какие обязанности.

Кстати: Logging - это проблема перекрестной репликации, которая часто "вводится/разрешается", вызывая отдельную статическую factory или службу вместо того, чтобы делать инъекцию конструктора/свойства (см. использование Common.Logging).

public class MyModule : Module
{
    private static readonly ILog Log = LogManager.GetLogger<MyModule>();

    protected override void Load(ContainerBuilder builder)
    {
        Log.Debug(msg => msg("Hello")); // log whatever you want here
    }
}

Вы также можете использовать библиотеки AOP и вставлять зависимость в модуль (используя отражение). Но я не думаю, что стоит попробовать только для входа в модуль.

В любом случае: @mr100 уже показывал правильное использование во время регистрации. Там вы также можете обрабатывать активацию и т.д., Но не выполнять ведение журнала для самого модуля.