Загрузка сборки и применение предиката к ее типам в другом домене приложения

Пожалуйста, прочитайте весь вопрос. У меня уникальная ситуация с несколькими ограничениями, которые я хотел бы решить.

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

// this is what I need:
return assembly.GetTypes().Where(t => predicate(t)).Select(t => t.FullName);

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

Здесь все становится сложнее. Есть несколько проблем, с которыми я сталкиваюсь.:

Если я загружаю сборку в другой домен приложения и просто возвращаю массив всех ее типов,чтобы я мог применить предикат обратно в свой основной домен приложения, как только типы будут упорядочены обратно в мой основной домен приложения, я получаю FileNotFoundException, утверждающий, что эта сборка не найдена. Это имеет смысл, потому что сборка загружается только в другом созданном мной домене приложения. Загрузка его также в основной домен приложения приведет к поражению цели.

Если, в качестве альтернативы, я попытаюсь передать предикат в другой домен приложения, чтобы применить его там и получить обратно массив строк (полное имя типа ), я получаю SerializationException: "Cannot serialize delegates over unmanaged function pointers, dynamic methods or methods outside the delegate creator's assembly.", потому что предикат Динамический метод (, скомпилированный из дерева выражений ).

Загрузка в основной домен приложения не вызовет никаких проблем, но, поскольку невозможно выгрузить загруженную сборку без выгрузки всего домена приложения, как только сборка изменится (после перестроения ), любая попытка загрузка сборки с тем же именем приведет к исключению.

Контекст:
Я создаю подключаемый модуль для ReSharper под названием Agent Mulder . Идея плагина заключается в анализе регистраций контейнеров DI/IoC в вашем решении и помощи ReSharper в определении использования типов, зарегистрированных через контейнер DI (. Вы можете посмотреть короткое видео о том, как это работает здесь ). ].

По большей части анализ регистрации контейнеров не вызывает затруднений. -Мне достаточно собрать достаточно информации, чтобы узнать, какие конкретные типы затронуты. В этом примере с замком Виндзор:Component.For().ImplementedBy()результирующий тип очевиден, поэтомуAllTypes.FromThisAssembly().BasedOn()-дает мне достаточно информации, чтобы приблизительно оценить конкретные типы, на которые повлияет эта строка. Однако рассмотрим эту регистрацию в источнике Castle Windsor:

container.Register(Classes
   .FromAssemblyInDirectory(new AssemblyFilter(".").FilterByName(an => an.Name.StartsWith("Ploeh.Samples.Booking")))
   .Where(t => !(t.IsGenericType && t.GetGenericTypeDefinition() == typeof(Dispatcher<>)))
   .WithServiceAllInterfaces());

()

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

Поскольку все, что я могу сделать, это статически проанализировать это, у меня в руках AST ReSharper (, называемый PSI в ReSharper )представлении лямбда-выражения из предложения Where.Я могу преобразовать этот AST в дерево выражений LINQ, а затем скомпилировать его в делегат.

Моя идея заключалась в том, чтобы загрузить выходную сборку (, определенную FromAssembly*дескриптором )посредством отражения, и применить этот делегат к типам сборки, чтобы получить имена типов (Мне нужны только имена ). Это также нужно -оценивать каждый раз, когда изменяется сборка (На данный момент я не беспокоюсь о производительности ).

В заключение, если кто-то не может порекомендовать лучший способ определения типов, затронутых предикатом, я хотел бы знать, как это сделать с помощью отражения (К сожалению, я не рассматривал другие программы чтения метаданных, потому что я d нужно каким-то образом преобразовать лямбда-выражение AST в предикат другого типа данных, и я не знаю, существует ли преобразование 1 -в -1 ).

Спасибо, что прочитали. Когда этот вопрос станет доступным, награда за этот вопрос составит 500 баллов.

8
задан Igal Tabachnik 7 May 2012 в 11:46
поделиться