Castle windsor解决了具有开放式通用和接口的阵列

时间:2013-09-04 13:50:44

标签: c# castle-windsor

我想用温莎城堡解决以下问题:

IEnumerable<Definition<IEntity>>

目前我只获得一个IEnumerable,其中一个对象与IEntity的第一个实现相匹配。

我想要一个

数组
{ Definition<Entity1>, Definition<Entity2>, ... } 

我觉得需要一个子解析器,但我不知道从哪里开始。

更新

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

1 个答案:

答案 0 :(得分:1)

首先,我认为你应该改进你的设计。我不知道实际情况,但我相信你的意图如下:

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>
{
}

使用此设计,您会遇到以下代码无效的问题:

Definition<IEntity> definition = new Entity1Definition();

为了使其工作,您应该为IEntity类型引入协变通用接口。有关协方差和逆变的更多信息,请访问:Covariance and Contravariance in Generics

所以我建议你介绍以下界面:

public interface IDefinition<out TEntity>
    where TEntity : IEntity
{
}

注意 out 关键字将接口标记为协变。然后从此界面派生 Definition&lt; TEntity&gt;

public abstract class Definition<TEntity> : IDefinition<TEntity>
    where TEntity : IEntity
{
}

现在,当我们以这种方式设置设计时,其余部分很容易。我们可以注册这样的组件:

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

然后解决它们:

var items = container.ResolveAll(typeof(IDefinition<IEntity>));

注意,要解决Windsor中已注册服务的所有实例,您应该调用 ResolveAll 方法。