如何在ASP.NET Core中自动注册接口的多个实现(无需手动注册)
我正在使用C#和.NET 8,搭配Microsoft.Extensions.DependencyInjection。有一个接口MyInterface,有30多个不同的类实现了它,希望将IEnumerable<MyInterface>以作用域生命周期注入到另一个类中。
我知道可以手动逐个注册这30个类,示例代码如下:
services.AddScoped<MyInterface, MyConcreteClassOne>(); services.AddScoped<MyInterface, MyConcreteClassTwo>(); ... services.AddScoped<MyInterface, MyConcreteClassThirty>();
有没有无需手动逐个注册的动态实现方式?
补充:我自己尝试的方案,求反馈
我找到了一个看似可行的解决方案,能否有人给出反馈?
Type baseClass = typeof(IBaseClass); var types = Assembly.GetAssembly(baseClass)?. GetTypes().Where(p => !p.IsAbstract && !p.IsInterface && baseClass .IsAssignableFrom(p)); foreach (Type t in types!) { services.AddScoped(typeof(IBaseClass), t); }
方案反馈与优化建议
你的这个动态注册方案核心逻辑是可行的,能实现批量将接口的所有非抽象实现类注册为作用域服务,后续注入IEnumerable<MyInterface>时也能获取到所有实例。但有几个细节需要优化:
空值安全处理:
Assembly.GetAssembly(baseClass)可能返回null(比如接口定义在未加载的程序集),直接用types!会触发空引用异常,建议增加空判断:var targetAssembly = Assembly.GetAssembly(typeof(MyInterface)); if (targetAssembly == null) return; var implementTypes = targetAssembly.GetTypes() .Where(p => !p.IsAbstract && !p.IsInterface && typeof(MyInterface).IsAssignableFrom(p));排除泛型定义类:如果程序集里存在泛型实现类(比如
MyGenericImpl<T> : MyInterface),GetTypes()会包含这些泛型定义,直接注册会报错,建议在筛选条件中添加!p.IsGenericTypeDefinition:.Where(p => !p.IsAbstract && !p.IsInterface && !p.IsGenericTypeDefinition && typeof(MyInterface).IsAssignableFrom(p))命名一致性:代码中用
IBaseClass指代问题里的MyInterface,注意保持变量名和实际接口名一致,避免后续维护混淆。简化写法(推荐):.NET 6及以上版本的
Microsoft.Extensions.DependencyInjection提供了更简洁的批量注册扩展方法(需引用Microsoft.Extensions.DependencyInjection.Abstractions包),自动处理边界情况:services.Scan(scan => scan .FromAssemblyOf<MyInterface>() // 扫描接口所在程序集 .AddClasses(classes => classes.AssignableTo<MyInterface>()) // 筛选所有实现该接口的类 .AsImplementedInterfaces() // 以实现的接口类型注册 .WithScopedLifetime()); // 设置作用域生命周期
内容的提问来源于stack exchange,提问作者Bob Sacamano

