Как найти все классы, реализующие данный интерфейс?
В данном пространстве имен у меня есть набор классов, которые реализуют интерфейс. Позвольте называть его ISomething
. У меня есть другой класс (пусть его называют CClass
), который знает о ISomething
, но не знает о классах, реализующих этот интерфейс.
Я хотел бы, чтобы CClass
просматривал всю реализацию ISomething
, создавал экземпляр экземпляра и выполнял метод.
Есть ли у кого-нибудь идея о том, как это сделать с С# 3.5?
Ответы
Ответ 1
Рабочий код-образец:
var instances = from t in Assembly.GetExecutingAssembly().GetTypes()
where t.GetInterfaces().Contains(typeof(ISomething))
&& t.GetConstructor(Type.EmptyTypes) != null
select Activator.CreateInstance(t) as ISomething;
foreach (var instance in instances)
{
instance.Foo(); // where Foo is a method of ISomething
}
Изменить Добавлена проверка конструктора без параметров, чтобы вызов CreateInstance преуспел.
Ответ 2
Вы можете получить список загруженных сборок, используя это:
Assembly assembly = System.Reflection.AppDomain.CurrentDomain.GetAssemblies()
Оттуда вы можете получить список типов в сборке (предполагая публичные типы):
Type[] types = assembly.GetExportedTypes();
Затем вы можете спросить каждый тип, поддерживает ли он этот интерфейс, найдя этот интерфейс для объекта:
Type interfaceType = type.GetInterface("ISomething");
Не уверен, есть ли более эффективный способ сделать это с отражением.
Ответ 3
Пример использования Linq:
var types =
myAssembly.GetTypes()
.Where(m => m.IsClass && m.GetInterface("IMyInterface") != null);
Ответ 4
foreach (Type t in Assembly.GetCallingAssembly().GetTypes())
{
if (t.GetInterface("ITheInterface") != null)
{
ITheInterface executor = Activator.CreateInstance(t) as ITheInterface;
executor.PerformSomething();
}
}
Ответ 5
Вы можете использовать что-то вроде следующего и адаптировать его к вашим потребностям.
var _interfaceType = typeof(ISomething);
var currentAssembly = System.Reflection.Assembly.GetExecutingAssembly();
var types = GetType().GetNestedTypes();
foreach (var type in types)
{
if (_interfaceType.IsAssignableFrom(type) && type.IsPublic && !type.IsInterface)
{
ISomething something = (ISomething)currentAssembly.CreateInstance(type.FullName, false);
something.TheMethod();
}
}
Этот код может использовать некоторые улучшения производительности, но это начало.
Ответ 6
Может быть, мы должны пойти этим путем
foreach ( var instance in Assembly.GetExecutingAssembly().GetTypes().Where(a => a.GetConstructor(Type.EmptyTypes) != null).Select(Activator.CreateInstance).OfType<ISomething>() )
instance.Execute();