class Program
{
static void Main(string[] args)
{
var container = new WindsorContainer();
container.Register(Component.For(typeof(ISometype<>)).ImplementedBy(typeof(SomeTypeImpl<>)),
Component.For(typeof(ISometype<>)).ImplementedBy(typeof(SomeSpecificTypeImpl<>))
.PreferredFor<ISomeSpecificSpecifier>());
var selector = new Selector();
container.Kernel.AddHandlerSelector(selector);
var sometype = container.Resolve<ISometype<string>>();
Debug.Assert(sometype.GetType() == typeof(SomeTypeImpl<string>));
var sometype2 = container.Resolve<ISometype<Specifier>>();
Debug.Assert(sometype2.GetType() == typeof(SomeSpecificTypeImpl<Specifier>));
}
}
public static class Preferred
{
public static ComponentRegistration<object> PreferredFor<TClosingGenericType>(this ComponentRegistration<object> registration)
{
return registration.ExtendedProperties(new Preference(typeof(TClosingGenericType)));
}
}
internal class Preference
{
public static readonly string Name = "PreferredForClosingType";
public Type PreferredForClosingType { get; set; }
public Preference(Type type)
{
this.PreferredForClosingType = type;
}
}
public class Selector : IHandlerSelector
{
public bool HasOpinionAbout(string key, Type service)
{
// that's about as much as we can say at this point...
return service.IsGenericType && service.GetGenericArguments().Length == 1;
}
public IHandler SelectHandler(string key, Type service, IHandler[] handlers)
{
var @default = handlers.FirstOrDefault(h => MatchHandler(service, h));
return @default ?? handlers.First();
}
private bool MatchHandler(Type service, IHandler handler)
{
if (handler.ComponentModel.ExtendedProperties.Contains(Preference.Name) == false)
return false;
var closingTypeRequired = (Type)handler.ComponentModel.ExtendedProperties[Preference.Name];
var closingTypeActual = service.GetGenericArguments().Single();
return closingTypeRequired.IsAssignableFrom(closingTypeActual);
}
}