如何为每个IAnimal实现类注入独立的HostedService实例?
问题描述
希望运行多个HostedService,每个实例注入一个IAnimal实现类,确保每个IAnimal实现类都对应一个独立的HostedService实例。当前实现方式不够优雅,寻求更优方案。
当前实现代码
AnimalDependencyResolver.cs
public interface IDependencyResolver<out TResolve> { TResolve GetDependency(); } public class AnimalDependencyResolver : IDependencyResolver<IAnimal> { private int _currentIndex = 0; private readonly int _animalCount = 0; private readonly IEnumerable<IAnimal> _animals; public AnimalDependencyResolver(IEnumerable<IAnimal> animals) { _animals = animals; _animalCount = _animals.Count(); } public IAnimal GetDependency() { if (_animalCount <= 0 || _currentIndex >= _animalCount) throw new InvalidOperationException("Sequence contains no (more) elements"); return _animals.ElementAt(_currentIndex++); } }
Program.cs
services.AddSingleton<IHostedService, AnimalService>(); services.AddSingleton<IHostedService, AnimalService>(); services.AddSingleton<IHostedService, AnimalService>(); services.AddSingleton<IHostedService, AnimalService>(); services.AddSingleton<IHostedService, AnimalService>(); services.AddScoped<IAnimal, MajesticSeaFlapFlap>(); services.AddScoped<IAnimal, TrashPanda>(); services.AddScoped<IAnimal, FartSquirrel>(); services.AddScoped<IAnimal, DangerFloof>(); services.AddScoped<IAnimal, NopeRope>(); services.AddSingleton<IDependencyResolver<IAnimal>, AnimalDependencyResolver>();
AnimalService.cs
public AnimalService(ILogger<AnimalService> logger, IDependencyResolver<IAnimal> animalResolver) { _logger = logger; _animal = animalResolver.GetDependency(); }
优化方案
方案1:工厂模式自动注册对应实例
去掉冗余的IDependencyResolver,让AnimalService直接依赖IAnimal,通过反射遍历所有IAnimal实现类,自动注册对应的HostedService实例。
修改AnimalService
public class AnimalService : IHostedService { private readonly ILogger<AnimalService> _logger; private readonly IAnimal _animal; public AnimalService(ILogger<AnimalService> logger, IAnimal animal) { _logger = logger; _animal = animal; } public Task StartAsync(CancellationToken cancellationToken) { _logger.LogInformation($"启动 {_animal.GetType().Name} 对应的服务"); // 此处添加业务逻辑 return Task.CompletedTask; } public Task StopAsync(CancellationToken cancellationToken) { _logger.LogInformation($"停止 {_animal.GetType().Name} 对应的服务"); // 此处添加清理逻辑 return Task.CompletedTask; } }
自动注册逻辑(Program.cs)
// 获取当前程序集中所有实现IAnimal的非抽象类 var animalTypes = Assembly.GetExecutingAssembly() .GetTypes() .Where(t => typeof(IAnimal).IsAssignableFrom(t) && !t.IsAbstract && !t.IsInterface); foreach (var animalType in animalTypes) { // 注册当前IAnimal实现类 services.AddScoped(animalType); // 为每个IAnimal实现类创建并注册对应的AnimalService实例 services.AddSingleton<IHostedService>(sp => { var logger = sp.GetRequiredService<ILogger<AnimalService>>(); var animal = (IAnimal)sp.GetRequiredService(animalType); return new AnimalService(logger, animal); }); }
方案2:泛型HostedService
定义泛型AnimalHostedService<TAnimal>,每个泛型实例对应一个具体的IAnimal实现,通过反射自动完成注册。
定义泛型HostedService
public class AnimalHostedService<TAnimal> : IHostedService where TAnimal : IAnimal { private readonly ILogger<AnimalHostedService<TAnimal>> _logger; private readonly TAnimal _animal; public AnimalHostedService(ILogger<AnimalHostedService<TAnimal>> logger, TAnimal animal) { _logger = logger; _animal = animal; } public Task StartAsync(CancellationToken cancellationToken) { _logger.LogInformation($"启动 {typeof(TAnimal).Name} 对应的服务"); // 此处添加业务逻辑 return Task.CompletedTask; } public Task StopAsync(CancellationToken cancellationToken) { _logger.LogInformation($"停止 {typeof(TAnimal).Name} 对应的服务"); // 此处添加清理逻辑 return Task.CompletedTask; } }
自动注册逻辑(Program.cs)
var animalTypes = Assembly.GetExecutingAssembly() .GetTypes() .Where(t => typeof(IAnimal).IsAssignableFrom(t) && !t.IsAbstract && !t.IsInterface); foreach (var animalType in animalTypes) { // 注册当前IAnimal实现类 services.AddScoped(animalType); // 创建泛型HostedService类型并注册 var hostedServiceType = typeof(AnimalHostedService<>).MakeGenericType(animalType); services.AddSingleton<IHostedService>(hostedServiceType); }
方案优势
- 无需手动重复注册
HostedService,新增IAnimal实现类时自动生效,减少维护成本 - 去掉冗余的解析器,依赖关系更直接,符合依赖注入设计原则
- 每个
HostedService实例明确对应一个IAnimal实现,逻辑清晰,便于调试维护
内容的提问来源于stack exchange,提问作者Starfish
相关产品推荐
相关产品推荐

