解决Autofac可枚举的依存关系而无矛盾

时间:2019-01-16 00:03:37

标签: c# dependency-injection autofac

我的应用程序有两个命令类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,其中BarCommandBarCommand的子类。

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会同时匹配BarCommandBarCommandHandler的实现,因为FooCommandHandler源自BarCommand

FooCommand

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

是否有一种方法可以解决var barCommandHandlers = container.Resolve<IEnumerable<ICommandHandler<BarCommand>>>() // returns [ BarCommandHandler, FooCommandHandler ] 从而只提供直接实现IEnumerable<ICommandHandler<BarCommand>>接口的处理程序,而不包括那些实现ICommandHandler<BarCommand>的处理程序?

1 个答案:

答案 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>>部分。也许您还需要一些其他的泛型,而在运行时,您实际上正在解决其他问题。