Note that there are some explanatory texts on larger screens.

plurals
  1. POCastle Windsor Fluent API: Define Array with Single item as Dependency
    text
    copied!<p>Given this XML configuration (which works)</p> <pre><code>&lt;component type="X.Y.Z.ActivityService, X.Y.Z.Services" id="X.Y.Z.ActivityService" lifestyle="transient"&gt; &lt;parameters&gt; &lt;Listeners&gt; &lt;array&gt; &lt;item&gt;${DefaultActivityListener}&lt;/item&gt; &lt;/array&gt; &lt;/Listeners&gt; &lt;/parameters&gt; &lt;/component&gt; &lt;component type="X.Y.Z.DefaultActivityListener, X.Y.Z.Services" id="DefaultActivityListener" lifestyle="transient" /&gt; </code></pre> <p>I have converted to use the fluent API as below (which doesn't work):</p> <pre><code>Container.Register( Component.For&lt;X.Y.Z.ActivityService&gt;() .ServiceOverrides( ServiceOverride.ForKey("Listeners").Eq(typeof(X.Y.Z.DefaultActivityListener).Name)) .LifeStyle.Transient ); Container.Register( Component.For&lt;X.Y.Z.DefaultActivityListener&gt;() .Named("DefaultActivityListener") .LifeStyle.Transient ); </code></pre> <p>When I now attempt to resolve an instance of <code>X.Y.Z.ActivityService</code> Windsor throws a <code>NotImplementedException</code> in <code>Castle.MicroKernel.SubSystems.Conversion.ArrayConverter.PerformConversion(String, Type)</code>. </p> <p>The implementation of the PerformConversion method is:</p> <pre><code>public override object PerformConversion(String value, Type targetType) { throw new NotImplementedException(); } </code></pre> <p>I should add that if I remove the <code>ServiceOverrides</code> call, all behaves as expected. So there is specifically something wrong in the way I am wiring up the Listeners parameter. Listeners by the way is a property as opposed to a constructor parameter.</p> <p>Seeing as the XML config works as expected how do I best use the fluent API (short of implementing the PerformConversion method) in order to achieve the same result?</p> <p>I am using Release 2.0.</p> <p>EDIT</p> <p>I will extend the question to how would you achieve this configuration in code, with or without use of the fluent API.</p> <p>UPDATE</p> <p>It appears the problem occurs if you attempt to assign a single element to an array property. Unit tests provided below to illustrate issue.</p> <pre><code>namespace Components { public class A { public I[] I { get; set; } } public interface I { string Name { get; } } public class B : I { public string Name { get { return "B"; } } } public class C : I { public string Name { get { return "C"; } } } } [TestMethod] public void ArrayPropertyTestApi() { //PASSES using (Castle.Windsor.WindsorContainer container = new Castle.Windsor.WindsorContainer()) { container.Register(Component.For&lt;Components.A&gt;().ServiceOverrides(ServiceOverride.ForKey("I").Eq(typeof(Components.B).FullName, typeof(Components.C).FullName))); container.Register(Component.For&lt;Components.B&gt;()); container.Register(Component.For&lt;Components.C&gt;()); Components.A svc = container.Resolve&lt;Components.A&gt;(); Assert.IsTrue(svc.I.Length == 2); Assert.IsTrue(svc.I[0].Name == "B"); Assert.IsTrue(svc.I[1].Name == "C"); } } [TestMethod] public void ArrayPropertyTestApi2() { //FAILS using (Castle.Windsor.WindsorContainer container = new Castle.Windsor.WindsorContainer()) { container.Register(Component.For&lt;Components.A&gt;().ServiceOverrides(ServiceOverride.ForKey("I").Eq(typeof(Components.B).FullName))); container.Register(Component.For&lt;Components.B&gt;()); container.Register(Component.For&lt;Components.C&gt;()); Components.A svc = container.Resolve&lt;Components.A&gt;(); //Throws NotImplementedException Assert.IsTrue(svc.I.Length == 1); Assert.IsTrue(svc.I[0].Name == "B"); } } </code></pre> <p>Question still stands.</p> <p>Thanks.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload