Поиск классов в DLL, наследуемых от классов в недоступной сборке

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

Поэтому мое программное обеспечение должно проверять библиотеки DLL, чтобы определить, содержат ли они классы, которые наследуются от классов надстроек API по имени. Однако я не хочу, чтобы мое приложение зависело от самого API. Не нужно создавать экземпляры или выполнять какие-либо из этих классов, нужно только определить полные имена классов, которые наследуются от классов надстроек API.

Я могу загрузить сборку dll, используя:

Assembly.LoadFrom(dllFileName)

Тем не менее, когда я пытаюсь вызвать GetTypes() для загруженной сборки. Я получаю исключение ReflectionTypeLoadException с рядом исключений LoaderException, жалующихся на невозможность найти файлы API.

Я также пытался использовать ReflectionOnlyLoadFrom(), но это вызывало то же исключение.

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


person Eric Anastas    schedule 17.04.2013    source источник
comment
Дикое предположение, зависит ли ваш dllFileName от других dll's. Если да, то являются ли эти dll одним и тем же путем поиска?   -  person jacob aloysious    schedule 17.04.2013
comment
Да в том то и дело. Интересующая DLL зависит от других сборок (API), но я не хочу, чтобы мой инструмент зависел от сборок API. Я не пытаюсь выполнить какой-либо код, только определяю, какие классы в DLL наследуются от конкретных классов в сборке API.   -  person Eric Anastas    schedule 17.04.2013


Ответы (2)


Это невозможно сделать с помощью Reflection API фреймворка. Для отражения требуется доступ к сборкам для загрузки метаданных типа. Что вы можете сделать, так это использовать что-то вроде Mono.Cecil (доступно на nuget) для проверки MSIL. Вот пример, показывающий типы с базовыми классами и интерфейсами в сборке:

using Mono.Cecil;
using Mono.Cecil.Cil;

var assembly = AssemblyDefinition.ReadAssembly("ClassLibrary.dll");
// skip the first type '<Module>' whatever that is.
var types = assembly.MainModule.Types.Skip(1);

foreach (var type in types)
{
    var interfaces = type.Interfaces.Select(i => i.FullName);
    if (interfaces.Any())
    {
         Console.WriteLine("{0} : {1}, {2}", type.FullName, type.BaseType.FullName, string.Join(", ", interfaces));
    }
    else
    {
         Console.WriteLine("{0} : {1}", type.FullName, type.BaseType.FullName);
    }
}

Это не приводит к загрузке сборки или каких-либо ее зависимостей. Это было бы полезно, если вы знаете, что интересующие вас классы напрямую унаследованы от классов внешнего API. Если есть несколько уровней наследования, вам придется проделать больше работы, чем я показал выше.

person Mike Zboray    schedule 17.04.2013
comment
Спасибо. Я попытался установить Mono.Ceil, но свойство type.BaseType.FullName возвращает System.Object, а не имя класса в сборке API. - person Eric Anastas; 17.04.2013
comment
@EricAnastas Это странно. Я протестировал код со сценарием, аналогичным тому, что вы описали в своем вопросе, и получил ожидаемый базовый тип. Если вы посмотрите на это ildasm, что это говорит? - person Mike Zboray; 17.04.2013
comment
Да, и Reflector, и ildasm показывают правильный базовый тип. Ildasm показывает что-то вроде «реализует [APIAssembly] Company.Software.Foobar.APIAddInClass» - person Eric Anastas; 17.04.2013
comment
@EricAnastas Если написано «реализует», это звучит как интерфейс. Я считаю, что ildasm говорит, что он распространяется на базовые классы. Я также отредактировал образец, чтобы показать интерфейсы. - person Mike Zboray; 17.04.2013
comment
Ах да, это работает. Извините, я забыл, что это интерфейс, а не наследование классов. - person Eric Anastas; 17.04.2013

Невозможно использовать Reflection. Если вас просто интересует поиск зависимостей, вы можете использовать ObjectExplorer для просмотра классов в сборке DLL и их базовых типов. И искать типы, не принадлежащие к одной сборке.

Полезную информацию можно найти здесь:
Какая программа в Visual Studio позволяет мне заглянуть в библиотеки DLL, чтобы увидеть ее API?

person Ali    schedule 17.04.2013