Windsor breaking change: changing how container.ResolveAll works <-- your feedback needed

409 views
Skip to first unread message

Krzysztof Koźmic

unread,
Mar 2, 2011, 7:23:17 AM3/2/11
to Castle Project Users
Hi folks.

First some background:

container.ResolveAll<IFoo>();

if you call this method in current version of Windsor (and v2.1 and 2.0 and RC3 too I think) it will resolve all components where implementation type implements IFoo. That's not what most people would expect, which is - to return only components that were registered to expose IFoo as their service.

in other words:

container.ResolveAll<object>() will resolve each and every component from the container.


Now, that's not usually a big deal and I guess some people even depend on this behaviour. However it breaks horribly in ASP.NET MVC where Controller class implements all four kinds of filter interfaces and it's a mess if you want to nicely pull filters from the container.

It also is not the default that most people would expect so:

I want to change that behaviour in vNext so that it returns only components exposing IFoo as a service.

Notice that you will be able to make it behave like it does now with a custom IHandlersFilter (added few weeks back) which will have additional benefit of being more fine grained so it doesn't have to be an all-or-nothing thing.

Any insights/objections?


Krzysztof

Dmitry Kryuchkov

unread,
Mar 2, 2011, 7:46:01 AM3/2/11
to Castle Project Users
Actually, I always register multiple types in this way
BasedOnDescriptor postProcessors = AllTypes.Of<IFoo>()
.FromAssembly(Assembly.GetAssembly(typeof(IFoo)))
.WithService.FromInterface();

And I always thought that Windsor will not resolve types registered
without service if I'll try to resolve them with service.
Anyway, I think it will be OK, if I will be able to change this
behavior.

On Mar 2, 3:23 pm, Krzysztof Koźmic <krzysztof.koz...@gmail.com>
wrote:
> Hi folks.
>
> First some background:
>
> container.ResolveAll<IFoo>();
>
> if you call this method in current version of Windsor (and v2.1 and 2.0
> and RC3 too I think) it will resolve all components where implementation
> type implements IFoo. That's not what most people would expect, which is
> - to return only components that were registered to expose IFoo as their
> service.
>
> in other words:
>
> container.ResolveAll<object>() will resolve each and every component
> from the container.
>
> Now, that's not usually a big deal and I guess some people even depend
> on this behaviour. However it breaks horribly in ASP.NET MVC where
> Controller class implements all four kinds of filter interfaces and it's
> a mess if you want to nicely pull filters from the container.
>
> It also is not the default that most people would expect so:
>
> *I want to change that behaviour in vNext so that it returns only
> components exposing IFoo as a service.*

Krzysztof Kozmic

unread,
Mar 2, 2011, 7:46:12 AM3/2/11
to Castle Project Users
Here's a link to a discussion from 2008 about the very same problem
for some more background:
http://groups.google.com/group/castle-project-users/browse_thread/thread/2b5728dbcea5081a/deea0d2e795ff8f7?hl=en&lnk=gst&q=unwanted+constructor#deea0d2e795ff8f7
That's from time before we supported components exposing multiple
types. That's not the case anymore.

On Mar 2, 10:23 pm, Krzysztof Koźmic <krzysztof.koz...@gmail.com>
wrote:
> Hi folks.
>
> First some background:
>
> container.ResolveAll<IFoo>();
>
> if you call this method in current version of Windsor (and v2.1 and 2.0
> and RC3 too I think) it will resolve all components where implementation
> type implements IFoo. That's not what most people would expect, which is
> - to return only components that were registered to expose IFoo as their
> service.
>
> in other words:
>
> container.ResolveAll<object>() will resolve each and every component
> from the container.
>
> Now, that's not usually a big deal and I guess some people even depend
> on this behaviour. However it breaks horribly in ASP.NET MVC where
> Controller class implements all four kinds of filter interfaces and it's
> a mess if you want to nicely pull filters from the container.
>
> It also is not the default that most people would expect so:
>
> *I want to change that behaviour in vNext so that it returns only
> components exposing IFoo as a service.*

Jason Meckley

