Jose, Pat
I ran your test and I did reproduce your issue. This is a known
limitation in Windsor right now that goes back to the early days.
http://castle.uservoice.com/forums/38955-windsor-v3/suggestions/455402-get-rid-of-the-arbitrary-division-for-service-para?ref=title
In short, Windsor has three "kinds" of dependencies:
services (the most common one: from the container give me any
component's instance that support this service)
service overrides (from the container give me specific component's instance)
parameters (which is used for things like strings, ints etc: from the
component's configuration/local context give me the value)
Notice that for parameters it does not look in the container. The
problem is - for this dependency Windsor treats it as parameter (like I
said - the division is very arbitrary and sometimes gets it wrong).
For current version probably the best workaround is to use
DynamicParameters to provide the value...
for the next version (codenamed Wawel) we accept patches :)
On 08/01/2011 11:21 PM, José F. Romaniello wrote:
sorry the exception that i got is
Can't create component 'X.Tests.SomeService' as it has dependencies to
be satisfied.
X.Tests.SomeService is waiting for the following dependencies:
Keys (components with specific keys)
- samples which was not registered.
2011/1/8 José F. Romaniello <[email protected]
<mailto:[email protected]>>
Yes, Ive tested and i've same problem here:
[TestFixture]
public class CastleTest
{
[Test]
public void Test()
{
var container = new WindsorContainer();
container.AddFacility<FactorySupportFacility>();
container.Register(Component.For<IEnumerable<ISample>>()
.UsingFactoryMethod(k => Mocks.Of<ISample>().Where(s => s.Name ==
"Test").Take(10).ToArray()),
Component.For<SomeService>());
container.Resolve<IEnumerable<ISample>>().Count().Should().Be.EqualTo(10);
var service = container.Resolve<SomeService>();
service.CountSamples().Should().Be.EqualTo(10);
}
}
public class SomeService
{
private readonly IEnumerable<ISample> samples;
public SomeService(IEnumerable<ISample> samples)
{
this.samples = samples;
}
public int CountSamples()
{
return samples.Count();
}
}
public interface ISample
{
string Name { get; set; }
}
I've never done this before, so i am confused too. and this
confused me:
Why is Windsor not able to inject array or list of components?
http://stw.castleproject.org/Windsor.FAQ.ashx#Why_is_Windsor_not_able_to_inject_array_or_list_of_components_8
Windsor, *by default when you have dependency on IFoo[],
IEnumerable<IFoo> or IList<IFoo> will check if you have a
component registered for that exact type (array or list of IFoo),*
not if you have any components registered for IFoo (array of
components, is not the same as a component which is an array). You
can change the behavior to say "When you see array or list of IFoo
just give me all IFoos you can get" you use CollectionResolver.
2011/1/8 pmcg <[email protected] <mailto:[email protected]>>
José
I did look at CollectionResolver, but that solves a different
problem
than what I am trying to achieve. I will not have registered
all the
apples in the container, I want to get the apples from the apple
factory and hence i have configured the apples component as
transient
which allows me to use the factory method every time i need to
satisfy
an apples dependency. This means the dependency collection is
dynamic
and can change over time etc.
I have used a pretty simple example to illustrate, but i would
expect
the problem is not uncommon i.e. a repository backed
collection which
is a dependancy for another component ?
Thanks
Pat
On Jan 8, 12:09 pm, José F. Romaniello <[email protected]
<mailto:[email protected]>> wrote:
> There is a resolver for that, you can use:
> container.Kernel.Resolver.AddSubResolver(new
> CollectionResolver(container.Kernel, true));
>
> then you can register all your Apples as such, and inject
> IEnumerable<Apple>, Apple[], IList<Apple> or ICollection<Apple>
>
> (More info
here:http://stw.castleproject.org/Windsor.Resolvers.ashx)
>
> So, you wouldn't need a factory or anything else.
>
> Maybe IEnumerable<T> are handled differently, not sure about
this.
>
> 2011/1/8 pmcg <[email protected] <mailto:[email protected]>>
>
> > Hi,
> > I'm trying to understand why when I have a registered an
IEnumerable
> > component, which I can resolve using a normal resolve
method call, the
> > container will not satisfy another component's resolution
call where
> > this second component has the same IEnumerable type
dependency. I have
> > managed to get it to work using the DynamicParameters
registration
> > helper method. I guess I could also get it to work using
service
> > overrides.
> > Note I am using a factory method to create the IEnumerable
component.
>
> > This simple example illustrates what I’m trying to
understand, if you
> > remove the DynamicParameters usage in the Worker component
> > registration, its apples dependency will not be satisfied,
even though
> > we could resolve the apples collection when doing so
directly against
> > the container
>
> > Should the container not be able to satisfy the Worker apples
> > dependency without the help of DynamicParameters ?
>
> > Thanks in advance
> > Pat
>
> > var _container = new WindsorContainer();
> > _container.AddFacility("factorySupport", new
> > FactorySupportFacility());
>
> > _container.Register(
> > Component.For<AppleFactory>()
> > .Named("appleFactory"));
>
> > _container.Register(
> > Component.For<IEnumerable<Apple>>()
> > .Named("apples")
> > .LifeStyle.Transient
> > .UsingFactoryMethod(kernel =>
> > kernel.Resolve<AppleFactory>().GetAll()));
>
> > // If i don't include the DynamicParameters statement -
Could not
> > resolve non-optional dependency for 'worker' (Worker).
Parameter
> > 'apples' type
'System.Collections.Generic.IEnumerable`1[[Apple,
> > ConsoleApplication1, Version=1.0.0.0, Culture=neutral,
> > PublicKeyToken=null]]'
> > _container.Register(
> > Component.For<Worker>()
> > .Named("worker")
> > .LifeStyle.Transient
> > .DynamicParameters((kernel, parameters) => {
parameters["apples"] =
> > (kernel.Resolve<AppleFactory>()).GetAll(); })); // Could
have just
> > used the apple factory directly here but i may want
caching\logging
> > etc logic
>
> > var _apples = _container.Resolve<IEnumerable<Apple>>();
> > Console.WriteLine("Managed to resolve apples component,
count = {0}",
> > _apples.Count());
>
> > Console.WriteLine("Now trying to resolve a worker which
has an apples
> > dependancy which fails ");
> > var _worker = _container.Resolve<Worker>();
> > _worker.DoIt();
>
> > --
> > You received this message because you are subscribed to
the Google Groups
> > "Castle Project Users" group.
> > To post to this group, send email to
[email protected]
<mailto:[email protected]>
> > .
> > To unsubscribe from this group, send email to
> > [email protected]
<mailto:castle-project-users%[email protected]><castle-project-users%[email protected]
<mailto:castle-project-users%[email protected]>>
> > .
> > For more options, visit this group at
> >http://groups.google.com/group/castle-project-users?hl=en.
>
>
--
You received this message because you are subscribed to the
Google Groups "Castle Project Users" group.
To post to this group, send email to
[email protected]
<mailto:[email protected]>.
To unsubscribe from this group, send email to
[email protected]
<mailto:castle-project-users%[email protected]>.
For more options, visit this group at
http://groups.google.com/group/castle-project-users?hl=en.
--
You received this message because you are subscribed to the Google
Groups "Castle Project Users" group.
To post to this group, send email to
[email protected].
To unsubscribe from this group, send email to
[email protected].
For more options, visit this group at
http://groups.google.com/group/castle-project-users?hl=en.
--
You received this message because you are subscribed to the Google Groups "Castle
Project Users" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to
[email protected].
For more options, visit this group at
http://groups.google.com/group/castle-project-users?hl=en.