Как настроить контейнер Windor в консольном приложении для внедрения во внешнюю библиотеку
У меня есть консольное приложение и веб-API, которые ссылаются на один и тот же слой данных, который является отдельным проектом.
В этом слое данных у меня есть класс, для которого требуется хранилище, которое мы извлекаем из контейнера при создании экземпляра этого класса.
В этом классе у него есть базовый класс, который мы делаем в конструкторе для настройки репозитория:
IContainerAccessor containerAccessor = HttpContext.Current.ApplicationInstance as IContainerAccessor;
Repository = containerAccessor.Container.Resolve<IRepository>();
Как лучше всего это настроить? Это очевидно проблема для нашего консольного приложения, так как оно не имеет HttpContext.
1 ответ
Если я прав, вы хотите настроить консольное приложение, чтобы оно могло вводить классы из общего слоя данных.
Для этого вам необходимо создать установщик для консольного приложения и указать ему запускать установщики в общей библиотеке, но изменить стиль жизни с "PerWebRequest" на "Singleton" или "Transient".
Для получения дополнительной информации прочитайте эту статью: http://blog.ploeh.dk/2010/04/26/ChangingWindsorlifestylesafterthefact/
Имейте в виду, что изменение этого может вызвать проблемы. То есть: если для нескольких компонентов, настроенных как perWebRequest, требуется "единица работы", то это значение будет разным для всех компонентов, если вы измените стиль жизни на переходный. Изменение его на Singleton вызывает ту же, но противоположную проблему. Созданные объекты будут иметь один и тот же объект для разных запросов...
Если вы в порядке с проблемами, этот код должен начать
public class ConsoleAppInstaller: IWindsorInstaller
{
public void Install(IWindsorContainer container, IConfigurationStore store)
{
// 1) make sure we do not use PerWebRequest life style types
var convertWebToTransient = new WebToTransientConvertor();
container.Kernel.ComponentModelBuilder.AddContributor(convertWebToTransient);
// 2) call installers on all libraries we use ...
container.Install(FromAssembly.Containing<SharedDataLayerInstaller>());
// 3) link internal services ...
container.Register(Component.For<IXxxxFactory>().AsFactory());
container.Register(Component.For<IYyyyFactory>().AsFactory());
container.Register(Classes.FromThisAssembly().Where(c => typeof(Form).IsAssignableFrom(c)).LifestyleTransient());
}
public static IWindsorContainer Bootstrap()
{
return new WindsorContainer().Install(FromAssembly.This());
}
}
/// <summary>
/// This class allows to intercept installers using PerWebRequest lifestyles and replaces them with Transient life styles.
/// <code>container.Kernel.ComponentModelBuilder.AddContributor(new WebToTransientConvertor())</code>
/// </summary>
public class WebToTransientConvertor : IContributeComponentModelConstruction
{
//http://blog.ploeh.dk/2010/04/26/ChangingWindsorlifestylesafterthefact/
public void ProcessModel(IKernel kernel, ComponentModel model)
{
if (model.LifestyleType == LifestyleType.PerWebRequest)
//model.LifestyleType = LifestyleType.Transient;
model.LifestyleType = LifestyleType.Singleton;
}
}