캐슬 윈저:코드에서 생성자 매개변수를 지정하는 방법은 무엇입니까?
-
01-07-2019 - |
문제
다음 수업이 있다고 가정 해 보겠습니다.
MyComponent : IMyComponent {
public MyComponent(int start_at) {...}
}
다음과 같이 XML을 통해 Castle Windsor에 인스턴스를 등록할 수 있습니다.
<component id="sample" service="NS.IMyComponent, WindsorSample" type="NS.MyComponent, WindsorSample">
<parameters>
<start_at>1</start_at >
</parameters>
</component>
코드에서 똑같은 작업을 수행하려면 어떻게 해야 합니까?(생성자 매개변수에 주목)
해결책
편집하다:Fluent 인터페이스와 함께 아래 코드의 답변을 사용했습니다. :)
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));
}
}
}
다른 팁
이 시도
int start_at = 1;
container.Register(Component.For().DependsOn(dependency: Dependency.OnValue(start_at)));
Binsor를 사용하여 컨테이너를 구성하는 것을 고려해 보셨나요?장황하고 서투른 XML 대신 Boo 기반 DSL을 사용하여 Windsor를 구성할 수 있습니다.구성은 다음과 같습니다.
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
당신은 그것으로 시작할 수 있습니다 여기.
컨테이너에 인스턴스를 요청할 때 IDictionary를 전달해야 합니다.
IWindsorContainer의 Resolve 오버로드를 사용합니다.
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);
사전의 키 값은 대소문자를 구분합니다.
구성 클래스를 사용하여 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<MyConfiguration>().CacheSize))
.LifestyleSingleton());
IWindsorContainer 인터페이스의 AddComponentWithProperties 메서드를 사용하여 확장 속성이 있는 서비스를 등록할 수 있습니다.
다음은 NUnit 단위 테스트를 사용하여 이 작업을 수행하는 '작동' 샘플입니다.
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));
}
}
}