如何使用 .NET Core 的 IoC 容器注册默认实现,并提供一种覆盖现有实现的方法?
例如,我可能想创建一个为某些服务提供默认实现的包。
namesapce Package
{
public interface ISomeService { }
public class Default : ISomeService { }
}
然后在同一个包中使用该服务。
namesapce Package
{
public class Service
{
Service(ISomeService service) { }
}
}
如何注册ISomeService
默认实现?
稍后,当在某些项目中使用此包并希望用另一个包覆盖现有实现时,应将 Default 替换为 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
,并且您的配置决定它的注册方式(单例、 transient 等)
当库依赖于配置值(例如必须由使用者提供的连接字符串)时,这也是一种有用的模式。您可以将它们设置为构建选项的必需参数,然后将它们设置为构建安装程序所需的参数,或者仅将它们设置为安装程序中的必需参数。现在,如果没有所需的配置值,就无法安装该软件包。
关于c# - .NET Core DI,为包注册默认实现,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56255424/