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?
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()));