unread,
Mar 2, 2011, 8:02:09 AM3/2/11
to castle-pro...@googlegroups.com
I also thought Windsor only resolved all types explicitly registered. I wouldn't have a problem with this change.

Craig Neuwirt

unread,
Mar 2, 2011, 8:22:16 AM3/2/11
to castle-pro...@googlegroups.com
How could an IHandlerFilter make it behave like that?  Wouldn't the handlers passed to it already by too restricted?

--
You received this message because you are subscribed to the Google Groups "Castle Project Users" group.
To post to this group, send email to castle-pro...@googlegroups.com.
To unsubscribe from this group, send email to castle-project-u...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/castle-project-users?hl=en.

Krzysztof Koźmic

unread,
Mar 2, 2011, 8:40:29 AM3/2/11
to castle-pro...@googlegroups.com
Craig,

IHandlersFilter is modelled after IHandlersSelector which works off of what's returned from GetAssignableHandlers().

Krzysztof

José F. Romaniello

unread,
Mar 2, 2011, 8:49:21 AM3/2/11
to castle-pro...@googlegroups.com
for those who don't know about this behavior with ResolveAll note that is slightly explained in the doco;

How ResolveAll behaves

When you're using ResolveAll be aware that it has a little bit different semantics than Resolve. It will return all resolvable components assignable to specified type, not just those that have the type registered as one of their services.

http://docs.castleproject.org/Windsor.Three-Calls-Pattern.ashx?HL=resolveall

and this is a reminder to update the doc after the modification.


2011/3/2 Krzysztof Koźmic <krzyszto...@gmail.com>
--

Craig Neuwirt

unread,
Mar 2, 2011, 8:51:36 AM3/2/11
to castle-pro...@googlegroups.com
right, but I thought your change will no longer use GetAssignableHandlers, but rather handlers for a specific interface

Krzysztof Koźmic

unread,
Mar 2, 2011, 9:45:37 AM3/2/11
to castle-pro...@googlegroups.com
Yes, unless we hit handler filter. Have a look at how handler selector is working

Alex Henderson

unread,
Mar 2, 2011, 4:20:33 PM3/2/11
to castle-pro...@googlegroups.com
+1 I didn't realise ResolveAll<> didn't just return those components explicitly registered for that service.  I'm fine with the change, as it's deterministic/won't break anything I've got relying on that feature.

Cheers,

Alex

On Thu, Mar 3, 2011 at 2:02 AM, Jason Meckley <jasonm...@gmail.com> wrote:
I also thought Windsor only resolved all types explicitly registered. I wouldn't have a problem with this change.

--

Lundberg, Per

unread,
Mar 3, 2011, 2:10:13 PM3/3/11
to castle-pro...@googlegroups.com

Hi,

 

While the subject of changing registration semantics has been brought up... Has there been any previous discussion on the matter of Castle Windsor’s default behavior related to property-based injection (and possibly also Resolve<T>()) when there are multiple components providing a given service?

 

Think of a scenario like this: there is a service called ISomeService, and SomeServiceProviderOne and SomeServiceProviderTwo are both implementing the ISomeService interface. Now, what happens when you try to inject a component of ISomeService is that Castle Windsor chooses an arbitrary component providing the given service.

 

To me, this seems like a bad default behavior, but perhaps I’m just not seeing the full picture here. J

 

I’d rather have Resolve<T>() throw an exception in this case, since the behavior is likely not completely predictable to the application using the container. Which component will it get? Now, you could say that the application shouldn’t care, but in reality this might not be the case. You might have specific needs, implying that you want ISomeChildService rather than ISomeService, but perhaps you are yourself implementing some other interface which makes it impossible to change the property type… for example.

 

Is there a (simple) way to change this default behavior? Many thanks in advance!

(And also, of course, the question is whether this default behavior is sane or not…)

 

Best regards,

Per Lundberg

John Simons

unread,
Mar 3, 2011, 4:12:33 PM3/3/11
to Castle Project Users, thesoftwa...@udidahan.com, andreas...@hotmail.com
I wonder if this change breaks NServiceBus integration!
https://github.com/NServiceBus/NServiceBus/blob/master/src/impl/ObjectBuilder/ObjectBuilder.CastleWindsor/WindsorObjectBuilder%20.cs

