寻求可遍历全量引用程序集获取IDomainEvent实现类的Nuget库
解决方案
问题根源
你当前代码返回空是正常的:CLR采用按需加载程序集的策略,只要程序集内的类型没有被已执行的代码引用过,就不会被提前加载到当前应用程序域中,AppDomain.CurrentDomain.GetAssemblies()只能获取到已加载的程序集,自然无法检索到未加载程序集中的IDomainEvent实现类。
原生实现(无需额外Nuget)
你可以借助.NET内置的DependencyContext组件遍历所有声明的依赖项,手动加载未加载的程序集后再扫描类型,适配.NET Core 3.0/.NET 5+版本:
using System.Reflection; using Microsoft.Extensions.DependencyModel; // 先获取所有运行时依赖的程序集名称 var allAssemblies = new List<Assembly>(); var dependencyAssemblies = DependencyContext.Default.RuntimeLibraries // 过滤系统程序集,可根据需求调整过滤规则 .Where(l => !l.Name.StartsWith("System.") && !l.Name.StartsWith("Microsoft.")) // 你可以额外加过滤条件,只保留名称包含DomainEvents的程序集,减少不必要加载 // .Where(l => l.Name.Contains("DomainEvents")) .Select(l => Assembly.Load(new AssemblyName(l.Name))) .ToList(); // 合并已加载的程序集和刚加载的依赖程序集,去重 allAssemblies.AddRange(AppDomain.CurrentDomain.GetAssemblies()); var finalAssemblies = allAssemblies.Distinct().ToList(); // 扫描实现类 var allDomainEventTypes = finalAssemblies .SelectMany(x => x.GetTypes()) .Where(t => typeof(IDomainEvent).IsAssignableFrom(t) && !t.IsInterface && !t.IsAbstract) .ToList();
常用Nuget包方案(更简便)
如果不想自己处理加载逻辑,可以使用常用的程序集扫描库Scrutor,它已经封装好了全依赖遍历的逻辑,一般用来做自动依赖注入注册,也完全满足你的扫描需求:
- 先安装Nuget包:
Scrutor - 直接调用内置的扫描方法即可:
using Scrutor; var allDomainEventTypes = new List<Type>(); var scanner = new TypeSourceSelector(allDomainEventTypes); scanner.FromApplicationDependencies(assemblies => // 可按需过滤程序集,比如只扫DomainEvents相关 // assemblies.Where(a => a.FullName.Contains("DomainEvents")) assemblies ) .AddClasses(c => c.AssignableTo<IDomainEvent>()) .As<IDomainEvent>(); // 执行扫描后allDomainEventTypes就是所有符合要求的实现类
注意事项
- 若你使用单文件发布模式,需要在项目文件中配置
<IncludeAllContentForSelfExtract>true</IncludeAllContentForSelfExtract>,否则依赖程序集不会被内嵌,无法被扫描到。 - 增加程序集名称过滤规则可以大幅降低扫描耗时,同时避免加载系统程序集时可能出现的权限、类型加载异常问题。
- 如果是.NET Framework环境,没有DependencyContext,可以直接遍历应用程序运行目录下所有
.dll文件,过滤名称符合要求的dll后调用Assembly.LoadFrom手动加载再扫描即可。
内容的提问来源于stack exchange,提问作者diegosasw
相关产品推荐
相关产品推荐

