假设我有此服务注册:
services.AddScoped<IFoo, Foo>();
我知道你可以“替换 ASP.NET Core 内置 DI 容器中的服务注册? ”但是是否可以替换它但仍然保持前一个实例完好无损?
services.AddScoped<IFoo>(sp => new MyFooWrapper(/* I need the original Foo here */));
当我执行单元测试时,这将很有帮助,我可以决定是否要替换例如外部 API 调用:
public class MyFooWrapper(IFoo wrapped) : IFoo
{
public void DoSomething()
{
if (TestingWithExternal)
{
wrapped.DoSomething(); // Original method that calls external HTTP API
}
else
{
FakeSomething();
}
}
}
另一个用例是我想要包装 Blazor,IJSRuntime
因为 MS 使得改变其行为变得非常困难,internal
并且如果他们更新它,重新实现一切就会非常困难。
感谢答案,这是可以替换多个服务的代码
// Replace with fakes
foreach (var s in services.ToList())
{
// Other logic
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));
}
}
您可以将包装
Foo
服务注册为其自身,即:然后,在注册包装类时,使用
ServiceProvider
来获取注册的实例:这样,您将
Foo
用其包装器完全替换所有内容。如果您仍想使用这两种实现,则必须在接口级别(定义IFooWrapper
)将它们分开或使用键控服务(但这是 .NET 中的最新功能)。