You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何按依赖顺序获取当前应用的所有已加载程序集列表?

按依赖顺序获取已加载程序集的实现方案

我知道可以用AppDomain.GetAssemblies()获取当前应用的所有已加载程序集,但这个方法不保证返回顺序。我需要得到一个依赖程序集排在宿主程序集之前的列表,比如[B, A, A.Optional, A.Optional.Data, C](其中A.Optional.Data依赖A.Optional,A.Optional又依赖A;A、B、C相互独立,顺序无关)。是否能实现?

需求背景

我用MyAttribute标记了多个程序集中的多个类,最终项目需要收集这些类并注册,但注册顺序很关键——A.Optional里的类必须在A的类注册完成后才能正常工作。


当然可以实现,核心思路是基于程序集的依赖关系做拓扑排序,确保依赖项始终先于被依赖项出现。以下是具体实现步骤:

1. 构建程序集依赖映射

遍历所有已加载程序集,建立每个程序集与其直接依赖程序集的映射关系:

var assemblies = AppDomain.CurrentDomain.GetAssemblies();
var dependencyMap = new Dictionary<Assembly, List<Assembly>>();

foreach (var assembly in assemblies)
{
    dependencyMap[assembly] = assembly.GetReferencedAssemblies()
        .Select(name => assemblies.FirstOrDefault(a => a.FullName == name.FullName))
        .Where(refAssembly => refAssembly != null)
        .ToList();
}

2. 用Kahn算法做拓扑排序

通过入度表法实现拓扑排序,确保依赖顺序正确:

// 初始化入度表:记录每个程序集被多少其他程序集依赖
var inDegree = assemblies.ToDictionary(assembly => assembly, _ => 0);

// 统计每个程序集的入度
foreach (var dependencies in dependencyMap.Values)
{
    foreach (var dep in dependencies)
    {
        inDegree[dep]++;
    }
}

// 入度为0的程序集先入队(无依赖或依赖已处理)
var queue = new Queue<Assembly>(inDegree.Where(kvp => kvp.Value == 0).Select(kvp => kvp.Key));
var sortedAssemblies = new List<Assembly>();

while (queue.Count > 0)
{
    var currentAssembly = queue.Dequeue();
    sortedAssemblies.Add(currentAssembly);

    // 遍历当前程序集的依赖项,减少其入度,入度为0则入队
    foreach (var dependentAssembly in dependencyMap[currentAssembly])
    {
        inDegree[dependentAssembly]--;
        if (inDegree[dependentAssembly] == 0)
        {
            queue.Enqueue(dependentAssembly);
        }
    }
}

// 检查是否存在循环依赖
if (sortedAssemblies.Count != assemblies.Length)
{
    throw new InvalidOperationException("检测到程序集循环依赖,无法完成排序");
}

3. 结果验证

最终sortedAssemblies就是符合要求的有序列表:所有被依赖的程序集会排在依赖它的程序集之前,完全满足你的注册顺序需求。

注意事项

  • 如果只需要处理业务程序集(排除系统程序集),可以在获取assemblies时添加过滤条件:
    var assemblies = AppDomain.CurrentDomain.GetAssemblies()
        .Where(a => !a.FullName.StartsWith("System.") && !a.FullName.StartsWith("Microsoft."))
        .ToList();
    
  • 循环依赖会导致排序失败,需要提前排查项目中的循环依赖问题。

内容的提问来源于stack exchange,提问作者Luke Vo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 14:22:41