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