Помогите System.Web.Compilation.BuildManager найти тип в несвязанной сборке
Я пытаюсь написать систему плагинов, в которой сборки можно помещать в папку, о которой ASP.NET не знает. Эта система плагинов прекрасно работает для сборок на основе ASP.NET MVC, но для сборок старой школы WebForm (где .aspx
файлы Inherits
System.Web.UI.Page
производные классы) System.Web.Compilation.BuildManager
отвечает за составление .aspx
файл в динамическую сборку.
Моя проблема в том, что BuildManager
ничего не знает о сборках в моей папке плагинов, и, похоже, я ничего не могу сделать, чтобы помочь этому. Если я сделаю:
BuildManager.GetType("PluginAssembly.DefinedType", true, true)
это бросает. Если я впервые получу ссылку на Type
а затем попробуйте:
var instance = BuildManager.CreateInstanceFromVirtualPath(path, type);
это все еще бросает, хотя я теперь прошел в конкретном type
это должно скомпилировать .aspx
файл. Могу ли я чем-нибудь помочь? BuildManager
найти типы, необходимые для компиляции .aspx
файл?
Обновление: я сделал еще один шаг вперед, посмотрев, что BuildManager.GetType()
на самом деле Указывая сборку, в которой определяется тип (такой как "PluginAssembly.DefinedType, PluginAssembly"), а затем подключая себя к System.AppDomain.CurrentDomain.AssemblyResolve
Теперь я могу найти сборку плагина и вернуть ее, чтобы BuildManager мог успешно сконструировать тип. Это делает следующую работу с летающими цветами:
BuildManager.GetType("PluginAssembly.DefinedType, PluginAssembly", true, true)
Однако, это все еще терпит неудачу:
var instance = BuildManager.CreateInstanceFromVirtualPath(path, type);
Хотя .aspx
файл теперь имеет такую же ссылку на сборку в своем Inherits
директива:
<%@ Page Language="C#"
CodeBehind="Index.aspx.cs"
Inherits="PluginAssembly.DefinedType, PluginAssembly" %>
Я получаю ошибку:
"Сообщение об ошибке компилятора: CS0234: имя типа или пространства имен" DefinedType "не существует в пространстве имен" PluginAssembly "(отсутствует ссылка на сборку?)" Со следующими исходными данными:
Line 205:
Line 206: [System.Runtime.CompilerServices.CompilerGlobalScopeAttribute()]
Line 207: public class plugins_pluginassembly_dll_index_aspx
: global::PluginAssembly.DefinedType,
System.Web.SessionState.IRequiresSessionState,
System.Web.IHttpHandler {
Line 208:
Line 209: private static bool @__initialized;
Кажется, что происходит внутри BuildManager.CreateInstanceFromVirtualPath()
включает в себя определенный System.Web.Util.IWebObjectFactory
что он может быть ответственным за создание этого исключения, не найдя мою сборку. Я могу реализовать этот интерфейс без каких-либо проблем, но что это поможет, если я не могу сказать BuildManager
об этом?
4 ответа
В итоге я решил эту проблему с помощью проектов веб-развертывания [1], предварительно скомпилировав все веб-приложение в две отдельные сборки, а затем углубившись в нужную сборку с Assembly.GetTypes()
чтобы создать правильный Page
для данного HTTP-запроса.
Это больше ложится на плечи разработчиков плагинов, но дает лучшую производительность с дополнительным преимуществом полной проверки всех плагинов компилятором ASP.NET перед их выполнением в (чувствительном к безопасности и хрупком) веб-контексте.,
Я не знаю как BuildManager
загружает типы, но вы можете попробовать использовать AssemblyResolve
- подписаться на AppDomain.CurrentDomain.AssemblyResolve
событие, и загрузить сборку самостоятельно и вернуть (да, вернуть) Assembly
экземпляр (или null
если ты не узнаешь это).
Не весь такой код использует подходы, совместимые с этим, но это стоит попробовать.
Я вижу два способа указать сборки, используемые для компиляции страницы:
- Вызов BuildManager.AddReferencedAssembly (но я полагаю, вы уже пробовали это?)
- Помещение в конфигурацию виртуального каталога страницы компиляции списка необходимых сборок (в разделе system.web/compilation/ сборки) и доступность этих сборок в домене приложения (среда, кажется, использует Assembly.Load для поиска сборок, найденных в конфигурации. файлы).
Я сам разрабатываю ленивый фреймворк загрузки для ASP.NET. Ваши плагины всегда могут использовать <@ Assembly>
директива на их страницах, чтобы вручную ссылаться на сборку.