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

ASP.NET Core中能否包装已注册服务并保留原实例?

如何在替换ASP.NET Core DI服务时保留原实例?

假设我有如下服务注册:

services.AddScoped<IFoo, Foo>();

我知道可以替换ASP.NET Core内置DI容器中的服务注册,但能否在替换时仍保留原实例,实现类似下面的效果?

services.AddScoped<IFoo>(sp => new MyFooWrapper(/* 此处需要原Foo实例 */));

这种需求在单元测试场景中很实用,比如我可以通过控制开关决定是否调用外部API:

public class MyFooWrapper(IFoo wrapped) : IFoo
{
    
    public void DoSomething()
    {
        if (TestingWithExternal)
        {
            wrapped.DoSomething(); // 调用外部HTTP API的原方法
        }
        else
        {
            FakeSomething();
        }
    }

}

另一个场景是包装Blazor的IJSRuntime——由于微软将它的实现设为internal,直接修改行为难度很大,重新实现所有功能又会在版本更新时带来额外的维护负担。


解决方案:批量替换服务并保留原实例

以下是可替换多个服务的实现代码:

// 替换为假实现
foreach (var s in services.ToList())
{
    // 其他逻辑
    if (s.ServiceType == typeof(IOaApiService))
    {
        services.Remove(s);

        var implType = s.ImplementationType;
        ArgumentNullException.ThrowIfNull(implType);

        services.Add(new(implType, implType, s.Lifetime));
        services.Add(new(
            s.ServiceType,
            sp => new FakeOaAiService((IOaApiService)sp.GetRequiredService(implType)),
            s.Lifetime));
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 04:17:40