Использование Autofac в качестве средства поиска сервисов

Я использую Autofac для обработки внедрения зависимостей в моем приложении. Однако у меня есть один компонент, который выполняет некоторую магию отражения во время выполнения, и я не знаю во время компиляции, какие зависимости ему понадобятся.

Обычно у меня просто этот компонент напрямую ссылается на Контейнер и разрешает все, что он хочет. Однако класс, создающий экземпляр этого класса, не имеет ссылки на Контейнер.

Фактически, мой компонент зависит от Autofac. Я бы предпочел более слабую связь, но это не вариант. Есть ли способ попросить (в аргументах конструктора или с помощью внедрения свойств или чего-то еще!) Autofac предоставить мне ссылку на контейнер в моем конструкторе? Или есть более чистый способ, чтобы Autofac предоставил мне волшебный объект локатора службы, который может разрешить что угодно?


person David Pfeffer    schedule 25.08.2011    source источник
comment
Хотя было бы интересно посмотреть, какую магию творит компонент. Возможно, есть другие способы, кроме шаблона локатора сервисов. Не могли бы вы обновить какой-нибудь код?   -  person Peter Lillevold    schedule 25.08.2011
comment
Я могу довольно хорошо это описать. Когда сообщения поступают по шине, код определяет, какой тип сообщения использует некоторые метаданные, а затем создает указанный тип. Затем ему необходимо найти всех разработчиков IConsume<type> (где type - это тип из метаданных) с помощью Autofac, а затем вызвать для него метод Consume.   -  person David Pfeffer    schedule 26.08.2011
comment
Вы имеете в виду: kozmic.pl/2010/03/11/   -  person Krzysztof Kozmic    schedule 29.08.2011
comment
Да, но мало что из этого соответствует Autofac.   -  person David Pfeffer    schedule 29.08.2011


Ответы (3)


Да, ты можешь. Просто возьмите зависимость от IComponentContext:

public class MyComponent
{
    IComponentContext _context;
    public MyComponent(IComponentContext context)
    {
        _context = context;
    }

    public void DoStuff()
    {
        var service = _context.Resolve(...);
    }
}

Обновление из комментариев: IComponentContext, введенный в MyComponent, зависит от области, из которой было разрешено MyComponent. Таким образом, важно учитывать, в каком диапазоне времени жизни MyComponent зарегистрирован. Например. при использовании InstancePerLifetimeScope контекст всегда будет соответствовать той же области, в которой находится служба в зависимости от MyComponent.

person Peter Lillevold    schedule 25.08.2011
comment
Будет ли это работать с несколькими областями жизненного цикла? т.е. будет ли IComponentContext базовым контейнером или областью? - person David Pfeffer; 25.08.2011
comment
Он разрешит IComponentContext из области, в которой было разрешено MyComponent. Таким образом, если MyComponent зарегистрирован как InstancePerLifetimeScope, context всегда будет разрешаться из ожидаемой области. - person Peter Lillevold; 25.08.2011

Предположим, у вас есть два компонента, A и B.

Если A необходимо узнать X о B перед его использованием, это запрос метаданных, и он описан в этом отличный пост.

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

На момент написания этой статьи лучшим сообщением в блоге, которое я смог найти, описывающим это, было это один.

person Nikos Baxevanis    schedule 26.08.2011
comment
Я не уверен, почему вы ответили на уже хорошо проработанный вопрос вещами, которые вообще не связаны с моим вопросом ... как я уже сказал, моя проблема заключается в том, что я не знаю, какой B мне нужно будет решить до времени выполнения. - person David Pfeffer; 28.08.2011
comment
@NikosBaxevanis +1, даже если OP, похоже, этого не понял. Оба поста отличные. Эта единственная фраза из сообщения Николая подводит итог всему: в то же время практически нет оправдания для использования IContainer или IComponentContext в ваших компонентах. - person rsenna; 07.04.2012

В других случаях, когда ваш компонент не создан с помощью DI, вы все равно можете использовать шаблон локатора сервисов. Библиотека Common Service Locator на сайте CodePlex идеально подходит для этой цели.

person Daniel Leiszen    schedule 19.12.2012