Как найти все классы, которые реализуют данный интерфейс? - PullRequest
66 голосов
/ 31 марта 2009

В данном пространстве имен у меня есть набор классов, которые реализуют интерфейс. Давайте назовем это ISomething. У меня есть другой класс (назовем его CClass), который знает о ISomething, но не знает о классах, которые реализуют этот интерфейс.

Я бы хотел, чтобы CClass искал всю реализацию ISomething, создал ее экземпляр и выполнил метод.

У кого-нибудь есть идеи, как это сделать с помощью C # 3.5?

Ответы [ 6 ]

129 голосов
/ 31 марта 2009

Рабочий код-образец:

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 завершился успешно.

10 голосов
/ 31 марта 2009

Вы можете получить список загруженных сборок, используя это:

Assembly assembly = System.Reflection.AppDomain.CurrentDomain.GetAssemblies()

Оттуда вы можете получить список типов в сборке (при условии открытых типов):

Type[] types = assembly.GetExportedTypes();

Затем вы можете спросить каждый тип, поддерживает ли он этот интерфейс, найдя этот интерфейс на объекте:

Type interfaceType = type.GetInterface("ISomething");

Не уверен, что есть более эффективный способ сделать это с помощью отражения.

8 голосов
/ 31 марта 2009

Пример использования Linq:

var types =
  myAssembly.GetTypes()
            .Where(m => m.IsClass && m.GetInterface("IMyInterface") != null);
3 голосов
/ 24 января 2011
foreach (Type t in Assembly.GetCallingAssembly().GetTypes())
{
    if (t.GetInterface("ITheInterface") != null)
    {
        ITheInterface executor = Activator.CreateInstance(t) as ITheInterface;
        executor.PerformSomething();
    }
}
2 голосов
/ 31 марта 2009

Вы можете использовать что-то вроде следующего и адаптировать его к вашим потребностям.

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();
    }
}

Этот код может использовать некоторые улучшения производительности, но это только начало.

0 голосов
/ 22 апреля 2016

Может быть, мы должны идти по этому пути

foreach ( var instance in Assembly.GetExecutingAssembly().GetTypes().Where(a => a.GetConstructor(Type.EmptyTypes) != null).Select(Activator.CreateInstance).OfType<ISomething>() ) 
   instance.Execute(); 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...