views:

31

answers:

1

Hi,

I'm using Castle Windsor as part of a more specialized framework. One of the requirement that popped up is to be able to select the implementations to use when resolving a service based on attributes specified on the service.

For example, let say:

public class MyService
{
   public MyService([Selector("Bar")]SomeDependency foo){......}
}

Then i would want to, inside an ISubDependencyResolver, to get the SelectorAttribute, get its value, and resolve accordingly.

We already do this, but with attributes on the type itself (let say an attribute on SomeDependency's definition). Thats easy since you have a reference to the type. I am, however, having issues finding out how to get a reference to the parameter/property currently being resolved, which would let me fetch that attribute.

Anyone care to share some insight?

Thanks!

+1  A: 

IMO this is actually a service override defined inline so I would treat it as such. Instead of trying to implement this in an ISubDependencyResolver I'd use a component model contributor (IContributeComponentModelConstruction).

Problem is, to do that I don't see any other way than replacing the default ConstructorDependenciesModelInspector with your own (it would be very similar but it would also read this SelectorAttribute and when found it would create a DependencyModel with DependencyType.ServiceOverride.

To replace ConstructorDependenciesModelInspector use container.Kernel.ComponentModelBuilder.

Mauricio Scheffer
I don't think you need to replace it... Not sure thought - I'd have to check
Krzysztof Koźmic
@Krzysztof Koźmic: yeah, it's possible without replacing it, I'll edit my answer.
Mauricio Scheffer
@Krzysztof Koźmic: on second thought, I'd prefer replacing it rather than editing the attached DependencyModels after the fact.
Mauricio Scheffer
This looks like it has potential. I'm researching this up right now to see how to do it, but if you have any references, that would already be great.The one thing that irks me a little in all of it, is that the information I seek IS actually available to the ISubDependencyResolver as part of the DependencyModelExtended.Info property. This would make implementing this quite trivial.Unfortunately, its internal, and I don't feel too good about using hidden members.
shados
I toyed with the IContributeComponentModelConstruction interface, and its pretty easy to inspect the attribute, but I didn't know how to associate the override with specific parameters of specific constructors. Hopefully ConstructorDependenciesModelInspector is the key. Thanks!
shados
@shados: take a look at the ConstructorDependenciesModelInspector code here: http://github.com/castleproject/Castle.InversionOfControl/blob/master/src/Castle.Windsor/MicroKernel/ModelBuilder/Inspectors/ConstructorDependenciesModelInspector.cs
Mauricio Scheffer
@Mauricio Scheffer: Yeah, i looked at the code, and was able to replace the default model inspector with my own, and the code ran, and my application worked with normal DI usage. I was not, however, able to get a custom service key to be used when resolving dependencies.I used the same code as the default inspector, but added a condition to create my own dependencymodel if the attribute was present, with a custom key. But the default implementation would still be the one resolved, even though I could see my dependencymodel being used in the debugger.I must be missing something!
shados
@shados: are you creating the DependencyModel with type DependencyType.ServiceOverride?
Mauricio Scheffer
Yes. Do i have this right though?Let say I register a service of type Foo, with a key "AlternateFoo", then create the DependencyModel as follow:dependencies[i] = new DependencyModel(DependencyType.ServiceOverride, "AlternateFoo", paramType, false);it should work? I basically made a custom IContributeComponentModelConstruction with the exact code of the original ConstructorDependenciesModelInspector, except that before line 77, i added a condition checking for my attribute, and created/assigned my DependencyModel as described above (else use the normal logic).
shados
Mauricio Scheffer
Hmm interesting. Well, i have all the information i need now for sure. Thanks!
shados