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

关于GetRedirectedTypeOrNull方法与服务注册实例一致性的技术咨询

依赖注入服务注册的重定向逻辑与实例一致性解析

1. 理解GetRedirectedTypeOrNull方法

这个方法是服务注册阶段的实例一致性协调工具,核心作用是从所有要暴露的服务类型中,筛选出一个作为「基准类型」,让其他暴露类型的服务请求都重定向到这个基准类型获取实例。

  • 输入:实现类类型、当前要注册的暴露服务类型、所有暴露服务类型的集合
  • 输出:存在合规基准类型则返回它,否则返回null(代表无需重定向)

2. Singleton/Scoped服务需要重定向的原因

Singleton(单例)和Scoped(作用域)的设计核心是实例唯一性:

  • Singleton要求全局范围内同一服务仅存在一个实例
  • Scoped要求同一个作用域内同一服务仅存在一个实例

如果不做重定向,每个暴露的服务类型(比如IA1、IA2)会被单独注册为指向实现类的服务。这会导致:请求IA1时创建一个A实例,请求IA2时又创建另一个A实例,直接违背了Singleton/Scoped的生命周期约定。而Transient(瞬时)服务本身就是每次请求生成新实例,因此不需要重定向。

核心注册逻辑代码

protected virtual ServiceDescriptor CreateServiceDescriptor(
    Type implementationType,
    Type exposingServiceType,
    List<Type> allExposingServiceTypes,
    ServiceLifetime lifeTime)
{
    if (lifeTime.IsIn(ServiceLifetime.Singleton, ServiceLifetime.Scoped))
    {
        var redirectedType = GetRedirectedTypeOrNull(
            implementationType,
            exposingServiceType,
            allExposingServiceTypes
        );
        if (redirectedType != null)
        {
            return ServiceDescriptor.Describe(
                exposingServiceType,
                provider => provider.GetService(redirectedType),
                lifeTime
            );
        }
    }
    return ServiceDescriptor.Describe(
        exposingServiceType,
        implementationType,
        lifeTime
    );
}
  • 当生命周期为Singleton/Scoped时,优先尝试获取重定向目标类型
  • 若拿到重定向类型,就注册「代理服务」:请求当前暴露类型时,实际从容器中获取重定向类型的实例
  • 若无重定向目标,则直接注册暴露类型指向实现类的常规服务

现象解析

现象1:仅暴露IA1和IA2时,获取不同实例

代码示例:

[ExposeServices(typeof(IA1), typeof(IA2))]
public class A: IA1, IA2, IScopedDependency
  • 此时allExposingServiceTypes集合仅包含IA1和IA2,没有实现类A本身
  • GetRedirectedTypeOrNull找不到合适的基准类型,返回null
  • IA1和IA2会被分别注册为独立的Scoped服务,各自指向实现类A
  • 同一作用域内,请求IA1会创建并缓存一个A实例,请求IA2会创建并缓存另一个A实例,因此拿到不同实例
  • 关于「A默认也会被暴露」:这是框架默认行为——即使显式指定了暴露接口,框架仍会自动把实现类A本身作为服务注册,但该注册与IA1、IA2的注册相互独立,所以通过A获取的实例和通过IA1/IA2获取的也不是同一个。

现象2:暴露A、IA1和IA2时,获取同一实例

代码示例:

[ExposeServices(typeof(A), typeof(IA1), typeof(IA2))]
  • 此时allExposingServiceTypes集合包含A、IA1、IA2
  • GetRedirectedTypeOrNull会把实现类A作为基准类型返回
  • 注册IA1和IA2时,会生成重定向到A的代理服务:请求IA1/IA2时,实际从容器中获取A的实例
  • 由于A是Scoped服务,同一作用域内只会存在一个A实例,因此通过A、IA1、IA2获取到的都是这个实例,保证了一致性

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 13:45:23