我想通过 .NET Core 中的抽象工厂访问特定接口的多个实现。根据提供的枚举,应返回正确的实现。这是我当前的代码:
public enum ServiceInstanceEnum { SampleE, SampleD }
// MyServiceFactory
public ISampleC CreateService(ServiceInstanceEnum serviceType)
{
switch (serviceType)
{
case ServiceInstanceEnum.SampleE: return new SampleE();
case ServiceInstanceEnum.SampleD: return new SampleD();
default: throw new Exception($" The service is not exist...");
}
}
我在 Startup.cs 上的服务注入
services.AddScoped<IMyServiceFactory, MyServiceFactory>();
services.AddScoped<ISampleC, SampleD>();
services.AddScoped<ISampleC, SampleE>();
控制器
private readonly ISampleC _sampleC;
public WeatherForecastController(
ILogger<WeatherForecastController> logger,
IMyServiceFactory myServiceFactory)
{
_logger = logger;
_sampleC = myServiceFactory.CreateService(ServiceInstanceEnum.SampleD);
}
问题是我当前的 MyServiceFactory 实现手动创建服务,而我希望它们由 DI 容器创建和管理。
让您的
MyServiceFactory
取决于 IServiceProvider
:
public class MyServiceFactory(IServiceProvider container) : IMyServiceFactory
{
public ISampleC CreateService(ServiceInstanceEnum serviceType)
{
switch (serviceType)
{
case ServiceInstanceEnum.SampleE:
return container.GetRequiredInstance<SampleE>();
case ServiceInstanceEnum.SampleD:
return container.GetRequiredInstance<SampleD>();
default: throw new Exception($" The service is not exist...");
}
}
}
services.AddScoped<IMyServiceFactory, MyServiceFactory>();
services.AddScoped<SampleD>();
services.AddScoped<SampleE>();
在 .NET 8 中通过密钥服务解决了这个问题。密钥可以是任何类型。不需要工厂
builder.Services.AddKeyedSingleton<ICache, BigCache>("big");
builder.Services.AddKeyedSingleton<ICache, SmallCache>("small");
class BigCacheConsumer([FromKeyedServices("big")] ICache cache)
{
public object? GetData() => cache.Get("data");
}
也应该可以使用枚举作为键:
services.AddKeyedScoped<ISampleC, SampleD>(ServiceInstanceEnum.SampleD);
services.AddKeyedScoped<ISampleC, SampleE>(ServiceInstanceEnum.SampleE);
并将其注入控制器
public class WeatherForecastController: Controller
{
private readonly ISampleC _sampleC;
public WeatherForecastController(
ILogger<WeatherForecastController> logger,
[FromKeyedServices(ServiceInstanceEnum.SampleE)] ISampleC sampleC)
{
_logger = logger;
_sampleC = sampleC;
}
或者,使用主构造函数,只需:
public class WeatherForecastController(
ILogger<WeatherForecastController> logger,
[FromKeyedServices(ServiceInstanceEnum.SampleE)] ISampleC sampleC): Controller
{
private readonly ISampleC _sampleC=sampleC;
private readonly ILogger<WeatherForecastController> _logger = logger;
...
}