我假设您正在使用.NET依赖项注入库(Microsoft.Extensions.DependencyInjection
)?
然而,这一原则适用于国际奥委会图书馆.只有登记会有所不同.
You can create a new concrete type, of course.
But since you only have different configurations of the same type, depending on the exact context you could introduce an abstract factory or a factory delegate.
The factory allows to create the same instance with different configurations. The advantage of factories is that they allow to create different configurations dynamically (where the required configuration is not know in advance).
根据实际的IOC库,您可能有其他特定于库的选项.例如,有些支持将命名服务与属性一起使用.
解决方案1:工厂代表
大多数IOC库都支持工厂委托来实现简单工厂.您只需将Func
定义为构造函数参数,并注册产品类型.MOST将自动为您创建代表..NET IOC要求您显式注册Func
:
注册工厂代表:
builder.Services.AddSingleton<Func<string, string, WeatherForecastService>>(
serviceProvider =>
(parameter1, parameter2) => new WeatherForecastService(parameter1, parameter2);
将工厂声明为依赖项并使用它:
class SomeType
{
private WeatherForecastService WeatherForecastService { get; }
public SomeType(Func<string, string, WeatherForecastService>, serviceFactory)
{
this.WeatherForecastService = serviceFactory.Invoke("param1", "param2");
}
}
class SomeOtherType
{
private WeatherForecastService WeatherForecastService { get; }
public SomeType(Func<string, string, WeatherForecastService>, serviceFactory)
{
this.WeatherForecastService = serviceFactory.Invoke("param3", "param4");
}
}
解决方案2:抽象工厂
如果配置不是动态的,您可以创建一个工厂来返回预先配置的实例(当然,动态配置也可以由调用者显式决定如何配置实例):
定义工厂:
class WeatherForecastServiceFactory : IWeatherForecastService
{
public WeatherForecastService CreateEuropeService()
=> new WeatherForecastService("param1", "param2");
public WeatherForecastService CreateAfricaService()
=> new WeatherForecastService("param3", "param4");
}
注册工厂:
builder.Services.AddSingleton<IWeatherForecastServiceFactory, WeatherForecastServiceFactory>();
声明依赖项:
class SomeType
{
private WeatherForecastService ForecastEurope { get; }
public SomeType(IWeatherForecastServiceFactory serviceFactory)
{
this.ForecastEurope = serviceFactory.CreateEuropeService();
}
}
解决方案3:封装配置(推荐、最方便、最可靠)
在静态配置变化的情况下,使用抽象工厂的替代方案(解决方案2)是 for each 配置定义一个专用类.此解决方案为您提供了非常受欢迎的编译器支持,以确保使用正确的配置:这消除了出现严重错误的可能性:
class WeatherForecastEurope : WeatherForecastService
{
public WeatherForecastEurope() : base("param1", "param2")
{}
}
class WeatherForecastAfrica : WeatherForecastService
{
public WeatherForecastEurope() : base("param3", "param4")
{}
}