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

如何在不实例化所有实现的情况下从依赖注入获取特定实现

在Microsoft.Extensions.DependencyInjection中按需获取特定接口实现的方案

不是必须通过实例化所有接口实现来获取特定类型,也并非只有注入IEnumerable<TInterface>或Func<IEnumerable<TInterface>>这一种方案。下面是几种更高效的按需获取方式:

1. 键控服务(.NET 6+推荐)

.NET 6及以上版本的DI容器支持键控服务,注册时为每个实现指定唯一标识,使用时直接通过标识获取对应实例,无需实例化其他实现:

// 注册阶段:为每个实现绑定键值
services.AddKeyedTransient<IYourInterface, ImplementationA>("ImplA");
services.AddKeyedTransient<IYourInterface, ImplementationB>("ImplB");

// 使用阶段:根据键值获取目标实现
var targetService = serviceProvider.GetKeyedService<IYourInterface>("ImplA");

如果需要注入到类中,可结合[FromKeyedServices]特性:

public class YourService
{
    public YourService([FromKeyedServices("ImplA")] IYourInterface service)
    {
        // 使用指定实现
    }
}

2. 自定义工厂模式

通过自定义工厂类封装服务获取逻辑,内部依赖IServiceProvider按需创建目标实例:

// 定义工厂接口
public interface IYourInterfaceFactory
{
    IYourInterface GetImplementation(string identifier);
}

// 实现工厂类
public class YourInterfaceFactory : IYourInterfaceFactory
{
    private readonly IServiceProvider _serviceProvider;
    private readonly Dictionary<string, Type> _implMap = new()
    {
        { "ImplA", typeof(ImplementationA) },
        { "ImplB", typeof(ImplementationB) }
    };

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

    public IYourInterface GetImplementation(string identifier)
    {
        if (_implMap.TryGetValue(identifier, out var implType))
        {
            return (IYourInterface)_serviceProvider.GetService(implType);
        }
        throw new ArgumentException($"Unknown implementation: {identifier}");
    }
}

// 注册工厂与实现类
services.AddTransient<ImplementationA>();
services.AddTransient<ImplementationB>();
services.AddSingleton<IYourInterfaceFactory, YourInterfaceFactory>();

// 使用工厂获取实例
var factory = serviceProvider.GetRequiredService<IYourInterfaceFactory>();
var targetService = factory.GetImplementation("ImplA");

3. 直接获取具体实现类型

如果业务场景允许直接依赖具体实现(耦合度略高),可直接注册并获取:

// 注册具体实现
services.AddTransient<ImplementationA>();

// 直接获取
var targetService = serviceProvider.GetRequiredService<ImplementationA>();

总结

无需每次实例化所有接口实现,选择适合的方案可以大幅减少不必要的资源消耗:

  • 优先使用.NET 6+的键控服务,简洁且原生支持;
  • 自定义工厂模式适配旧版本.NET或复杂场景;
  • 直接依赖具体实现适合耦合度可接受的场景。

内容的提问来源于stack exchange,提问作者537mfb

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 15:30:45