簡體   English   中英

無逆變解決 Autofac 可枚舉依賴項

[英]Resolving Autofac enumerable dependencies without contravariance

我的應用程序有兩個命令類FooCommandBarCommand ,其中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 的枚舉關系類型解析注冊的處理程序,這工作正常。

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

到現在為止還挺好。 但是當我為BarCommand解析注冊的處理程序時,Autofac 匹配BarCommandHandlerFooCommandHandler實現,因為BarCommand派生自FooCommand

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

這種行為並不太出乎意料,但並不是我想要的。

有沒有辦法解決IEnumerable<ICommandHandler<BarCommand>>只提供直接實現ICommandHandler<BarCommand>接口的處理程序,而不包括那些實現ICommandHandler<Base>

評論太長了:我無法復制這種行為。 以下是一些類型和單元測試:

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>> 也許您有一些額外的泛型在工作,而在運行時您實際上正在解決其他問題。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM