【问题标题】:Find Types in All Assemblies在所有程序集中查找类型
【发布时间】:2011-06-09 04:55:42
【问题描述】:

我需要在网站或 Windows 应用程序的所有程序集中查找特定类型,有没有简单的方法可以做到这一点?就像 ASP.NET MVC 的控制器工厂如何查看控制器的所有程序集一样。

谢谢。

【问题讨论】:

    标签: c# .net asp.net reflection types


    【解决方案1】:

    有两个步骤可以实现:

    • AppDomain.CurrentDomain.GetAssemblies() 为您提供当前应用程序域中加载的所有程序集。
    • Assembly 类提供了一个GetTypes() 方法来检索该特定程序集中的所有类型。

    因此您的代码可能如下所示:

    foreach (Assembly a in AppDomain.CurrentDomain.GetAssemblies())
    {
        foreach (Type t in a.GetTypes())
        {
            // ... do something with 't' ...
        }
    }
    

    要查找特定类型(例如,实现给定接口、从共同祖先继承或其他),您必须过滤掉结果。如果您需要在应用程序的多个位置执行此操作,最好构建一个提供不同选项的帮助程序类。例如,我常用命名空间前缀过滤器、接口实现过滤器和继承过滤器。

    有关详细文档,请查看 MSDN herehere

    【讨论】:

    • 当然,如果您要对这些类型和程序集进行一些过滤,您会使用 LINQ,对吗? ;)
    • @Niall Connaughton 这是个人喜好问题。
    • 我发现这样做会导致异常,原来是因为我的应用程序正在生成动态程序集,这只是一个需要注意的问题。您可以识别动态程序集并像这样跳过它们stackoverflow.com/questions/1423733/… - 如果确实会导致问题
    • 请注意,程序集仅按需加载,即第一次使用时。
    【解决方案2】:

    带有检查程序集是否为动态的 LINQ 解决方案:

    /// <summary>
    /// Looks in all loaded assemblies for the given type.
    /// </summary>
    /// <param name="fullName">
    /// The full name of the type.
    /// </param>
    /// <returns>
    /// The <see cref="Type"/> found; null if not found.
    /// </returns>
    private static Type FindType(string fullName)
    {
        return
            AppDomain.CurrentDomain.GetAssemblies()
                .Where(a => !a.IsDynamic)
                .SelectMany(a => a.GetTypes())
                .FirstOrDefault(t => t.FullName.Equals(fullName));
    }
    

    【讨论】:

      【解决方案3】:

      轻松使用 Linq:

      IEnumerable<Type> types =
                  from a in AppDomain.CurrentDomain.GetAssemblies()
                  from t in a.GetTypes()
                  select t;
      
      foreach(Type t in types)
      {
          ...
      }
      

      【讨论】:

        【解决方案4】:

        大多数情况下,您只对从外部可见的程序集感兴趣。因此,您需要调用 GetExportedTypes() 但除此之外,还可以抛出 ReflectionTypeLoadException。以下代码处理了这些情况。

        public static IEnumerable<Type> FindTypes(Func<Type, bool> predicate)
        {
            if (predicate == null)
                throw new ArgumentNullException(nameof(predicate));
        
            foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
            {
                if (!assembly.IsDynamic)
                {
                    Type[] exportedTypes = null;
                    try
                    {
                        exportedTypes = assembly.GetExportedTypes();
                    }
                    catch (ReflectionTypeLoadException e)
                    {
                        exportedTypes = e.Types;
                    }
        
                    if (exportedTypes != null)
                    {
                        foreach (var type in exportedTypes)
                        {
                            if (predicate(type))
                                yield return type;
                        }
                    }
                }
            }
        }
        

        【讨论】:

        • 其实我还是得到了could not load type exception和你的代码。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多