.NET Core DI,注册程序包的默认实现 [英] .NET Core DI, register a default implementation for a package

查看:221
本文介绍了.NET Core DI,注册程序包的默认实现的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何使用.NET Core的IoC容器注册默认实现,并提供一种覆盖现有实现的方法?

How can one register a default implementation using the IoC container for .NET Core and also provide a way to override the existing implementation ?

例如,我可能想创建一个为某些服务提供默认实现的软件包.

For example, I might want to create a package which provide a default implementation for some service.

namesapce Package 
{
    public interface ISomeService { }

    public class Default : ISomeService { }
}

然后在同一软件包中使用此服务.

This service is then used inside the same package.

namesapce Package 
{
    public class Service 
    {
        Service(ISomeService service) { }
    }
}

如何注册ISomeService默认实现?

稍后在某些项目中使用此程序包并想要用另一个方法覆盖现有实现时,应将Default替换为Override.

Later when using this package in some project and want to override the existing implementation with another the Default should be replaced with Override.

namespace Project 
{
    public class Override : ISomeService { }
}

推荐答案

如果您的软件包包含配置IServiceCollection的类,例如:

If your package contains a class that configures an IServiceCollection, such as this:

public class MyPackageInstaller
{
    public void Install(IServiceCollection services)
    {
        // Your package registers its services
    }
}

然后这也是允许消费者进行可选更改的地方.例如,您可以定义一个这样的类,该类允许使用者为某些服务指定实现:

Then this can also be a point where you allow the consumer to make optional changes. For example, you could define a class like this which allows the consumer to specify implementations for certain 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;
    }
}

现在,您的安装程序可以使用这些选项,并注册使用者指定的实现或它自己的默认实现.

Now your installer can take those options, and register either the implementation specified by the consumer or its own default.

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);

乍看之下,获得相同结果的方法似乎更长.好处是,它使您可以更清楚地指出哪些服务应该被覆盖或不应被覆盖.这样一来,感觉就像您正在使用故意公开的配置选项,而不会像戳软件包的内部一样.

At first glance it looks like a longer way to get the same result. The benefit is that it allows you to make it clearer which services should or should not be overridden. That way it feels more like you're working with deliberately exposed configuration options and less like poking at the internals of the package.

代替允许使用者添加ServiceDescriptor,您可以允许他们仅指定服务类型,而您的配置确定如何注册(单例,瞬态等)

Instead of allowing the consumer to add a ServiceDescriptor you could allow them to specify only a service type, and your configuration determines how it gets registered (singleton, transient, etc.)

当库依赖于配置值(例如必须由使用者提供的连接字符串)时,这也是一种有用的模式.您可以将它们设为构造选项的必需参数,然后再要求选项来构造安装程序,或者仅在安装程序中使它们成为必需参数.现在,没有所需的配置值就无法安装该软件包.

This is also a helpful pattern when the library depends on configuration values like connection strings which must be supplied by the consumer. You can make them required arguments to construct options and then require the options to construct the installer, or just make them required arguments in the installer. Now it's impossible to install the package without the needed configuration values.

这篇关于.NET Core DI,注册程序包的默认实现的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