使用 ASP.NET Core 从抽象工厂返回同一接口的多个实现

问题描述 投票:0回答:2

我想通过 .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 容器创建和管理。

asp.net-core dependency-injection multiple-instances asp.net-core-middleware abstract-factory
2个回答
0
投票

让您的

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>();

0
投票

在 .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;

    ...
}
© www.soinside.com 2019 - 2024. All rights reserved.