我的应用程序有两个命令类int[] x = new int[] { 5, 7, -100, 400, 8 };
int max = x[0];
for(int i = 1; i < x.Length; i++)
{
if (x[i] > max) max = x[i];
}
Console.WriteLine("MAX = " + max);
和FooCommand
,其中BarCommand
是BarCommand
的子类。
FooCommand
然后我就有了执行这些命令的类。
class FooCommand
class BarCommand : FooCommand
这些命令处理程序已在Autofac中注册为class FooCommandHandler : ICommandHandler<FooCommand>
class BarCommandHandler : ICommandHandler<BarCommand>
服务。
ICommandHandler<>
然后,当我需要执行命令时,我会使用Autofac的enumeration relationship type来解析已注册的处理程序,效果很好。
builder.RegisterType<FooCommandHandler>.As<ICommandHandler<FooCommand>>();
builder.RegisterType<BarCommandHandler>.As<ICommandHandler<BarCommand>>();
到目前为止,太好了。但是当我解析var barCommandHandlers = container.Resolve<IEnumerable<ICommandHandler<FooCommand>>>()
// returns [ FooCommandHandler ]
的注册处理程序时,Autofac会同时匹配BarCommand
和BarCommandHandler
的实现,因为FooCommandHandler
源自BarCommand
。
FooCommand
这种行为并不是太出乎意料,但这并不是我想要的。
是否有一种方法可以解决var barCommandHandlers = container.Resolve<IEnumerable<ICommandHandler<BarCommand>>>()
// returns [ BarCommandHandler, FooCommandHandler ]
从而只提供直接实现IEnumerable<ICommandHandler<BarCommand>>
接口的处理程序,而不包括那些实现ICommandHandler<BarCommand>
的处理程序?
答案 0 :(得分:1)
评论太久了:我无法复制行为。以下是一些类型和单元测试:
public interface ICommandHandler<T> where T : FooCommand { }
public class FooCommand { }
public class BarCommand : FooCommand { }
class FooCommandHandler : ICommandHandler<FooCommand> { }
class BarCommandHandler : ICommandHandler<BarCommand> { }
class BarCommandHandler2 : ICommandHandler<BarCommand> { }
[TestClass]
public class AutofacTests
{
[TestMethod]
public void ContainerResolvesExpectedDependency()
{
var container = GetContainer();
var barCommandHandlers = container.Resolve<IEnumerable<ICommandHandler<BarCommand>>>()
.ToArray();
Assert.AreEqual(2, barCommandHandlers.Length);
Assert.IsTrue(barCommandHandlers.Any(bch => bch is BarCommandHandler));
Assert.IsTrue(barCommandHandlers.Any(bch => bch is BarCommandHandler2));
Assert.IsFalse(barCommandHandlers.Any(bch => bch is FooCommandHandler));
}
private IContainer GetContainer()
{
var builder = new ContainerBuilder();
builder.RegisterType<FooCommandHandler>().As<ICommandHandler<FooCommand>>();
builder.RegisterType<BarCommandHandler>().As<ICommandHandler<BarCommand>>();
builder.RegisterType<BarCommandHandler2>().As<ICommandHandler<BarCommand>>();
return builder.Build();
}
}
我正在注册ICommandHandler<T>
的各种实现。我另外添加了一个BarCommandHandler2
-因此可以验证是否从容器中获得了多个实现的集合。
测试通过。我正在注册所有这三种类型,但是当我解析IEnumerable<ICommandHandler<BarCommand>>
时,只会得到我期望的两种实现。
这是有道理的,因为FooCommandHandler
没有实现ICommandHandler<BarCommand>
。如果容器确实解决了该问题,那将是一个错误。
我的建议是仔细研究您要解决的IEnumerable<ICommandHandler<BarCommand>>
部分。也许您还需要一些其他的泛型,而在运行时,您实际上正在解决其他问题。