Ищите способ передать образ жизни Виндзора в библиотеку - PullRequest
2 голосов
/ 01 мая 2019

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

Библиотека предоставляет функцию "RegisterDependancies (контейнер IWindsorContainer)", которая при вызове регистрирует все зависимости для этой конкретной библиотеки.

Поэтому, когда приложение web api запускается, оно самостоятельно регистрируется, а затем вызывает общую библиотеку, что-то вроде следующего псевдокода:

public void SetupWindsor(){

    IWindsorContainer container = new WindsorContainer();

    container.Register(Component.For<iFoo>().ImplementedBy<Foo>());

     SharedLibrary.RegisterDependancies(container);
}

Функция общей библиотеки выглядит примерно так:

public void RegisterDependancies(IWindsorContainer container)
{
    container.Register(Component.For<iBar>().ImplementedBy<Bar>());
    //In this instance Bar is internal so could not be registered by the api project.
}

Теперь мы хотим, чтобы в проекте веб-API использовался стиль жизни PerWebRequest, но другие системы могут захотеть использовать другой стиль жизни (это решение будет зависеть от того, кто пишет клиентское приложение - общая библиотека будет использоваться в приложениях консоли и Windows - поэтому perwebrequest не подходит для их использования)

Мы хотим изменить метод RegisterDependancies, чтобы мы могли переходить к образу жизни.

Возможно ли это сделать с помощью образа жизни PerWebRequest? Некоторые из нас смотрели и не могли понять, как это сделать, несмотря на то, что делали подобное без единства в прошлом.

Мы либо ищем способ решения проблемы описанным способом, либо есть ли лучший способ решения этой проблемы, который также был бы полезен.

Изменить, чтобы уточнить, что разделяемая библиотека определяет интерфейс IBar как открытый, а класс Bar как внутренний, поэтому API не может выполнить регистрацию - если только в windsor нет какой-то магии, о которой я не знаю.

Ответы [ 2 ]

1 голос
/ 02 мая 2019

Вы можете установить образ жизни при регистрации компонента, используя LifeStyle.Is(LifestyleType)

Нечто подобное позволит вам пройти жизненный цикл.

public void RegisterDependencies(IWindsorContainer container, Castle.Core.LifestyleType lifestyleType)
{
    container.Register(Component.For<IBar>().ImplementedBy<Bar>().LifeStyle.Is(lifestyleType));
}

В качестве альтернативы, посмотрите на регистрацию по соглашению со сборкой, это позволило бы контролировать образ жизни изнутри проекта API без необходимости публичной реализации. https://github.com/castleproject/Windsor/blob/master/docs/registering-components-by-conventions.md

0 голосов
/ 11 мая 2019

разделяемая библиотека определяет интерфейс IBar как общедоступный, а класс Bar - как внутренний, поэтому API не может выполнить регистрацию

Давайте на минуту рассмотрим это проектное решение.Хотя никакие внешние абоненты не могут создать объект Bar, они могут создать объект IBar:

IWindsorContainer container = new WindsorContainer();
SharedLibrary.RegisterDependancies(container);
IBar bar = container.Resolve<IBar>();

Существуют различные причины для сохранения класса Bar internal, но поскольку вы уже можете запускать код, подобный приведенному выше, почему бы просто не позволить общей библиотеке предоставить фабрику?

IBar bar = SharedLibrary.CreateBar();

Это было бы намного проще и отделило бы разделяемую библиотеку от контейнера.В целом, это лучший совет, который я могу дать относительно Dependency Injection и многоразовых библиотек: используйте шаблоны Dependency Injection, а не контейнеры.См. Мою статью DI-Friendly Library для получения более подробной информации.

Если вы все еще хотите использовать DI-контейнер в своем хост-проекте (например, проекте Wep API), вы можете зарегистрироваться IBar противэтот статический метод фабрики.

Внутренние классы

Существуют законные причины, по которым можно хотеть сохранить некоторые классы internal, но я часто вижу базы кода, где классы internal, по непонятным причинампричина.Мой опыт работы с кодом C # на протяжении десятилетий заключается в том, что случаи, когда классы internal без веской причины, значительно перевешивают случаи, когда есть веская причина.

Действительно ли Bar должен быть внутренним?Почему?

Из OP ясно, что IBar реализуется Bar.Этот может быть артефактом сведения вопроса к основам (хорошая работа, делая это, кстати), но у меня складывается впечатление, что Bar - это only класс, который реализует IBar,Так ли это?

Если это так, класс Bar должен предоставлять методы, определенные IBar.Таким образом, API класса уже общедоступен, так зачем скрывать класс?Таким образом, единственное, что скрыто, это конструктор ...

Идеальный шторм

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

С другой стороны, этот вопрос - почти идеальный (маленький) шторм, который иллюстрирует, почемуповторно используемые библиотеки не должны зависеть от DI-контейнеров:

  • Библиотека должна использоваться в нескольких контекстах (веб, консоль, рабочий стол и т. д.)
  • Библиотека зависит от CastleWindsor
  • Интерфейсы общедоступны, но классы реализации не являются

Это усложняет ситуацию - отсюда и вопрос о переполнении стека.

Мой лучший совет - сохранитьвсе просто.Удаление зависимости от Castle Windsor сделает разработку и повторное использование библиотеки проще, а не сложнее.

Было бы еще проще использовать библиотеку, если вы сделаете большинство библиотечных классов общедоступными.

...