ASP.NET Core的一個關鍵特性是它使用依賴注入(DI)。該框架圍繞「符合容器」抽象設計,容許框架自己使用簡單容器,同時還容許插入功能更豐富的第三方容器。git
針對多個服務註冊實現的通常模式是常見的。大多數第三方DI容器都內置了這個概念。例如:Autofac;github
可是在Core 的DI容器中它是不支持的,好比:框架
public interface IBar {} public interface IFoo {} public class Foo : IFoo, IBar {} [Fact] public void WhenRegisteredAsSeparateSingleton_InstancesAreNotTheSame() { var services = new ServiceCollection(); services.AddSingleton<IFoo, Foo>(); services.AddSingleton<IBar, Foo>(); var provider = services.BuildServiceProvider(); var foo1 = provider.GetService<IFoo>(); // An instance of Foo var foo2 = provider.GetService<IBar>(); // An instance of Foo Assert.Same(foo1, foo2); // FAILS }
註冊的Foo
是兩個單例IFoo
和IBar
,但結果可能不是你所指望的。咱們實際上有兩個Foo
「Singleton」 實例,每一個實例註冊一次。ide
這個問題是由David Fowler在2年前提出的,但它已經解決了,有兩種不太優雅的解決方案。函數
[Fact] public void WhenRegisteredAsInstance_InstancesAreTheSame() { var foo = new Foo(); // The singleton instance var services = new ServiceCollection(); services.AddSingleton<IFoo>(foo); services.AddSingleton<IBar>(foo); var provider = services.BuildServiceProvider(); var foo1 = provider.GetService<IFoo>(); var foo2 = provider.GetService<IBar>(); Assert.Same(foo1, foo); // PASSES; Assert.Same(foo2, foo); // PASSES; }
這裏要注意: 必須在配置時對Foo進行實例化,而且必須知道並提供Foo的依賴項。在單例狀況下,這可能比較適合,但它不是很靈活。ui
此外,若是你想Foo
成爲每一個請求範圍的單個實例(Scoped),那麼這種方法就不行了,須要第二種方法spa
[Fact] public void WhenRegisteredAsForwardedSingleton_InstancesAreTheSame() { var services = new ServiceCollection(); services.AddSingleton<Foo>(); // We must explicitly register Foo services.AddSingleton<IFoo>(x => x.GetRequiredService<Foo>()); // Forward requests to Foo services.AddSingleton<IBar>(x => x.GetRequiredService<Foo>()); // Forward requests to Foo var provider = services.BuildServiceProvider(); var foo1 = provider.GetService<Foo>(); // An instance of Foo var foo2 = provider.GetService<IFoo>(); // An instance of Foo var foo3 = provider.GetService<IBar>(); // An instance of Foo Assert.Same(foo1, foo2); // PASSES Assert.Same(foo1, foo3); // PASSES }
爲了將接口請求「轉發」到具體類型,必須作兩件事:設計
services.AddSingleton<Foo>()
services.AddSingleton<IFoo>(x => x.GetRequiredService<Foo>())