在所有程序集中查找类型

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

122

实现这个功能需要两步:

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

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

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

要查找特定类型(例如实现给定接口、继承自共同祖先或其他)需要筛选结果。如果您需要在应用程序的多个位置执行此操作,则建议构建一个助手类,提供不同的选项。例如,我通常应用命名空间前缀过滤器、接口实现过滤器和继承过滤器。
有关详细文档,请查看 MSDN 此处此处

1
当然,如果你要对这些类型和程序集进行过滤,你会使用LINQ,对吧? ;) - Niall Connaughton
9
@Niall Connaughton 这是个人喜好的问题。 - Ondrej Tucny
2
我发现在这样做时会导致异常的情况,原来是因为我的应用程序正在生成动态程序集,这只是一个需要注意的问题。您可以像这样识别动态程序集并跳过它们:https://dev59.com/_HM_5IYBdhLWcg3wUxfF - 如果它确实引起了问题。 - James Gaunt
17
请注意,程序集仅在需要时加载,即在它们第一次被使用时。 - CodesInChaos

40

带有检查程序集是否为动态的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));
}

33

Linq简单易用:

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

foreach(Type t in types)
{
    ...
}

10

通常你只关心从外部可见的程序集。因此,你需要调用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;
                }
            }
        }
    }
}

实际上,我仍然在您的代码中遇到“无法加载类型异常”。 - Rafael Herscovici

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接