[英]Resolving Autofac enumerable dependencies without contravariance
我的應用程序有兩個命令類FooCommand
和BarCommand
,其中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 匹配BarCommandHandler
和FooCommandHandler
實現,因為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.