1 回答
TA贡献1847条经验 获得超7个赞
将您的注册更改为以下内容:
public static void AddGatewayServers(this IServiceCollection services)
{
services.AddTransient<Server1>();
services.AddTransient<Server2>();
services.AddScoped<Func<ServerType, IGatewayServer>>(provider => (key) =>
{
switch (key)
{
case ServerType.Type1: return provider.GetRequiredService<Server1>();
case ServerType.Type2: return provider.GetRequiredService<Server2>();
default: throw new InvalidEnumArgumentException(
typeof(ServerType), (int)key, nameof(key));
}
});
}
最重要的变化来自于:
services.AddTransient<IGatewayServer, Server1>();
services.AddTransient<IGatewayServer, Server2>();
对此:
services.AddTransient<Server1>();
services.AddTransient<Server2>();
MS.DI 中的注册来自从服务类型 ( IGatewayServer) 到实现(Server1或Server2分别)的简单字典映射。当你请求时,它在它的字典中Server1找不到。typeof(Server1)因此,解决方案是按具体类型注册这些类型。
最重要的是,我使用了以下GetRequiredService方法:
provider.GetRequiredService<Server1>()
而不是GetService:
provider.GetService<Server1>()
GetRequiredService当注册不存在时将抛出异常,这允许您的代码快速失败。
我更改了代表的注册Transient:
services.AddTransient<Func<ServerType, IGatewayServer>>
到Scoped:
services.AddScoped<Func<ServerType, IGatewayServer>>
这可以防止它被注入到任何Singleton消费者中,因为 MS.DI 只能防止Scoped服务被注入到Singleton消费者中,但不会阻止Transient实例被注入到Scoped消费者中Singleton(但请确保启用验证)。如果您将其注册为Transient,委托将被注入到消费者中,但是当您调用所请求的服务取决于生活方式Singleton时,这最终会在运行时失败,因为这会导致Captive Dependencies。或者它甚至可能导致内存泄漏,当您解析实现的组件时(糟糕!)。将代表注册为GetRequiredServiceScopedTransientIDisposableSingleton,但是,也会导致与俘虏依赖项相同的问题。所以Scoped是唯一明智的选择。
而不是返回null一个未知数ServerType:
default:
return null;
我抛出一个异常,让应用程序快速失败:
default:
throw new InvalidEnumArgumentException(...);
- 1 回答
- 0 关注
- 84 浏览
添加回答
举报