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

查看:23
本文介绍了.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 默认实现?

How to register the ISomeService default implementation?

稍后在某些项目中使用此包并希望用另一个覆盖现有实现时,应将默认值替换为 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天全站免登陆