Reputation: 1016
With ancestor class:
abstract class MyOpenGenericAncestor<T, TOptions>
and descendant class:
class MyPartiallyClosedDescendant<T> : MyOpenGenericAncestor<T, MyConcreteOptionsType>
I want to be able to resolve MyPartiallyClosedDescendant using MyOpenGenericAncestor, such as:
MyOpenGenericAncestor<T, TOptions> ResolveGeneric<T, TOptions>(TOptions options)
{
// assume options are used for stuff
return _container.Resolve<MyOpenGenericAncestor<T, TOptions>();
}
Is there a way to accomplish this? In this code's current implementation, the registration looks like:
var assemblyFilter = new AssemblyFilter("C:\\thePath\", "MyStuff.*.dll");
var myTypes = Classes
.FromAssemblyInDirectory(assemblyFilter)
.BasedOn(typeof(MyOpenGenericAncestor<,>))
.WithServiceBase()
.LifestyleTransient();
container.Register(myTypes);
With this registration, the MyPartiallyClosedDescendant is registered as a component, but calling ResolveGeneric(myConcreateOptionsInstance) causes a Castle.MicroKernel.ComponentNotFoundException with the message that no component for supporting the service MyOpenGenericAncestor`2[MyConcreateTType, MyConcreateOptionsType] was found. Getting that exception makes sense, but is there a way to register and/or resolve the descendant by requesting the ancestor?
Upvotes: 3
Views: 149
Reputation: 4408
In Castle, there is IGenericImplementationMatchingStrategy for this purpose. Unfortunately I'm not sure how to use it with convention registration, so at least this...
public class MyOpenGenericAncestorMatchingStrategy : IGenericImplementationMatchingStrategy
{
public Type[] GetGenericArguments(ComponentModel model, CreationContext context)
{
return new[] { context.GenericArguments[1] };
}
}
container.Register(Component.For(typeof(MyOpenGenericAncestor<,>))
.ImplementedBy(typeof(MyPartiallyClosedDescendant<>), new MyOpenGenericAncestorMatchingStrategy()));
Upvotes: 1