Как зайти в Даркнет?!
25th January, 01:11
6
0
Как в tkinter из поля ввода Entry получить значение в одну переменную и обновить строку кнопкой, затем получить ещё одно введённое значение и затем сложить их. Ниже пример кода
21st July, 19:00
895
0
Программа, которая создает фейковые сервера в поиске игровых серверов CS 1.6 Steam
21st March, 17:43
948
0
Очень долго работает Update запрос Oracle
27th January, 09:58
914
0
не могу запустить сервер на tomcat HTTP Status 404 – Not Found
21st January, 18:02
905
0
Где можно найти фрилансера для выполнения поступающих задач, на постоянной основе?
2nd December, 09:48
938
0
Разработка мобильной кроссплатформенной военной игры
16th July, 17:57
1724
0
период по дням
25th October, 10:44
3955
0
Пишу скрипты для BAS только на запросах
16th September, 02:42
3720
0
Некорректный скрипт для закрытия блока
14th April, 18:33
4613
0
прокидывать exception в блоках try-catch JAVA
11th March, 21:11
4381
0
Помогите пожалуйста решить задачи
24th November, 23:53
6086
0
Не понимаю почему не открывается детальное описание продукта
11th November, 11:51
4351
0
Нужно решить задачу по программированию на массивы
27th October, 18:01
4396
0
Метода Крамера С++
23rd October, 11:55
4309
0
помогите решить задачу на C++
22nd October, 17:31
4002
0
Помогите решить задачу на python с codeforces
22nd October, 11:11
4492
0
Python с нуля: полное руководство для начинающих
18th June, 13:58
2599
0
Получение всех типов, реализующих интерфейс
Используя отражение, как я могу получить все типы, которые реализуют интерфейс с C# 3.0/.NET 3.5 с наименьшим количеством кода и минимизацией итераций?
Вот что я хочу переписать:
foreach (Type t in this.GetType().Assembly.GetTypes())
if (t is IMyInterface)
; //do stuff
Чтобы найти все типы в assembly, которые реализуют интерфейс IFoo:
var results = from type in someAssembly.GetTypes()
where typeof(IFoo).IsAssignableFrom(type)
select type;
Обратите внимание, что предложение Райана Ринальди было неверным. Он будет возвращать 0 типов. Вы не можете писать
where type is IFoo
потому что тип-это экземпляр System.Type, и никогда не будет иметь тип IFoo. Вместо этого вы проверяете, можно ли назначить IFoo из этого типа. Это даст вам ожидаемые результаты.
Кроме того, предложение Adam Райта, которое в настоящее время помечено как ответ, также неверно, и по той же причине. Во время выполнения вы увидите, что возвращается 0 типов, потому что все экземпляры System.Type не были реализаторами IFoo.
Я понимаю, что это очень старый вопрос, но я подумал, что добавлю еще один ответ для будущих пользователей, поскольку все ответы на сегодняшний день используют некоторую форму Assembly.GetTypes .
Хотя GetTypes() действительно вернет все типы, это не обязательно означает, что вы можете активировать их и таким образом потенциально бросить ReflectionTypeLoadException .
Классический пример невозможности активировать тип - это когда возвращаемый тип derived из base , но base определен в другом assembly из derived, assembly, на который не ссылается вызывающий assembly.
Так скажем у нас есть:
Class A // in AssemblyA
Class B : Class A, IMyInterface // in AssemblyB
Class C // in AssemblyC which references AssemblyB but not AssemblyA
Если в ClassC , который находится в AssemblyC , мы тогда делаем что-то согласно принятому ответу:
var type = typeof(IMyInterface);
var types = AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(s => s.GetTypes())
.Where(p => type.IsAssignableFrom(p));
Тогда он бросит ReflectionTypeLoadException .
Это происходит потому, что без ссылки на AssemblyA в AssemblyC вы бы не смогли:
var bType = typeof(ClassB);
var bClass = (ClassB)Activator.CreateInstance(bType);
Другими словами, ClassB не загружается , что является тем, что проверяет и бросает вызов GetTypes.
Таким образом, чтобы безопасно квалифицировать результирующий набор для загружаемых типов, то в соответствии с этой статьей Phil Haacked получите все типы в коде Assembly и Jon Skeet , вместо этого вы сделаете что-то вроде:
public static class TypeLoaderExtensions {
public static IEnumerable<Type> GetLoadableTypes(this Assembly assembly) {
if (assembly == null) throw new ArgumentNullException("assembly");
try {
return assembly.GetTypes();
} catch (ReflectionTypeLoadException e) {
return e.Types.Where(t => t != null);
}
}
}
И затем:
private IEnumerable<Type> GetTypesWithInterface(Assembly asm) {
var it = typeof (IMyInterface);
return asm.GetLoadableTypes().Where(it.IsAssignableFrom).ToList();
}
Другие ответы здесь используют IsAssignableFrom . Вы также можете использовать FindInterfaces из пространства имен System , как описано здесь .
Вот пример, который проверяет все сборки в текущей папке assembly, ища классы, которые реализуют определенный интерфейс (избегая LINQ для ясности).
static void Main() {
const string qualifiedInterfaceName = "Interfaces.IMyInterface";
var interfaceFilter = new TypeFilter(InterfaceFilter);
var path = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
var di = new DirectoryInfo(path);
foreach (var file in di.GetFiles("*.dll")) {
try {
var nextAssembly = Assembly.ReflectionOnlyLoadFrom(file.FullName);
foreach (var type in nextAssembly.GetTypes()) {
var myInterfaces = type.FindInterfaces(interfaceFilter, qualifiedInterfaceName);
if (myInterfaces.Length > 0) {
// This class implements the interface
}
}
} catch (BadImageFormatException) {
// Not a .net assembly - ignore
}
}
}
public static bool InterfaceFilter(Type typeObj, Object criteriaObj) {
return typeObj.ToString() == criteriaObj.ToString();
}
Вы можете настроить список интерфейсов, если хотите, чтобы они совпадали с несколькими.
перебирайте все загруженные сборки, перебирайте все их типы и проверяйте, реализуют ли они интерфейс.
что-то вроде:
Type ti = typeof(IYourInterface);
foreach (Assembly asm in AppDomain.CurrentDomain.GetAssemblies()) {
foreach (Type t in asm.GetTypes()) {
if (ti.IsAssignableFrom(t)) {
// here's your type in t
}
}
}
Edit: я только что видел правку, чтобы уточнить, что первоначальный вопрос был для сокращения итераций / кода, и это все хорошо и хорошо как упражнение, но в реальных ситуациях вы будете хотеть самой быстрой реализации, независимо от того, насколько круто выглядит лежащий в основе LINQ.
Вот мой метод Utils для перебора загруженных типов. Он обрабатывает обычные классы, а также интерфейсы, и опция excludeSystemTypes значительно ускоряет процесс, если вы ищете реализации в своей собственной / сторонней кодовой базе.
public static List<Type> GetSubclassesOf(this Type type, bool excludeSystemTypes) {
List<Type> list = new List<Type>();
IEnumerator enumerator = Thread.GetDomain().GetAssemblies().GetEnumerator();
while (enumerator.MoveNext()) {
try {
Type[] types = ((Assembly) enumerator.Current).GetTypes();
if (!excludeSystemTypes || (excludeSystemTypes && !((Assembly) enumerator.Current).FullName.StartsWith("System."))) {
IEnumerator enumerator2 = types.GetEnumerator();
while (enumerator2.MoveNext()) {
Type current = (Type) enumerator2.Current;
if (type.IsInterface) {
if (current.GetInterface(type.FullName) != null) {
list.Add(current);
}
} else if (current.IsSubclassOf(type)) {
list.Add(current);
}
}
}
} catch {
}
}
return list;
}
Признаюсь, это не очень красиво.
Другие ответы не работали с общим интерфейсом .
Это действительно так, просто замените typeof (ISomeInterface) на typeof (T).
List<string> types = AppDomain.CurrentDomain.GetAssemblies().SelectMany(x => x.GetTypes())
.Where(x => typeof(ISomeInterface).IsAssignableFrom(x) && !x.IsInterface && !x.IsAbstract)
.Select(x => x.Name).ToList();
Так что с
AppDomain.CurrentDomain.GetAssemblies().SelectMany(x => x.GetTypes())
мы получаем все сборки
!x.IsInterface && !x.IsAbstract
используется для исключения интерфейсных и абстрактных и
.Select(x => x.Name).ToList();
чтобы иметь их в списке.
Нет простого способа (с точки зрения производительности) сделать то, что вы хотите сделать.
Отражение работает в основном с ассемблерами и типами, поэтому вам придется получить все типы assembly и запросить их для правильного интерфейса. Вот вам пример:
Assembly asm = Assembly.Load("MyAssembly");
Type[] types = asm.GetTypes();
Type[] result = types.where(x => x.GetInterface("IMyInterface") != null);
Это даст вам все типы, которые реализуют IMyInterface в Assembly MyAssembly
Еще лучше при выборе места Assembly. Фильтруйте большинство сборок, если вы знаете, что все ваши реализованные интерфейсы находятся в пределах одного Assembly.DefinedTypes.
// We get the assembly through the base class
var baseAssembly = typeof(baseClass).GetTypeInfo().Assembly;
// we filter the defined classes according to the interfaces they implement
var typeList = baseAssembly.DefinedTypes.Where(type => type.ImplementedInterfaces.Any(inter => inter == typeof(IMyInterface))).ToList();
У меня есть исключения в linq-коде, поэтому я делаю это таким образом (без сложного расширения):
private static IList<Type> loadAllTypes(Types[] interfaces)
{
IList<Type> objects = new List<Type>();
// find all types
foreach (var interfaceType in interfaces)
foreach (var currentAsm in AppDomain.CurrentDomain.GetAssemblies())
try
{
foreach (var currentType in currentAsm.GetTypes())
if (interfaceType.IsAssignableFrom(currentType) && currentType.IsClass && !currentType.IsAbstract)
objects.Add(currentType);
}
catch { }
return objects;
}