--
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.
HowResolveAllbehavesWhen you're using
ResolveAllbe aware that it has a little bit different semantics thanResolve. It will return all resolvable components assignable to specified type, not just those that have the type registered as one of their services.
--
I also thought Windsor only resolved all types explicitly registered. I wouldn't have a problem with this change.
--
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
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
By the way, would it be possible for ResolveAll to tell when it does
not return all components because of missing dependencies?
not really...
I usually have a test for that...
2011/3/4, Krzysztof Koźmic <krzyszto...@gmail.com>:
--
Enviado desde mi dispositivo móvil
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...
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>:
--
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...
2011/3/5, Krzysztof Koźmic <krzyszto...@gmail.com>:
--
It doesn't bother me personally either way as I ensure I get all
components via the test.
Krzysztof
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.
I'm hopeful it will be similarly easy migration process for anyone else
who's depending on current behaviour.
cheers,
Krzysztof
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)
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)
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