Reputation: 1026
I would like to resolve the following with castle windsor:
IEnumerable<Definition<IEntity>>
At the moment I'm only getting an IEnumerable with 1 object which matches the first implementation of IEntity.
I would like an array of
{ Definition<Entity1>, Definition<Entity2>, ... }
I have a feeling a sub resolver is needed but I have no idea where to start.
var container = new WindsorContainer();
container.Kernel.Resolver.AddSubResolver(
new CollectionResolver(container.Kernel, true));
container.Register(Component.For(typeof (Definition<>)));
var binDir = HostingEnvironment.MapPath("~/bin");
var assemblyFilter = new AssemblyFilter(binDir);
container.Register(Types.FromAssemblyInDirectory(assemblyFilter)
.BasedOn<IEntity>()
.Unless(t => t.IsAbstract || t.IsInterface)
.WithServiceAllInterfaces()
.LifestyleTransient());
// This doesn't work!
var items = container.Resolve(typeof(IEnumerable<Definition<IEntity>>));
Upvotes: 4
Views: 2281
Reputation: 46
First, I think that you should improve your design a bit. I don't know the actual context, but I believe that your intent is the following:
public interface IEntity
{
}
public class Entity1 : IEntity
{
}
public class Entity2 : IEntity
{
}
public abstract class Definition<TEntity>
where TEntity : IEntity
{
}
public class Entity1Definition : Definition<Entity1>
{
}
public class Entity2Definition : Definition<Entity2>
{
}
With this design you have the problem that the following code is not valid:
Definition<IEntity> definition = new Entity1Definition();
In order for this to work you should introduce a covariant generic interface for the IEntity type. More on covariance and contravariance you can find here: Covariance and Contravariance in Generics
So I suggest you introduce the following interface:
public interface IDefinition<out TEntity>
where TEntity : IEntity
{
}
Note the out keyword that marks the interface as covariant. And then derive your Definition<TEntity> from this interface:
public abstract class Definition<TEntity> : IDefinition<TEntity>
where TEntity : IEntity
{
}
Now, when we have set the design in such way the rest is easy. We can register the components like this:
WindsorContainer container = new WindsorContainer();
container.Kernel.Resolver.AddSubResolver(
new CollectionResolver(container.Kernel, true));
container.Register(Types.FromThisAssembly()
.BasedOn(typeof(IDefinition<>))
.Unless(t => t.IsAbstract || t.IsInterface)
.WithServices(typeof(IDefinition<IEntity>))
.LifestyleTransient());
And then resolve them:
var items = container.ResolveAll(typeof(IDefinition<IEntity>));
Note, that to resolve all instances for a registered service in Windsor you should invoke the ResolveAll method.
Upvotes: 1