Замок Виндзор: Как указать параметр конструктора из кода?
Скажем, у меня есть следующий класс
MyComponent : IMyComponent {
public MyComponent(int start_at) {...}
}
Я могу зарегистрировать его экземпляр с помощью виндзора замка через xml следующим образом
<component id="sample" service="NS.IMyComponent, WindsorSample" type="NS.MyComponent, WindsorSample">
<parameters>
<start_at>1</start_at >
</parameters>
</component>
Как я буду делать то же самое, но в коде? (Обратите внимание, что параметр конструктора)
Ответы
Ответ 1
Изменить: использовались ответы ниже кода с Fluent Interface:)
namespace WindsorSample
{
using Castle.MicroKernel.Registration;
using Castle.Windsor;
using NUnit.Framework;
using NUnit.Framework.SyntaxHelpers;
public class MyComponent : IMyComponent
{
public MyComponent(int start_at)
{
this.Value = start_at;
}
public int Value { get; private set; }
}
public interface IMyComponent
{
int Value { get; }
}
[TestFixture]
public class ConcreteImplFixture
{
[Test]
void ResolvingConcreteImplShouldInitialiseValue()
{
IWindsorContainer container = new WindsorContainer();
container.Register(
Component.For<IMyComponent>()
.ImplementedBy<MyComponent>()
.Parameters(Parameter.ForKey("start_at").Eq("1")));
Assert.That(container.Resolve<IMyComponent>().Value, Is.EqualTo(1));
}
}
}
Ответ 2
Попробуйте это
int start_at = 1;
container.Register(Component.For().DependsOn(dependency: Dependency.OnValue(start_at)));
Ответ 3
Рассматривали ли вы использование Binsor для настройки вашего контейнера? Вместо подробного и неуклюжего XML вы можете настроить Windsor, используя DSL на основе Boo. Вот как выглядит ваш конфиг:
component IMyComponent, MyComponent:
start_at = 1
Преимущество состоит в том, что у вас есть податливый файл конфигурации, но избегайте проблем с XML. Также вам не нужно перекомпилировать, чтобы изменить конфигурацию так, как если бы вы сконфигурировали контейнер в коде.
Также существует множество вспомогательных методов, которые обеспечивают конфигурацию нулевого трения:
for type in Assembly.Load("MyApp").GetTypes():
continue unless type.NameSpace == "MyApp.Services"
continue if type.IsInterface or type.IsAbstract or type.GetInterfaces().Length == 0
component type.GetInterfaces()[0], type
Вы можете начать с него здесь.
Ответ 4
Вам нужно передать IDictionary, когда вы спросите контейнер для экземпляра.
Вы используете эту Resolve перегрузку IWindsorContainer:
T Resolve<T>(IDictionary arguments)
или не общий:
object Resolve(Type service, IDictionary arguments)
Итак, например: (предполагается, что контейнер - это IWindsorContainer)
IDictionary<string, object> values = new Dictionary<string, object>();
values["start_at"] = 1;
container.Resolve<IMyComponent>(values);
Обратите внимание, что значения ключа в словаре чувствительны к регистру.
Ответ 5
Вы можете использовать класс конфигурации для чтения app.config. Затем зарегистрируйте это и заставьте windsor использовать его для своей зависимости. В идеале моя MyConfiguration будет использовать интерфейс.
public class MyConfiguration
{
public long CacheSize { get; }
public MyConfiguration()
{
CacheSize = ConfigurationManager.AppSettings["cachesize"].ToLong();
}
}
container.Register(Component.For<MyConfiguration>().ImplementedBy<MyConfiguration>());
container.Register(Component.For<MostRecentlyUsedSet<long>>()
.ImplementedBy<MostRecentlyUsedSet<long>>().
DependsOn(Dependency.OnValue("size", container.Resolve<PatientCacheConfiguration>().CacheSize))
.LifestyleSingleton());
Ответ 6
Вы можете использовать метод AddComponentWithProperties интерфейса IWindsorContainer для регистрации службы с расширенными свойствами.
Ниже приведена "рабочая" выборка с помощью NUnit Unit Test.
namespace WindsorSample
{
public class MyComponent : IMyComponent
{
public MyComponent(int start_at)
{
this.Value = start_at;
}
public int Value { get; private set; }
}
public interface IMyComponent
{
int Value { get; }
}
[TestFixture]
public class ConcreteImplFixture
{
[Test]
void ResolvingConcreteImplShouldInitialiseValue()
{
IWindsorContainer container = new WindsorContainer();
IDictionary parameters = new Hashtable {{"start_at", 1}};
container.AddComponentWithProperties("concrete", typeof(IMyComponent), typeof(MyComponent), parameters);
IMyComponent resolvedComp = container.Resolve<IMyComponent>();
Assert.That(resolvedComp.Value, Is.EqualTo(1));
}
}
}