Как загрузить сборку и все ее зависимости во время выполнения в C# для отражения?

Я пишу утилиту для себя, отчасти как упражнение в изучении C# Reflection, а отчасти потому, что мне действительно нужен полученный инструмент для собственного использования.

То, что мне нужно, в основном указывает приложению на сборку и выбирает заданный класс, из которого выбираются свойства, которые должны быть включены в экспортируемую HTML-форму в качестве полей. Затем эта форма будет использоваться в моем приложении ASP.NET MVC в качестве начала представления.

Поскольку я использую объекты Subsonic для приложений, которые я хочу использовать, это должно быть разумно, и я решил, что, желая включить такие вещи, как различный выходной HTML в зависимости от типа данных, Reflection был способом сделать это.

Однако то, что я ищу, кажется неуловимым. Я пытаюсь взять DLL/EXE, выбранную через OpenFileDialog, в качестве отправной точки и загрузить ее:

String FilePath = Path.GetDirectoryName(FileName);
System.Reflection.Assembly o = System.Reflection.Assembly.LoadFile(FileName);

Это прекрасно работает, но поскольку объекты, сгенерированные Subsonic, на самом деле полны типов объектов, определенных в Subsonic.dll и т. д., эти зависимые объекты не загружаются. Войти:

AssemblyName[] ReferencedAssemblies = o.GetReferencedAssemblies();

Это тоже содержит именно то, что я ожидал. Однако я пытаюсь понять, как загрузить эти сборки, чтобы мое копание в моих объектах работало правильно. Я понимаю, что если бы эти сборки находились в GAC или в каталоге работающего исполняемого файла, я мог бы просто загрузить их по их имени, но это вряд ли подходит для этого варианта использования, и это мой основной вариант использования.

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

Я знаю, что такие инструменты, как Reflector, делают это, но я просто не могу найти синтаксис для этого.


person J Wynia    schedule 12.09.2008    source источник


Ответы (2)


Пара вариантов здесь:

  1. Присоединитесь к AppDomain.AssemblyResolve и сделайте еще LoadFile на основе запрошенной сборки.
  2. Запустите еще один AppDomain с каталогом в качестве основы и загрузите сборки в этот AppDomain.

Я настоятельно рекомендую использовать вариант 2, так как он, вероятно, будет чище и позволит вам выгрузить все эти сборки после. Кроме того, рассмотрите возможность загрузки сборок в контексте только для отражения, если вам нужно отражать только их (см. Assembly.ReflectionOnlyLoad).

person Kent Boogaart    schedule 12.09.2008

Я разработал второй вариант Кента Бугаарта. По сути, я должен был:

1.) Реализовать ResolveEventHandler в отдельном классе, унаследовав от MarshalByRefObject и добавив атрибут Serializable.

2.) Добавить текущую ApplicationBase, по сути, там, где находится dll обработчика событий, в файл AppDomain PrivateBinPath.

Вы можете найти код на github.

person mathume    schedule 05.05.2016
comment
Вы сказали MarshalByValueObject. Вы имели в виду MarshalByRefObject? - person Tengiz; 24.04.2018
comment
О, верно, MarshalByRefObject. - person mathume; 05.05.2018