Use component id in Castle Windsor generic object configuration

Posted by ChoccyButton on Stack Overflow See other posts from Stack Overflow or by ChoccyButton
Published on 2010-06-08T16:16:16Z Indexed on 2010/06/10 13:02 UTC
Read the original article Hit count: 288

Filed under:
|
|

2 questions in one, but very much related.

Is it possible with Castle Windsor to resolve a configuration entry such as -

Assembly.Namespace.Object1`2[[${ComponentId1}],[${ComponentId2}]], Assembly

Where ComponentId1 and ComponentId2 are defined as components. Castle Windsor doesn't seem to be resolving the ComponentId, it is just looking for ComponentId1 in the Castle.Windsor assembly.

The second question comes in to play if you can't do the first question. If you have to use a full assembly reference instead of a ComponentId, how can you pass any parameters to the object being created? eg to set ComponentId1.Field1 = "blah", or pass something to the constructor of ComponentId1

Hope that makes sense

Update -

Following the request for code I've knocked together the following -

Objects

public class Wrapper<T, T1> where T : ICollector where T1:IProcessor
{
    private T _collector;
    private T1 _processor;

    public Wrapper(T collector, T1 processor)
    {
        _collector = collector;
        _processor = processor;
    }

    public void GetData()
    {
        _collector.CollectData();
        _processor.ProcessData();
    }

}

public class Collector1 : ICollector
{
    public void CollectData()
    {
        Console.WriteLine("Collecting data from Collector1 ...");
    }
}

public class Processor1 : IProcessor
{
    public void ProcessData()
    {
        Console.WriteLine("Processing data from Processor1  ...");
    }
}

repeated so 3 of each type of object in the example

Config

<components>
<component id="Collector1"
           service="CastleWindsorPlay.ICollector, CastleWindsorPlay"
           type="CastleWindsorPlay.Collector1, CastleWindsorPlay"/>
<component id="Collector2"
           service="CastleWindsorPlay.ICollector, CastleWindsorPlay"
           type="CastleWindsorPlay.Collector2, CastleWindsorPlay"/>
<component id="Collector3"
           service="CastleWindsorPlay.ICollector, CastleWindsorPlay"
           type="CastleWindsorPlay.Collector3, CastleWindsorPlay"/>
<component id="Processor1"
           service="CastleWindsorPlay.IProcessor, CastleWindsorPlay"
           type="CastleWindsorPlay.Processor1, CastleWindsorPlay"/>
<component id="Processor2"
           service="CastleWindsorPlay.IProcessor, CastleWindsorPlay"
           type="CastleWindsorPlay.Processor2, CastleWindsorPlay"/>
<component id="Processor3"
           service="CastleWindsorPlay.IProcessor, CastleWindsorPlay"
           type="CastleWindsorPlay.Processor3, CastleWindsorPlay"/>
<component id="Wrapper1"
           type="CastleWindsorPlay.Wrapper`2[[CastleWindsorPlay.Collector1, CastleWindsorPlay],[CastleWindsorPlay.Processor3, CastleWindsorPlay]], CastleWindsorPlay" />
  </components>

Instantiation

        var wrapper = (Wrapper<ICollector, IProcessor>) container.Resolve("Wrapper1");
        wrapper.GetData();

This brief example errors with this error message though -

Can't create component 'Wrapper1' as it has dependencies to be satisfied. Wrapper1 is waiting for the following dependencies:

Services: - CastleWindsorPlay.Collector1 which was not registered. - CastleWindsorPlay.Processor3 which was not registered.

The curious part about this is that I can get it to resolve Collector1 and Processor3 individually before the call to the wrapper, but the wrapper still can't see them.

This is a basic example, the next thing I'd like to be able to do is when instantiating the Wrapper, set a property on the collector and/or processor. So it could be something like Collector.Id = 10, but set in the config where the wrapper is defined. Setting against the Collector component definition wouldn't work as I'd want to be able to instantiate multiple copies of each Collector, using different Id's

Update 2

What I'm actually trying to do is have -

<components>
<component id="Wrapper1"
           type="CastleWindsorPlay.Wrapper`2[${Collector1}(id=1)],[${Processor3}]], CastleWindsorPlay" />
<component id="Wrapper2"
           type="CastleWindsorPlay.Wrapper`2[${Collector1}(id=3)],[${Processor3}]], CastleWindsorPlay" />
  </components>

Then have another object defined as

<component id="Manager"
           type="CastleWindsorPlay.Manager,CastleWindsorPlay">
  <parameters>
    <wrappers>
      <array>
        <item>${Wrapper1}</item>
        <item>${Wrapper2}</item>
      </array>
    </wrappers>
  </parameters>

Then finally in code just be able to call -

var manager = (Manager)container.Resolve("Manager");

This should return the manager object, with an array of wrappers populated and the wrappers configured with the correct Collector and Convertor.

I know there are errors in the Castle config here, that's why I'm asking the question, I don't know how to set the config up to do what I'm after, or even if it's possible to do it in Castle Windsor

© Stack Overflow or respective owner

Related posts about c#

Related posts about generics