簡體   English   中英

.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.

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