On Mar 2, 11:23 pm, Krzysztof Koźmic <krzysztof.koz...@gmail.com>
wrote:
> Hi folks.
>
> First some background:
>
> container.ResolveAll<IFoo>();
>
> if you call this method in current version of Windsor (and v2.1 and 2.0
> and RC3 too I think) it will resolve all components where implementation
> type implements IFoo. That's not what most people would expect, which is
> - to return only components that were registered to expose IFoo as their
> service.
>
> in other words:
>
> container.ResolveAll<object>() will resolve each and every component
> from the container.
>
> Now, that's not usually a big deal and I guess some people even depend
> on this behaviour. However it breaks horribly in ASP.NET MVC where
> Controller class implements all four kinds of filter interfaces and it's
> a mess if you want to nicely pull filters from the container.
>
> It also is not the default that most people would expect so:
>
> *I want to change that behaviour in vNext so that it returns only
> components exposing IFoo as a service.*

Krzysztof Koźmic

unread,
Mar 3, 2011, 6:23:52 PM3/3/11
to castle-pro...@googlegroups.com
Per,

What you're talking about is not really related to the topic at hand, but anyway...
What you're talking about is a feature, not a bug. Windsor will provide you the first available component for that service when you're depending on it. If you need a specific one either don't use scanning, or use service overrides.
Same with ResolveAll, it should not matter in which order you get the components.

Krzysztof

Krzysztof Koźmic

unread,
Mar 3, 2011, 7:27:21 PM3/3/11
to castle-pro...@googlegroups.com
can't say from this code. Do they depend on this behaviour? Anyway -
like I said it will be possible to do a fallback to the old behavior
easily so if they need to, they can.

belva...@googlemail.com

unread,
Mar 4, 2011, 7:57:08 AM3/4/11
to castle-pro...@googlegroups.com
I'm not happy with the idea of changing that behaviour. And workarounds like custom IHandlerSelector etc. bring in some new complexity
wich is not necessary from my point of view. Why not simply make a method like ResolveAllExplicit<IFoo> or something like that and leave
the current ResolveAll like it is?


Am schrieb Krzysztof Koźmic <krzyszto...@gmail.com>:

> can't say from this code. Do they depend on this behaviour? Anyway - like I said it will be possible to do a fallback to the old behavior easily so if they need to, they can.
>
>
>
>
>
> On 04/03/2011 7:12 AM, John Simons wrote:
>
>
> I wonder if this change breaks NServiceBus integration!
>
> https://github.com/NServiceBus/NServiceBus/blob/master/src/impl/ObjectBuilder/ObjectBuilder.CastleWindsor/WindsorObjectBuilder%20.cs
>
>
>
> On Mar 2, 11:23 pm, Krzysztof Koźmickrzysztof.koz...@gmail.com>
>
> wrote:
>
>
> Hi folks.
>
>
>
> First some background:
>
>
>
> container.ResolveAll();

>
>
>
> if you call this method in current version of Windsor (and v2.1 and 2.0
>
> and RC3 too I think) it will resolve all components where implementation
>
> type implements IFoo. That's not what most people would expect, which is
>
> - to return only components that were registered to expose IFoo as their
>
> service.
>
>
>
> in other words:
>
>
>
> container.ResolveAll() will resolve each and every component

>
> from the container.
>
>
>
> Now, that's not usually a big deal and I guess some people even depend
>
> on this behaviour. However it breaks horribly in ASP.NET MVC where
>
> Controller class implements all four kinds of filter interfaces and it's
>
> a mess if you want to nicely pull filters from the container.
>
>
>
> It also is not the default that most people would expect so:
>
>
>
> *I want to change that behaviour in vNext so that it returns only
>
> components exposing IFoo as a service.*
>
>
>
> Notice that you will be able to make it behave like it does now with a
>
> custom IHandlersFilter (added few weeks back) which will have additional
>
> benefit of being more fine grained so it doesn't have to be an
>
> all-or-nothing thing.
>
>
>
> Any insights/objections?
>
>
>
> Krzysztof
>
>
>
>

Jason Meckley

