代码之家  ›  专栏  ›  技术社区  ›  Chris Fulstow

无需求逆求解Autofac可枚举依赖项

  •  1
  • Chris Fulstow  · 技术社区  · 7 年前

    我的应用程序有两个命令类 FooCommand 和 BarCommand 哪里 酒吧指挥部 是 FooCommand .

    class FooCommand
    class BarCommand : FooCommand
    

    然后我有类来执行这些命令。

    class FooCommandHandler : ICommandHandler<FooCommand>
    class BarCommandHandler : ICommandHandler<BarCommand>
    

    这些命令处理程序在Autofac中注册为 ICommandHandler<> 服务。

    builder.RegisterType<FooCommandHandler>.As<ICommandHandler<FooCommand>>();
    builder.RegisterType<BarCommandHandler>.As<ICommandHandler<BarCommand>>();
    

    然后,当我需要执行命令时,我使用Autofac的 enumeration relationship type ,效果很好。

    var barCommandHandlers = container.Resolve<IEnumerable<ICommandHandler<FooCommand>>>()
    // returns [ FooCommandHandler ]
    

    到目前为止,一切顺利。但当我决定 酒吧指挥部 ,Autofac与 BarCommandHandler 和 FooCommandHandler 因为 酒吧指挥部 源于 FooCommand .

    var barCommandHandlers = container.Resolve<IEnumerable<ICommandHandler<BarCommand>>>()
    // returns [ BarCommandHandler, FooCommandHandler ]
    

    这种行为并不出人意料,但这并不是我想要的。

    有办法解决吗 IEnumerable<ICommandHandler<BarCommand>> 只提供直接实现 ICommandHandler<BarCommand> 接口,但不包括那些实现 ICommandHandler<Base> ?

    1 回复  |  直到 7 年前
        1
  •  1
  •   Scott Hannen    7 年前

    评论时间过长:我不能重复这种行为。以下是一些类型和单元测试:

    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<BARCOMAND>> .也许你在工作中有一些额外的泛型,而在运行时你实际上在解决其他问题。

    推荐文章