Извлечение объектов, которые реализуют интерфейс из нескольких сборок - PullRequest
2 голосов
/ 02 февраля 2012

Я хотел бы получить перечисление созданных экземпляров классов, которые реализуют интерфейс из нескольких сборок в папке решения.

У меня есть следующая структура папки (если это имеет смысл):

Solution
   -SolutionFolder
      - Project1
          - class implementing interface I would like to find
          - other classes

      - Project2
          - class implementing interface I would like to find
          - other classes

   -MainProject
      - classes where my code is running in which I would like to retrieve the list of classes

Поэтому, если реализуемый интерфейс - ISettings, то я бы хотел IEnumerable<ISettings>, ссылающийся на экземпляры этого интерфейса.

До сих пор я использовал отражение для извлечения классов, которыереализовать интерфейс с известным именем класса:

IEnumerable<ISettings> configuration = 
                (from t in Assembly.GetAssembly(typeof(CLASSNAME-THAT-IMPLEMENTs-INTERFACE-HERE)).GetTypes()
                 where t.GetInterfaces().Contains(typeof(ISettings)) && t.GetConstructor(Type.EmptyTypes) != null
                 select (ISettings)Activator.CreateInstance(t)).ToList();

, но это одна сборка, и я на самом деле не буду знать имена классов.

Может ли это быть достигнуто с помощью отражения или требуетсячто-то еще?

Ответы [ 2 ]

1 голос
/ 02 февраля 2012

Пока вы говорите только о сборках, которые загружены в домен приложений (которым они должны быть для того, чтобы делать то, что вам нужно), вы можете использовать что-то вроде этого для их перебора: 1001 *

AppDomain.CurrentDomain
         .GetAssemblies().ToList()
         .ForEach(a => /* Insert code to work with assembly here */);

Или, если они загружены в другой домен приложения, вы можете использовать экземпляр вместо AppDomain.CurrentDomain выше.

0 голосов
/ 03 февраля 2012

Чтобы решить эту проблему, я установил событие после сборки каждого проекта в папке решения, чтобы скопировать его сборку в папку bin в папке bin основных проектов.

Событие пост-сборки было установлено так:

copy "$(TargetPath)" "$(SolutionDir)MainProjectName\bin"

Затем я использовал следующее для извлечения имен файлов сборок из этого каталога bin (благодарность Дарину за его пост решения здесь ):

string[] assemblyFiles = Directory.GetFiles(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "bin"), "*.dll");

Затем я получил реализации объектов, реализующих интерфейс ISettings, используя:

IEnumerable<ISettings> configuration = assemblyFiles.Select(f => Assembly.LoadFrom(f))
                .SelectMany(a => a.GetTypes())
                .Where(t => t.GetInterfaces().Contains(typeof(ISettings)) && t.GetConstructor(Type.EmptyTypes) != null)
                .Select(t => (ISettings)Activator.CreateInstance(t));

Это позволяет мне добавлять другие проекты, которые реализуют настройки, без перекомпиляции основного проекта.

Кроме того, я рассмотрел одну альтернативу: MEF, где можно найти введение здесь .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...