Помогите System.Web.Compilation.BuildManager найти тип в несвязанной сборке - PullRequest
3 голосов
/ 16 апреля 2010

Я пытаюсь написать систему плагинов, в которой сборки можно помещать в папку, о которой 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 голос
/ 26 апреля 2010

Я не знаю, как BuildManager загружает типы, но вы можете попробовать , используя AssemblyResolve - подписаться на событие AppDomain.CurrentDomain.AssemblyResolve, загрузить сборку самостоятельно и вернуться (да, вернуть ) экземпляр Assembly (или null, если вы его не узнаете).

Не весь такой код использует подходы, совместимые с этим, но стоит попробовать.

1 голос
/ 23 апреля 2010

Я вижу два способа указания сборок, используемых для компиляции страницы:

  • Вызов BuildManager.AddReferencedAssembly (но я полагаю, вы уже пробовали это?)
  • Помещение в конфигурацию виртуального каталога страницы компиляции списка требуемых сборок (в разделе system.web / compilation / сборки) и доступность этих сборок в домене приложения (кажется, что среда использует Assembly.Load для поиска найденных сборок). в конфигурационных файлах).
0 голосов
/ 02 августа 2012

Я сам разрабатываю ленивый фреймворк загрузки для ASP.NET. Ваши плагины всегда могут использовать директиву <@ Assembly> на своих страницах, чтобы вручную ссылаться на сборку.

0 голосов
/ 26 апреля 2010

Я решил решить эту проблему с помощью Web Deployment Projects [1] , предварительно скомпилировав все веб-приложение в две отдельные сборки и затем копаясь в нужную сборку с помощью Assembly.GetTypes() создать правильный Page для данного HTTP-запроса.

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

...