Reputation: 1477
I have the following:
class Repository<T> : IRepository<T>
interface ISuperRepository<T> : IRepository<T>
class SuperRepository<T> : ISuperRepository<T>
interface ISuperType
I want conditional registration in Castle Windsor DI for IRepository<T>
, if T
is ISuperType
, then provide ISuperRepository<T>
. Else, provide IRepository<T>.
So for example, if A : ISuperType
, then I want Resolve<IRepository<A>>
to provide SuperRepository<A>
, and Resolve<IRepository<B>>
to provide Repository<B>
.
How can I achive that?
Upvotes: 3
Views: 729
Reputation: 8725
Castle Windsor
doesn't support such a thing, however you can achieve it with a simple helper method:
public static void RegisterAccordingToISuperType<T>(this IWindsorContainer container)
{
if (typeof (T).GetInterfaces().Contains(typeof (ISuperType)))
container.Register(Component.For<IRepository<T>>()
.ImplementedBy<SuperRepository<T>>());
else
container.Register(Component.For<IRepository<T>>()
.ImplementedBy<Repository<T>>());
}
Then the registration:
container.RegisterAccordingToISuperType<SuperType>();
container.RegisterAccordingToISuperType<int>();
And the resolve will:
var super = container.Resolve<IRepository<SuperType>>();
var intRepo = container.Resolve<IRepository<int>>();
Another option is to the extra parameter in Component.For
. Then gets all type which inherite form the Type(For example) and register them.
private static void Register(...)
{
foreach (var type in GetInheriteTypes())
{
container.Register(Component.For(typeof(IRepository<>),type)
.ImplementedBy(typeof(SuperRepository<>)));
}
container.Register(Component.For(typeof(IRepository<>))
.ImplementedBy(typeof(Repository<>)));
}
private static IEnumerable<Type> GetInheriteTypes()
{
var listOfBs = (from domainAssembly in AppDomain.CurrentDomain.GetAssemblies()
from assemblyType in domainAssembly.GetTypes()
where assemblyType.GetInterfaces().Contains(typeof(ISuperType))
select assemblyType).ToArray();
return listOfBs;
}
Upvotes: 2
Reputation: 21
You can restrict what types a generic is used for with the "where T: typename" syntax, where "typename" refers to a type the specified type 'T' must inherit (or implement). In your case "where T: ISuperType" would match the specific types, and a version without the restriction should match all the rest.
ref. https://msdn.microsoft.com/en-us/library/bb384067.aspx
If it can't be done at compile-time, it can always be done at runtime (with f.ex. 'is').
Upvotes: -1