温莎城堡:如何从代码中指定构造函数参数?
时间:2020-03-05 19:00:06 来源:igfitidea点击:
说我有以下课程
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>
我将如何用代码做完全相同的事情? (注意,构造函数参数)
解决方案
回答
当我们向容器询问实例时,我们需要传递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);
请注意,字典中的键值区分大小写。
回答
编辑:通过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)); } } }
回答
我们可以使用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)); } } }
回答
我们是否考虑过使用Binsor配置容器?我们可以使用基于Boo的DSL配置Windsor,而不是冗长而笨拙的XML。这是配置如下所示:
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
我们可以在这里开始使用。