unread,
Mar 4, 2011, 8:39:18 AM3/4/11
to castle-pro...@googlegroups.com
Handler selectors are not a work around, they are how handler selection should be done. the recommendation on the table fixes a subtle, implicit bug. creating yet another method on IWindsorContainer doesn't solve the problem, it solves the symptom.

belva...@googlemail.com

unread,
Mar 4, 2011, 8:49:50 AM3/4/11
to castle-pro...@googlegroups.com
Jason, that may all be true, but I want to use the container as is and don't want to rethink and rework thinks from release to release. Now i use ResolveAll and
want it to return all components implementing a specific service no matter for what else they are registered. Next time i have to build something new to do this.
Now i use RemoveComponent. Next release it is not available anymore and i have again to build something new. I don't know , i thought i simply could use the lib
to simplify my work where i have enough other things to think about.

Am schrieb Jason Meckley <jasonm...@gmail.com>:

> Handler selectors are not a work around, they are how handler selection should be done. the recommendation on the table fixes a subtle, implicit bug. creating yet another method on IWindsorContainer doesn't solve the problem, it solves the symptom.
>
>
>
>
>

Krzysztof Koźmic

unread,
Mar 4, 2011, 9:28:39 AM3/4/11
to castle-pro...@googlegroups.com
That's a fair point and that's precisely why I started this thread and
asked for feedback.
So can you shed some more light on the context in which you're depending
on current behaviour and why/if alternative approach (just registering
your components with the service you ResolveAll) would or would not be
feasable.

I also don't want to derail this thread but i would also be interested
in hearing you scenario in which you're using RemoveComponent. Perhaps
if you could start another thread to discuss that, that would be great.

Krzysztof

Xavier

unread,
Mar 4, 2011, 5:27:13 PM3/4/11
to Castle Project Users
We use it exactly the same way and i didn't know it could return more
components than those registered for this service. So it should not
change anything.

By the way, would it be possible for ResolveAll to tell when it does
not return all components because of missing dependencies?

On 2 mar, 22:20, Alex Henderson <bitterco...@gmail.com> wrote:
> +1 I didn't realise ResolveAll<> didn't just return those components
> explicitly registered for that service.  I'm fine with the change, as it's
> deterministic/won't break anything I've got relying on that feature.
>
> Cheers,
>
> Alex
>

José F. Romaniello

unread,
Mar 4, 2011, 5:35:08 PM3/4/11
to castle-pro...@googlegroups.com

2011/3/4 Xavier <xleg...@gmail.com>

By the way, would it be possible for ResolveAll to tell when it does
not return all components because of missing dependencies?

+1 ... This can cause some serious headaches, so im with him 

Krzysztof Koźmic

unread,
Mar 4, 2011, 7:11:08 PM3/4/11
to castle-pro...@googlegroups.com
Xavier,

not really...

I usually have a test for that...

José F. Romaniello

unread,
Mar 5, 2011, 8:52:36 AM3/5/11
to castle-pro...@googlegroups.com
Well it is all related, because in the way i used to register before
this change the only way to test was calling the resolveall method and
verify if the service is in the result. If the service isnt there,
where do i have to start looking? If there is no exception...

2011/3/4, Krzysztof Koźmic <krzyszto...@gmail.com>:

--
Enviado desde mi dispositivo móvil

Krzysztof Koźmic

unread,
Mar 5, 2011, 8:55:55 AM3/5/11
to castle-pro...@googlegroups.com
Jose, I'm not sure I understand what you're saying.

to make sure all components for service IFoo are resolvable this simple
test will do:

var countOfAllFoos = Kernel.GetHandlers(typeof(IFoo)).Length;
var fooInstances = Kernel.ResolveAll<IFoo>();

Assert.AreEqual(countOfAllFoos, fooInstances.Length);

How the change to ResolveAll changes anything here? Actually it saves
you from hitting false positives...

José F. Romaniello

unread,
Mar 5, 2011, 9:13:24 AM3/5/11
to castle-pro...@googlegroups.com
If the assert fails, where do i start looking?
-did my convention based registration fails?
-or one of the services doesn't have satisfied one of *his* dependences.

