Further info to the topic, I've come up with an implementation which ended 
up being a lot larger than initially suspected (though when are things ever 
as easy as expected?!).

I've made a facility that for the base implementation (BaseModel in the 
scenario above) a FactoryMethod is attached. The factory method does the 
following:
1. Ask the kernel for all AssignableHandlers, and then from their services 
builds a list of all the constructor parameter types.
2. For each constructor, the parameter *types* are compared with the 
argument types and a "constructor ranking" is calculated. The total ranking 
is the multiple of each type ranking, which is how deep the type 
inheritance list is. Eg a constructor parameter which takes a more derived 
type gets a higher ranking than one that just takes object.
3. The handlers are sorted by ranking, then kernel goes through them until 
it can find one that resolves.

Things that could probably be improved (suggestions welcome!):
1. FactoryMethod is probably not best approach. Other thoughts?
2. Constructor ranking feels like duplication of how kernel already 
resolves arguments and dependencies. For each handler in AssignableHandlers 
Resolve of course does the resolving part, but there's no ranking of which 
handler service is more specialized. Plus my implementation is pretty 
rubbish for at least the following reasons: it works solely on ranking of 
argument types and not names (which kernel can do of course); matching of 
argument types is messy when there are multiple parameter matching types; 
ranking algorithm has several flaws that can result in ambiguities (equal 
rankings for different constructors).

An alternative approach to the whole thing could perhaps be adding an 
attribute to more specialised components which includes the constructor 
argument type they need and then use a simple HandlerSelector that finds 
the service with most specialized attribute for the calling argument. The 
other advantage of naming the constructor parameter (using an attribute) 
would then be that there wouldn't be any ambiguity between what's an 
argument and a dependency etc.

Input always appreciated.

Rob

On Friday, 2 August 2013 11:02:57 UTC+2, Robert Turner wrote:
>
> Excuse lack of understanding, but what do you mean by "make it an explicit 
> relationship something like: IHandler<SomeData>, IHandler<object>"? 
>
> On Thursday, 1 August 2013 00:14:46 UTC+2, Krzysztof Koźmic wrote:
>>
>> it feels as if you're using implementation detail to drive behaviour.
>>
>> In those cases I'd normally make it an explicit relationship something 
>> like:
>>
>> IHandler<SomeData>, IHandler<object>
>>
>> -- 
>> Krzysztof Kozmic
>>
>> On Thursday, 1 August 2013 at 1:08 AM, Robert Turner wrote:
>>
>> I am having problems using Windsor (ver 3.2.1) for the following IoC 
>> scenario:
>>
>> I have several classes that each extend a base class to provide 
>> additional functionality based on the data type provided. Suppose for 
>> example:
>>
>>         public class BaseModel
>>         {
>>             public BaseModel(object arg)
>>             {
>>                 Name = arg.ToString();
>>             }
>>             public string Name { get; protected set;  }
>>         }
>>
>>         public class AMoreDerivedModel1 : BaseModel
>>         {
>>             public AMoreDerivedModel1(SomeData arg)
>>                 : base(arg)
>>             {
>>                 Name = arg.ABetterName;
>>             }            
>>         }
>>
>> I then wish to resolve a most "suitable" (more derived) instance based on 
>> the constructor argument type. Specifically I wish to have a factory that 
>> can provide an instance based on the argument passed in. For example:
>>
>> Func<object, BaseModel> resolver; // provided by container
>>
>> var res1 = resolver(new SomeData()); // Would resolve to a 
>> AMoreDerivedModel1 type because a SomeData was passed in
>> var res2 = resolver("A name"); // Would "fall back" and resolve to the 
>> more generic BaseModel type
>>
>> So far I have tried both delegate and interface factories and both have 
>> the same result (not surprisingly) of always resolving to a BaseModel type.
>> I tried registering a ISubDependencyResolver and then a IHandlersFilter, 
>> but these were only get called when the factory is resolved, not when the 
>> factory resolves an instance.
>> I registered the BaseModel, and then registered derived classes with 
>> Forward<BaseModel>.
>> The only way I found to achieve what I wanted was with UsingFactoryMethod 
>> for the BaseModel, wherein I GetAssignableHandlers(typeof(BaseModel)) and 
>> search through all of the handler services till I find the best one (most 
>> derived constructor argument) and then resolve it.
>>
>> In my real world scenario I want to use this approach for populating 
>> nodes in a TreeView. The "more derived" classes have the option of adding 
>> additional nodes & data based on the data type. As new data types are added 
>> to the project, a viewer class (that extends BaseModel) can also be written 
>> for generating view information.
>>
>> Is the approach I came up with reasonable, or is the concept of what I'm 
>> doing flawed?
>>
>> Thanks,
>> Robert Turner
>>
>>
>>
>>  -- 
>> You received this message because you are subscribed to the Google Groups 
>> "Castle Project Users" group.
>> To unsubscribe from this group and stop receiving emails from it, send an 
>> email to [email protected].
>> To post to this group, send email to [email protected].
>> Visit this group at http://groups.google.com/group/castle-project-users.
>> For more options, visit https://groups.google.com/groups/opt_out.
>>  
>>  
>>  
>>  
>> 

-- 
You received this message because you are subscribed to the Google Groups 
"Castle Project Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
Visit this group at http://groups.google.com/group/castle-project-users.
For more options, visit https://groups.google.com/groups/opt_out.


Reply via email to