Поиск типов во всех сборках
Мне нужно искать конкретные типы во всех сборках на веб-сайте или в приложении Windows, есть ли простой способ сделать это? Подобно тому, как контроллер factory для ASP.NET MVC просматривает все сборки для контроллеров.
Спасибо.
Ответы
Ответ 1
Для этого есть два шага:
-
AppDomain.CurrentDomain.GetAssemblies()
предоставляет вам все сборки, загруженные в текущий домен приложения.
- Класс
Assembly
предоставляет метод GetTypes()
для извлечения всех типов внутри этой конкретной сборки.
Следовательно, ваш код может выглядеть так:
foreach (Assembly a in AppDomain.CurrentDomain.GetAssemblies())
{
foreach (Type t in a.GetTypes())
{
// ... do something with 't' ...
}
}
Чтобы искать конкретные типы (например, реализуя данный интерфейс, наследуя от общего предка или что-то еще), вам придется отфильтровывать результаты. В случае, если вам нужно сделать это в нескольких местах приложения, полезно создать вспомогательный класс, предоставляющий различные параметры. Например, я обычно применял фильтры префикса пространства имен, фильтры реализации интерфейса и фильтры наследования.
Подробную документацию смотрите в MSDN здесь и здесь.
Ответ 2
Простое использование Linq:
IEnumerable<Type> types =
from a in AppDomain.CurrentDomain.GetAssemblies()
from t in a.GetTypes()
select t;
foreach(Type t in types)
{
...
}
Ответ 3
Решение 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));
}
Ответ 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;
}
}
}
}
}