The second one is confusing for me and contra intuitive for newcomers.
I'd expect an exception rather...

2011/3/5, Krzysztof Koźmic <krzyszto...@gmail.com>:

--

Krzysztof Koźmic

unread,
Mar 5, 2011, 9:19:43 AM3/5/11
to castle-pro...@googlegroups.com
Well, I usually have a test like below and if it fails I just grab a
debugger, run the test to the point where my container is fully
configured and then have a look at "potentially misconfigured
components". That's enough in 99% of the cases and takes 20s, 10 of
which are spent waiting for VS to run the test.

If people really want that (go create a suggestion in UserVoice and
we'll see if people vote on it) then I may add an option to throw,
although I myself am not convinced that's the best thing to do...

José F. Romaniello

unread,
Mar 5, 2011, 9:50:33 AM3/5/11
to castle-pro...@googlegroups.com
Just curious, why you think throwing is not good for resolveall and it
is for resolve?

2011/3/5, Krzysztof Koźmic <krzyszto...@gmail.com>:

--

belva...@googlemail.com

unread,
Mar 5, 2011, 12:59:47 PM3/5/11
to castle-pro...@googlegroups.com
Hi Krzysztof,

one of the scenariois where i use this is the following:
The application is extendable with any plugins. A costumer has also the ability to extend the application with his own plugins.
The base for such plugins is a framework wich defines the architecture and some basic interfaces and classes so that the plugins
can integrate properly. One of the reasons for user defined plugins are Task that could be started by hand or in a chronological
order at defined points in time. So we provide Task interfaces for specific parts of the application (IPatientTask, IAppointmentTask and so on).
For any other Task not associated with a specific part of the application, simply the ITask interface could be used. During startup the app searches
for plugins and loads them. After that all plugins are being searched for known interface implementations to register them with the container.
In short it does something like this:

pContainer.Register( Component.For<IPatientTask>().ImplementedBy<PatientTaskCalc>().Named("p_calc").LifeStyle.Is(Castle.Core.LifestyleType.Transient) );
pContainer.Register( Component.For<IPatientTask>().ImplementedBy<PatientTaskMidnight>().Named("p_midnight").LifeStyle.Is(Castle.Core.LifestyleType.Transient) );
pContainer.Register( Component.For<IAppointmentTask>().ImplementedBy<AppointmentTaskMonth>().Named("a_month").LifeStyle.Is(Castle.Core.LifestyleType.Transient) );
pContainer.Register( Component.For<IAppointmentTask>().ImplementedBy<AppointmentTaskBack>().Named("a_back").LifeStyle.Is(Castle.Core.LifestyleType.Transient) );

In the application the user can now start a Task or can define, when a specific Task should start automatically etc. If i want a specific Task, i ask the container:

IPatientTask[] pTasksP = pContainer.ResolveAll<IPatientTask>(); //2
IAppointmentTask[] pTasksA = pContainer.ResolveAll<IAppointmentTask>(); //2

To get all the registered Tasks, i ask the container:
ITask[] pAllT = pContainer.ResolveAll<ITask>(); ///all 4


So, in the end for this i need the current behaviour or i have to change the current application code. Sure there are a lot of other
ways to accomplish this but we decided years ago to do it that way, because it is simple and it is there :-)
There are other parts, where we use the same approach for instance for text and document generation etc.

Regards





Am schrieb Krzysztof Koźmic <krzyszto...@gmail.com>:

Krzysztof Koźmic

unread,
Mar 5, 2011, 7:45:25 PM3/5/11
to castle-pro...@googlegroups.com
Not that. I'm thinking starting throwing where de previously didn't on a
piece of API that pretty much everyone uses is not the best idea.

It doesn't bother me personally either way as I ensure I get all
components via the test.

Krzysztof

Krzysztof Koźmic

unread,
Mar 5, 2011, 9:08:09 PM3/5/11
to castle-pro...@googlegroups.com
Thanks for the explanation. Actually supporting precisely this scenario
was the reason for introducing this behaviour in the first place, back
in 2008. And that's because back then Windsor only supported single
service per component. So you could have had PatientTaskCalc registered
either as IPatientTask, or as ITask but not as both. So to workaround
this limitation the ResolveAll ignored what service you assigned to the
component and just looked if its assignable to the type you want.

