You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C# IServiceProvider依赖注入:多IAnimal实现实例获取问题

问题描述

使用微软依赖注入扩展实现DI,创建了一个.NET 6控制台程序测试。定义了IAnimal接口,以及Dog和Cat两个实现类。通过AddTransient<IAnimal, Dog>()和AddTransient<IAnimal, Cat>()注册服务后,调用GetRequiredService<IAnimal>()仅返回最后注册的Cat实例,请问如何按需获取Dog或Cat实例?

using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;

HostApplicationBuilder builder = Host.CreateApplicationBuilder(args);
builder.Services.AddTransient<IAnimal, Dog>();
builder.Services.AddTransient<IAnimal, Cat>();

using IHost host = builder.Build();

var myobject = GetAnimalObject(host.Services, "Scope 1");
Console.WriteLine($"Name: {myobject.name}");
await host.RunAsync();

static IAnimal GetAnimalObject(IServiceProvider services, string scope)
{
    using IServiceScope serviceScope = services.CreateScope();
    IServiceProvider provider = serviceScope.ServiceProvider;
    var result = provider.GetRequiredService<IAnimal>();
    return result;
}

public sealed class Dog : IAnimal
{
    public string name { get; set; } = "Daug";
}

public sealed class Cat : IAnimal
{
    public string name { get; set; } = "Kate";
}

public interface IAnimal
{
    string name { get; set; }
}
解决方案

方法1:直接请求具体实现类型

如果需求是明确获取Dog或Cat实例,可以直接通过具体类型从服务容器中获取,无需通过IAnimal接口。修改GetAnimalObject方法,增加参数指定要获取的实例类型:

// 修改调用处,指定要获取的类型
var dog = GetAnimalObject(host.Services, "Scope 1", typeof(Dog));
Console.WriteLine($"Name: {dog.name}");

var cat = GetAnimalObject(host.Services, "Scope 1", typeof(Cat));
Console.WriteLine($"Name: {cat.name}");

static IAnimal GetAnimalObject(IServiceProvider services, string scope, Type animalType)
{
    using IServiceScope serviceScope = services.CreateScope();
    IServiceProvider provider = serviceScope.ServiceProvider;
    // 根据具体类型获取实例
    return (IAnimal)provider.GetRequiredService(animalType);
}

方法2:自定义工厂类封装实例获取逻辑

如果需要通过标识(如字符串)动态获取实例,可以创建一个工厂类,统一处理实例的创建逻辑:

// 新增工厂类
public class AnimalFactory
{
    private readonly IServiceProvider _serviceProvider;

    public AnimalFactory(IServiceProvider serviceProvider)
    {
        _serviceProvider = serviceProvider;
    }

    public IAnimal GetAnimal(string animalType)
    {
        return animalType switch
        {
            "Dog" => _serviceProvider.GetRequiredService<Dog>(),
            "Cat" => _serviceProvider.GetRequiredService<Cat>(),
            _ => throw new ArgumentException("不支持的动物类型")
        };
    }
}

// 修改服务注册
builder.Services.AddTransient<Dog>();
builder.Services.AddTransient<Cat>();
builder.Services.AddTransient<AnimalFactory>();

// 修改调用逻辑
using IHost host = builder.Build();
var factory = host.Services.GetRequiredService<AnimalFactory>();
var dog = factory.GetAnimal("Dog");
Console.WriteLine($"Name: {dog.name}");

var cat = factory.GetAnimal("Cat");
Console.WriteLine($"Name: {cat.name}");

方法3:获取所有实现并筛选

可以通过GetServices<IAnimal>()获取所有注册的IAnimal实例,再根据类型或自定义属性筛选目标实例:

static IAnimal GetAnimalObject(IServiceProvider services, string scope, Type targetType)
{
    using IServiceScope serviceScope = services.CreateScope();
    IServiceProvider provider = serviceScope.ServiceProvider;
    // 获取所有IAnimal实例,筛选出目标类型
    return provider.GetServices<IAnimal>().FirstOrDefault(a => a.GetType() == targetType) 
           ?? throw new InvalidOperationException("未找到指定类型的实例");
}

// 调用示例
var dog = GetAnimalObject(host.Services, "Scope 1", typeof(Dog));
Console.WriteLine($"Name: {dog.name}");

内容的提问来源于stack exchange,提问作者Xinwei Chen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 06:53:18