C#反射:在解决方案中获取*所有*活动程序集?

cyb*_*nte 27 c# reflection

继承人我的问题:

我有两个项目 - 一个'常见'项目,其行为类似于具有各种支持代码的库,以及在许多调用中使用该项目的实际程序.我们将这些项目称为"共同"和"程序".他们都在同一个解决方案中.

在"Common"中,我有一个用于commo反射任务的类,比如创建一个实例.如果我调用GetExecutingAssembly,它将获得所有"公共"类型,但是当我使用GetEntryAssembly时,我得到"程序"类型.

虽然我当然可以编辑代码以使用2套asm,但我担心解决方案中不仅仅有2个项目的情况 - 比方说5(不知道为什么,但让我们去那里现在),我担心调用GetExecutingAssembly和GetEntryAssembly不会获得整个程序中的所有类型.

还有其他方法可以让所有类型都在解决方案中吗?

bsn*_*eze 65

Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
Run Code Online (Sandbox Code Playgroud)

这将获取当前AppDomain中的所有已加载程序集.

如评论中所述,可以生成多个AppDomain,在这种情况下,每个AppDomain都可以拥有自己的程序集.这样做的直接好处是您可以通过卸载包含的AppDomain来卸载程序集.

  • 如果我错了,请纠正我:在需要之前,CLR不会加载引用的程序集(甚至是单个程序集中的模块).例如,只有当条目汇编中的代码引用RefAsmA中定义的类型时,才会加载RefAsmA - 调用静态方法或创建其中定义的类型.此时,程序集将加载到当前AppDomain的加载程序堆中. (10认同)
  • 可能或可能不工作受制于1)如果应用程序产生多个AppDomains 2)如果在此之前已加载所有引用程序集 (4认同)

3Da*_*ave 35

这是一个非常古老的问题,但是为了将来参考,这是一个完整的实现:

    public static IEnumerable<Assembly> GetAssemblies()
    {
        var list = new List<string>();
        var stack = new Stack<Assembly>();

        stack.Push(Assembly.GetEntryAssembly());

        do
        {
            var asm = stack.Pop();

            yield return asm;

            foreach (var reference in asm.GetReferencedAssemblies())
                if (!list.Contains(reference.FullName))
                {
                    stack.Push(Assembly.Load(reference));
                    list.Add(reference.FullName);
                }

        }
        while (stack.Count > 0);

    }
Run Code Online (Sandbox Code Playgroud)

  • @AgentFire有关过早优化的内容是什么?如果您的解决方案中有足够的程序集,或者经常调用它,那么它就会产生影响,其他方面也是错误的.在这种情况下,哈希生成可能比查找消耗更多的时间. (5认同)
  • @AgentFire是的,但它不仅仅需要一个项目添加到链接列表.对于这个应用程序,你永远不会看到差异. (4认同)
  • 尝试使用哈希集代替列表。 (3认同)

Tim*_*vis 10

另外:某些程序集不会立即加载,因此您还应该在AppDomain的程序集加载事件上放置一个事件处理程序.

AppDomain.CurrentDomain.AssemblyLoad += ....
Run Code Online (Sandbox Code Playgroud)


Gis*_*shu 8

如何使用GetReferencedAssemblies来处理AssemblyRef元数据条目?"解决方案"不是CLR知道或关心的东西......它在Assemblies中处理.

private static List<Assembly> GetListOfEntryAssemblyWithReferences()
{
  List<Assembly> listOfAssemblies = new List<Assembly>();
  var mainAsm = Assembly.GetEntryAssembly();
  listOfAssemblies.Add(mainAsm);

  foreach (var refAsmName in mainAsm.GetReferencedAssemblies())
  {
    listOfAssemblies.Add(Assembly.Load(refAsmName));
  }
  return listOfAssemblies;
}
Run Code Online (Sandbox Code Playgroud)

注意事项:
1.你仍然需要过滤核心组件系统.*2.这只是在ref链中的一个深层......但可以递归地完成 - 使用更多代码.