![](/img/trans.png)
[英]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.