Почему сравнение интерфейсов не выполняется с Assembly.ReflectionOnlyLoadFrom (), а не с Assembly.LoadFrom ()? - PullRequest
0 голосов
/ 04 октября 2019

Мой код сканирует различные каталоги на наличие плагинов DLL. Они узнаваемы, потому что имеют экспортированный тип, реализующий IBehaviourPlugin.

. После нескольких публикаций в Интернете я попытался загрузить сборки с помощью следующего кода (зацикливание файлов для удобства чтения):

    // Plugin interface
    Type behaviourPlugin = typeof(OrganShared.IBehaviourPlugin);

    // Load assembly from file
    Assembly a = Assembly.ReflectionOnlyLoadFrom(f);
    Type[] exports = a.GetExportedTypes();
    int validTypes = (from Type t in exports
                          where behaviourPlugin.IsAssignableFrom(t)
                          && behaviourPlugin.FullName != t.FullName
                          select t).Count();
    if (validTypes > 0) { files.Add(new FileInfo(f)); }

Это не позволяет идентифицировать любые сборки, которые соответствуют критериям. Однако , если я заменю Assembly a = Assembly.ReflectionOnlyLoadFrom(f); на Assembly a = Assembly.LoadFrom(f);, типы будут сравниваться идеально, и все мои подключаемые библиотеки DLL будут правильно идентифицированы.

Может кто-нибудь объяснить мне причину такого различного поведения? Это не первая моя прогулка с отражением, но она немного за мной.

Кстати, поведение такое же, если я использую альтернативный метод проверки: t.GetInterfaces().Contains(IBehaviourPlugin)

Наконец, яВ настоящее время я не создаю новый домен приложений для отражения - я подозреваю, что могу / должен / буду нуждаться в этом, но я хотел изолировать это поведение, прежде чем потенциально добавить дополнительные сложности.

Ответы [ 2 ]

2 голосов
/ 04 октября 2019

Я нашел другой поток, похожий на ReflectionOnlyLoad и GetField Кажется, что проверка не работает, если базовый тип не получен при сборке, не загруженной в режиме ReflectionlyOnly. Поэтому попробуйте загрузить тип IBehaviourPlugin следующим образом.

var baseAssembly = assembly.ReflectionOnlyLoad(typeof(OrganShared.IBehaviourPlugin).Assembly.FullName);
var baseTypes = baseAssembly.GetExportedTypes();
var reflectionOnlyBaseType = Array.Find(baseTypes,(t)=>(t.FullName==typeof(OrganShared.IBehaviourPlugin).FullName));

, затем измените

behaviourPlugin.IsAssignableFrom(t) 

на

reflectionOnlyBaseType.IsAssignableFrom(t)
2 голосов
/ 04 октября 2019

Давайте разберемся с этим.

  • Assembly.ReflectionOnlyLoadFrom() загружает вашу сборку только в контекст только для отражения.

Это означает, что ваша библиотека загружается для целей анализатолько. Используется для загрузки 64-битной сборки в 32-битном приложении. Вы можете просматривать типы, методы, свойства, но не сможете выполнять его код.

Когда вы загружаете сборку таким образом, ваш Assembly объект будет иметь ReflectionOnly свойство, установленное вtrue.

Обычная загрузка сборки через .LoadFile() загрузит весь код из сборки и сделает его готовым к выполнению.

Что происходит, когда вы пытаетесь их сравнить?

ОБНОВЛЕНИЕ! Разобрался. Это было проще, чем я думал.

Объект нормального типа имеет тип System.RuntimeType, а другой тип только для отражения имеет тип System.ReflectionOnlyType. Тайна раскрыта.

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