[英]How to register multiple implementation for same interface using .NET CORE DI
[英].NET Core DI, register a default implementation for a package
如何使用 .NET Core 的 IoC 容器注冊默認實現並提供覆蓋現有實現的方法?
例如,我可能想創建一個包,為某些服務提供默認實現。
namesapce Package
{
public interface ISomeService { }
public class Default : ISomeService { }
}
然后在同一個包中使用此服務。
namesapce Package
{
public class Service
{
Service(ISomeService service) { }
}
}
如何注冊ISomeService
默認實現?
稍后在某些項目中使用此包並希望用另一個覆蓋現有實現時,應將默認值替換為 Override。
namespace Project
{
public class Override : ISomeService { }
}
如果您的包包含配置IServiceCollection
的類,例如:
public class MyPackageInstaller
{
public void Install(IServiceCollection services)
{
// Your package registers its services
}
}
那么這也可以是您允許消費者進行可選更改的地方。 例如,您可以定義一個這樣的類,它允許消費者為某些服務指定實現:
public class MyPackageRegistrationOptions
{
public ServiceDescriptor FooServiceDescriptor { get; private set; }
public void AddFooService(ServiceDescriptor fooDescriptor)
{
if (fooDescriptor.ServiceType != typeof(IFooService))
{
throw new ArgumentException("fooDescriptor must register type IFooService.");
}
FooServiceDescriptor = fooDescriptor;
}
}
現在,您的安裝程序可以采用這些選項,並注冊使用者指定的實現或它自己的默認實現。
public class MyPackageInstaller
{
private readonly MyPackageRegistrationOptions _options;
public MyPackageInstaller(MyPackageRegistrationOptions options = null)
{
_options = options;
}
public void Install(IServiceCollection services)
{
if (_options?.FooServiceDescriptor != null)
services.Add(_options.FooServiceDescriptor);
else
// here's your default implementation
services.AddSingleton<FooService>();
}
}
用法:
var services = new ServiceCollection();
var options = new MyPackageRegistrationOptions();
options.AddFooService(ServiceDescriptor.Singleton<IFooService, AlternateFooService>());
var installer = new MyPackageInstaller(options);
installer.Install(services);
乍一看,獲得相同結果的方法似乎更長。 好處是它允許您更清楚哪些服務應該或不應該被覆蓋。 這樣,感覺更像是您在使用故意公開的配置選項,而不是在包的內部進行檢查。
您可以允許消費者僅指定服務類型,而不是允許消費者添加ServiceDescriptor
,而您的配置決定了它如何注冊(單例、瞬態等)
當庫依賴於必須由使用者提供的連接字符串等配置值時,這也是一種有用的模式。 您可以使它們成為構造選項的必需參數,然后需要這些選項來構造安裝程序,或者僅將它們設置為安裝程序中的必需參數。 現在不可能在沒有所需配置值的情況下安裝包。
內置的 .NET Core DI 容器允許應用程序開發人員通過簡單地將相同的服務附加到ServiceCollection
來覆蓋您的包注冊到ServiceCollection
。 如果對單一服務類型進行了多次注冊,則將使用最后一次注冊。 例如:
// Package registrations (part of your Package)
services.AddTransient<ISomeService, Default>();
// Override by application developer (part of his Startup.cs)
services.AddTransient<ISomeService, Override>();
務必考慮以不需要使用 DI 容器的方式構建您的包,如 Mark Seemann 在他的DI-Friendly Library文章中所述。
你可以在你的包中注冊任何你想要的服務並通過接口公開它們。 然后,當您將它用於某個項目時,覆蓋默認包實現所需要做的就是覆蓋公開的接口之一,即 .
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.