如何为同一具体类型注册带不同构造参数的命名服务?
解决同类型服务不同构造参数的注册与区分问题
.NET原生DI本身不支持你想要的.Name()命名服务方式,不过可以通过以下几种方案实现需求:
方案一:.NET 8+ 原生Keyed服务(推荐)
从.NET 8开始,官方DI新增了Keyed服务功能,完美匹配你的场景,直接按名称标识同类型的不同实例:
注册代码
builder.Services.AddKeyedScoped<WeatherForecastService>("my_first_service_named", sp => new WeatherForecastService("param1", "param2")); builder.Services.AddKeyedScoped<WeatherForecastService>("my_second_service_named", sp => new WeatherForecastService("param3", "param4"));
注入使用
通过[FromKeyedServices]特性指定要注入的服务key:
public class YourController { private readonly WeatherForecastService _firstService; private readonly WeatherForecastService _secondService; public YourController( [FromKeyedServices("my_first_service_named")] WeatherForecastService first, [FromKeyedServices("my_second_service_named")] WeatherForecastService second) { _firstService = first; _secondService = second; } }
方案二:创建标记派生类(兼容旧版本)
如果你的项目基于.NET 8以下版本,可以给原服务类创建两个空的派生类,用类型作为区分标识:
定义标记类
// 仅作为标记,继承原服务类 public class FirstWeatherForecastService : WeatherForecastService { public FirstWeatherForecastService(string p1, string p2) : base(p1, p2) { } } public class SecondWeatherForecastService : WeatherForecastService { public SecondWeatherForecastService(string p1, string p2) : base(p1, p2) { } }
注册与注入
// 注册 builder.Services.AddScoped<FirstWeatherForecastService>(sp => new FirstWeatherForecastService("param1", "param2")); builder.Services.AddScoped<SecondWeatherForecastService>(sp => new SecondWeatherForecastService("param3", "param4")); // 注入使用 public class YourController { private readonly WeatherForecastService _firstService; private readonly WeatherForecastService _secondService; public YourController(FirstWeatherForecastService first, SecondWeatherForecastService second) { _firstService = first; _secondService = second; } }
方案三:自定义服务工厂(灵活适配)
如果需要更灵活的服务获取逻辑,可以创建工厂类统一管理不同实例:
定义工厂类
public class WeatherForecastServiceFactory { public WeatherForecastService GetService(string serviceName) { return serviceName switch { "my_first_service_named" => new WeatherForecastService("param1", "param2"), "my_second_service_named" => new WeatherForecastService("param3", "param4"), _ => throw new ArgumentException($"未知服务名称:{serviceName}") }; } }
注册与使用
// 注册工厂 builder.Services.AddScoped<WeatherForecastServiceFactory>(); // 注入使用 public class YourController { private readonly WeatherForecastService _firstService; private readonly WeatherForecastService _secondService; public YourController(WeatherForecastServiceFactory factory) { _firstService = factory.GetService("my_first_service_named"); _secondService = factory.GetService("my_second_service_named"); } }
内容的提问来源于stack exchange,提问作者levis84
相关产品推荐
相关产品推荐

