Разрешение зависимостей 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 уже показывал правильное использование во время регистрации. Там вы также можете обрабатывать активацию и т.д., Но не выполнять ведение журнала для самого модуля.