Later on though (not sure if RC3 had it, but all releases starting with
2.0 did) we introduced concept of ForwardedHandler to allow components
to expose multiple services. That was piggy-backed a bit on top of
existing architecture at the time. In Wawel (codename for Windsor vNext)
that was rebuilt so that multi-service components are now a core concept
in Windsor.

This removes the need for the workaround since now you can be explicit
about your intention:

pContainer.Register( Component.For<IPatientTask,
ITask>().ImplementedBy<PatientTaskCalc>().LifeStyle.Transient);
As a sidenote, you can simplify that registration even further by
relying on scanning, like this:
container.Register(AllTypes.FromAssemblyBla().BasedOn<ITask>().WithService.DefaultInterface().Configure(c
=> c.Lifestyle.Transient));

You would get the same behaviour as you have now, with benefit of being
explicit.

And that implicitness of current implementation is the biggest problem
and driver for change here (mostly to accommodate massively popular
ASP.NET MVC framework with breaks SRP and is a PITA to work with, unless
this is fixed).

Looking forward to your (and others') insight on this.

belva...@googlemail.com

unread,
Mar 6, 2011, 6:03:29 AM3/6/11
to castle-pro...@googlegroups.com
Ok, that sounds good to me. I have to admit, I did'nt know about the possibility to register a Component with multiple services. When we started
using Windsor we used the file based XML configuration and partly do it today. And since the ResolveAll() worked as expected, we didn't think
about registering a component this way.
The multiservice concept resolves the problem i talked about. And the need for code changes seems not to be as big as i suspected, since in
the end the call to and the behaviour of ResolveAll() stays the same, if we change the registration process.
Thanks for the explanation.


Am schrieb Krzysztof Koźmic <krzyszto...@gmail.com>:
> Thanks for the explanation. Actually supporting precisely this scenario was the reason for introducing this behaviour in the first place, back in 2008. And that's because back then Windsor only supported single service per component. So you could have had PatientTaskCalc registered either as IPatientTask, or as ITask but not as both. So to workaround this limitation the ResolveAll ignored what service you assigned to the component and just looked if its assignable to the type you want.
>
>
>
> Later on though (not sure if RC3 had it, but all releases starting with 2.0 did) we introduced concept of ForwardedHandler to allow components to expose multiple services. That was piggy-backed a bit on top of existing architecture at the time. In Wawel (codename for Windsor vNext) that was rebuilt so that multi-service components are now a core concept in Windsor.
>
>
>
> This removes the need for the workaround since now you can be explicit about your intention:
>
>
>
> pContainer.Register( Component.For().ImplementedByPatientTaskCalc>().LifeStyle.Transient);
>
> As a sidenote, you can simplify that registration even further by relying on scanning, like this: container.Register(AllTypes.FromAssemblyBla().BasedOnITask>().WithService.DefaultInterface().Configure(c => c.Lifestyle.Transient));

>
>
>
> You would get the same behaviour as you have now, with benefit of being explicit.
>
>
>
> And that implicitness of current implementation is the biggest problem and driver for change here (mostly to accommodate massively popular ASP.NET MVC framework with breaks SRP and is a PITA to work with, unless this is fixed).
>
>
>
> Looking forward to your (and others') insight on this.
>
>
>
> On 06/03/2011 3:59 AM, belva...@googlemail.com wrote:
>
>
> Hi Krzysztof,
>
>
>
> one of the scenariois where i use this is the following:
>
> The application is extendable with any plugins. A costumer has also the ability to extend the application with his own plugins.
>
> The base for such plugins is a framework wich defines the architecture and some basic interfaces and classes so that the plugins
>
> can integrate properly. One of the reasons for user defined plugins are Task that could be started by hand or in a chronological
>
> order at defined points in time. So we provide Task interfaces for specific parts of the application (IPatientTask, IAppointmentTask and so on).
>
> For any other Task not associated with a specific part of the application, simply the ITask interface could be used. During startup the app searches
>
> for plugins and loads them. After that all plugins are being searched for known interface implementations to register them with the container.
>
> In short it does something like this:
>
>
>
> pContainer.Register( Component.For().ImplementedBy().Named("p_calc").LifeStyle.Is(Castle.Core.LifestyleType.Transient) );
>
> pContainer.Register( Component.For().ImplementedByPatientTaskMidnight>().Named("p_midnight").LifeStyle.Is(Castle.Core.LifestyleType.Transient) );
>
> pContainer.Register( Component.ForIAppointmentTask>().ImplementedByAppointmentTaskMonth>().Named("a_month").LifeStyle.Is(Castle.Core.LifestyleType.Transient) );
>
> pContainer.Register( Component.ForIAppointmentTask>().ImplementedByAppointmentTaskBack>().Named("a_back").LifeStyle.Is(Castle.Core.LifestyleType.Transient) );

>
>
>
> In the application the user can now start a Task or can define, when a specific Task should start automatically etc. If i want a specific Task, i ask the container:
>
>
>
> IPatientTask[] pTasksP = pContainer.ResolveAllIPatientTask>(); //2
>
> IAppointmentTask[] pTasksA = pContainer.ResolveAllIAppointmentTask>(); //2

>
>
>
> To get all the registered Tasks, i ask the container:
>
> ITask[] pAllT = pContainer.ResolveAll(); ///all 4

Krzysztof Koźmic

unread,
Mar 6, 2011, 6:25:59 AM3/6/11
to castle-pro...@googlegroups.com
No worries,

I'm hopeful it will be similarly easy migration process for anyone else
who's depending on current behaviour.

cheers,
Krzysztof

Lundberg, Per

unread,
Mar 6, 2011, 2:08:44 PM3/6/11
to castle-pro...@googlegroups.com

Hehe, yes. It’s not exactly related to the topic no, but it’s an issue I’ve encountered previously with Castle Windsor.

 

In my specific case, I think the “problem” is that the components providing IRootService and IChildServiceOne, IChildServiceTwo etc. will be registered as a provider of both these interfaces (the root interface and the specific child interface), which is not optimal in my case since it can lead to scenarios when the application gets the “wrong” component.

 

I think it could be related to how I register the components though (this is done using custom logic on my side, so it could be slightly broken). Only IChildServiceOne and IChildServiceTwo should be in the container; IRootService should not. I should look into that first I guess. It just “feels” that the Castle Windsor default behavior of random-cherrypickism is not my preferred way of having the component resolving to work. J What is the easiest way to tweak this? (I already have a service override mechanism in place; this is just to avoid shooting ourselves in our precious feet…)

 

Best regards,

Per Lundberg

 

From: castle-pro...@googlegroups.com [mailto:castle-pro...@googlegroups.com] On Behalf Of Krzysztof Kozmic
Sent: den 4 mars 2011 01:24
To: castle-pro...@googlegroups.com
Subject: Re: Windsor breaking change: changing how container.ResolveAll works <-- your feedback needed

 

Per,



What you're talking about is not really related to the topic at hand, but anyway...
What you're talking about is a feature, not a bug. Windsor will provide you the first available component for that service when you're depending on it. If you need a specific one either don't use scanning, or use service overrides.
Same with ResolveAll, it should not matter in which order you get the components.

Krzysztof


On 04/03/2011 5:10 AM, Lundberg, Per wrote:

Hi,

While the subject of changing registration semantics has been brought up... Has there been any previous discussion on the matter of Castle Windsors default behavior related to property-based injection (and possibly also Resolve<T>()) when there are multiple components providing a given service?

Think of a scenario like this: there is a service called ISomeService, and SomeServiceProviderOne and SomeServiceProviderTwo are both implementing the ISomeService interface. Now, what happens when you try to inject a component of ISomeService is that Castle Windsor chooses an arbitrary component providing the given service.

To me, this seems like a bad default behavior, but perhaps Im just not seeing the full picture here. J

Id rather have Resolve<T>() throw an exception in this case, since the behavior is likely not completely predictable to the application using the container. Which component will it get? Now, you could say that the application shouldnt care, but in reality this might not be the case. You might have specific needs, implying that you want ISomeChildService rather than ISomeService, but perhaps you are yourself implementing some other interface which makes it impossible to change the property type for example.

Is there a (simple) way to change this default behavior? Many thanks in advance!

(And also, of course, the question is whether this default behavior is sane or not)

Krzysztof Koźmic

unread,
Mar 6, 2011, 6:21:16 PM3/6/11
to castle-pro...@googlegroups.com
Well, IMO if you're calling ResolveAll<IRoot>() I would expect to find some components for that service.

If you're only using IRoot for resolving all it should not affect anything, and if you need to make sure service overrides should set you up. I don't have all the picture so I'm talking in general terms but I'm pretty sure that can be solved elegantly with the tools at hand.

Lundberg, Per

unread,
Mar 10, 2011, 1:02:49 PM3/10/11
to castle-pro...@googlegroups.com

Hi,

 

Sorry about the delay on my behalf...

 

The problem is not mainly with ResolveAll<IRoot>(); that one works correctly AFAIK.

 

The problem is with code like this:

 

[Inject]

public IRoot SomeComponent { get; set; }

 

(I’ve implemented the Inject attribute as a way to control whether property injection will occur or not.)

 

Here, a dependency on IRoot is declared. But what if you have ComponentOne and ComponentTwo both implementing IRoot (and being registered as IRoot providers)? Either one will be chosen, and the user (i.e. the person writing the code) will have no clue that this ambiguity exists.

 

That’s what I am concerned about; I’d like to modify the injection in this case so that a proper exception will be thrown, to alert the user (= the developer) that something funny is about to take place… J Any ideas? Perhaps “subresolvers” or something like that could be used.

 

Best regards,

Per Lundberg

 

From: castle-pro...@googlegroups.com [mailto:castle-pro...@googlegroups.com] On Behalf Of Krzysztof Kozmic
Sent: den 7 mars 2011 01:21
To: castle-pro...@googlegroups.com
Subject: Re: Windsor breaking change: changing how container.ResolveAll works <-- your feedback needed

 

Well, IMO if you're calling ResolveAll<IRoot>() I would expect to find some components for that service.



If you're only using IRoot for resolving all it should not affect anything, and if you need to make sure service overrides should set you up. I don't have all the picture so I'm talking in general terms but I'm pretty sure that can be solved elegantly with the tools at hand.

On 07/03/2011 5:08 AM, Lundberg, Per wrote:

Hehe, yes. Its not exactly related to the topic no, but its an issue Ive encountered previously with Castle Windsor.

In my specific case, I think the problem is that the components providing IRootService and IChildServiceOne, IChildServiceTwo etc. will be registered as a provider of both these interfaces (the root interface and the specific child interface), which is not optimal in my case since it can lead to scenarios when the application gets the wrong component.

I think it could be related to how I register the components though (this is done using custom logic on my side, so it could be slightly broken). Only IChildServiceOne and IChildServiceTwo should be in the container; IRootService should not. I should look into that first I guess. It just feels that the Castle Windsor default behavior of random-cherrypickism is not my preferred way of having the component resolving to work. J What is the easiest way to tweak this? (I already have a service override mechanism in place; this is just to avoid shooting ourselves in our precious feet)

Krzysztof Koźmic

unread,
Mar 10, 2011, 6:36:29 PM3/10/11
to castle-pro...@googlegroups.com
Why do you have ComponentOne and ComponentTwo both providing IRoot in the first place in the container?

In most cases this ends up being one of the following:
- you're doing it wrong and you only need one of them
- one is a decorator of the other in which case simple service override on the decorator is enough to handle this (or explicit ordering of the registration)
- you want one most of the time and the other in few selected cases in which case explicit ordering and service override in exceptional cases will get you covered.

Krzysztof

Krzysztof Koźmic

unread,
Mar 13, 2011, 1:36:02 AM3/13/11
to castle-pro...@googlegroups.com
Just an update:

the poll is now closed with two third of all votes for the 4th option
(resolve explicitly by service and throw when any is unresolvable).
As such that's the option I'm going to implement.

thanks everyone who voted.

krzysztof

Reply all
Reply to author
Forward
0 new messages