.Net Core依赖注入:如何通过不同工厂方法获取不同实例
如何根据需求调用不同的静态工厂方法获取IMyService实例?
看起来你现在的问题是注册了单一的IMyService实例,但需要根据不同场景调用First.Factory()或Second.Factory()来获取不同配置的实例。这里有几种实用的解决方案,适配不同的.NET版本和需求:
首先先明确你的原始代码结构(方便对照):
public static class First { public static IMyService Factory() { return new MyServiceImplementation() { /* 用Configs配置 */ }; } } public static class Second { public static IMyService Factory() { return new MyServiceImplementation() { /* 用不同的Configs配置 */ }; } } // 你当前的注册方式 services.AddSingleton(mb => { var myService= First.Factory(); return myService; });
方法1:使用.NET 6+的键控服务(Keyed Services)
如果你的项目基于.NET 6或更高版本,键控服务是最直接的方案——它允许你为同一服务类型的不同实例指定唯一标识(键),后续获取时通过键来区分:
注册服务
// 注册第一个配置的实例,标记键为"FirstConfig" services.AddKeyedSingleton<IMyService>("FirstConfig", (sp, key) => First.Factory()); // 注册第二个配置的实例,标记键为"SecondConfig" services.AddKeyedSingleton<IMyService>("SecondConfig", (sp, key) => Second.Factory());
获取实例
在需要使用的地方,通过[FromKeyedServices]特性注入指定键的实例:
public class MyServiceConsumer { // 注入第一个配置的实例 private readonly IMyService _firstConfigService; // 注入第二个配置的实例 private readonly IMyService _secondConfigService; public MyServiceConsumer( [FromKeyedServices("FirstConfig")] IMyService firstConfigService, [FromKeyedServices("SecondConfig")] IMyService secondConfigService) { _firstConfigService = firstConfigService; _secondConfigService = secondConfigService; } public void UseServices() { _firstConfigService.DoSomething(); // 使用First工厂的配置 _secondConfigService.DoSomething(); // 使用Second工厂的配置 } }
或者直接从服务提供者获取:
var firstService = serviceProvider.GetRequiredKeyedService<IMyService>("FirstConfig");
方法2:使用工厂委托(兼容旧版.NET)
如果你的项目是.NET 5或更早版本,可以注册一个Func<>委托来封装工厂选择逻辑,这样就能在运行时指定要使用哪个静态工厂:
第一步:定义类型标识(可选,也可以用字符串)
public enum MyServiceConfigType { First, Second }
注册工厂委托
services.AddSingleton<Func<MyServiceConfigType, IMyService>>(sp => configType => { return configType switch { MyServiceConfigType.First => First.Factory(), MyServiceConfigType.Second => Second.Factory(), _ => throw new ArgumentOutOfRangeException(nameof(configType), "不支持的服务配置类型") }; });
使用工厂获取实例
在消费类中注入这个委托,按需调用:
public class MyServiceConsumer { private readonly Func<MyServiceConfigType, IMyService> _serviceFactory; public MyServiceConsumer(Func<MyServiceConfigType, IMyService> serviceFactory) { _serviceFactory = serviceFactory; } public void HandleDifferentScenarios() { // 场景1:使用First工厂的配置 var firstService = _serviceFactory(MyServiceConfigType.First); firstService.DoWork(); // 场景2:使用Second工厂的配置 var secondService = _serviceFactory(MyServiceConfigType.Second); secondService.DoWork(); } }
方法3:注册独立的命名实例(手动区分)
如果你不想用键控服务或委托,也可以将两个实例注册为命名实例,通过IServiceProvider手动获取:
// 注册第一个实例 services.AddSingleton("FirstService", First.Factory()); // 注册第二个实例 services.AddSingleton("SecondService", Second.Factory());
获取时:
var firstService = (IMyService)serviceProvider.GetService(typeof(IMyService), "FirstService"); var secondService = (IMyService)serviceProvider.GetService(typeof(IMyService), "SecondService");
不过这种方式需要手动类型转换,不如前两种优雅。
内容的提问来源于stack exchange,提问作者Yahya Hussein
相关产品推荐
相关产品推荐

