Плагиновая структура с ASP.NET MVC3 и встроенными представлениями Razor
Я разрабатываю платформу плагинов для ASP.NET MVC3 с использованием представлений Razor, и у меня возникает проблема с правильной работой встроенных представлений.
Плагиновая структура предназначена для использования этих функций:
- Каждый плагин имеет свои собственные модели, контроллеры и представления. Представления представляют собой встроенные ресурсы, а контроллеры - из класса PluginController
- У плагинов есть ссылки зависимостей на общую библиотеку классов, которая определяет базовый класс PluginController
- Веб-приложение "shell", в котором размещаются плагины , не должно содержать ссылки на любые плагины во время разработки, так как во время разработки он не знает, какие плагины он имеет.
- Плагины dll отбрасываются в папку в приложении оболочки, которая не папка /bin
- Корпус заботится:
- Обнаружение плагинов (с использованием отражения)
- Регистрация всех контроллеров (я использую Spring.Net для этого)
- Создание маршрутов к контроллерам
- Обслуживание файлов бритвы (cshtml) через пользовательский VirtualPathProvider
Теперь все работает нормально, за исключением случаев, когда встроенные представления имеют ссылки на типы в DLL плагина. Затем я получаю печально известную ошибку (имена опущены):
The type or namespace name '[Plugins]' does not exist in the namespace '[MyPluginSolution]' (are you missing an assembly reference?)
Причиной этого является то, что компилятор csc, который вызывается во время выполнения для компиляции представлений бритвы , получает только ссылки dll из папки bin и GAC.
Я также пробовал предварительно компилировать представления, используя эту технику, но в итоге он дает те же результаты, поскольку среда выполнения настаивает на компиляция обертки для предварительно скомпилированного бритва.
Я мог бы, конечно, удалить dll плагина в папку /bin, но мой вопрос:
Есть ли способ зарегистрировать DLL файлы в папке, отличной от bin (и не-GAC), и рассматривать их как "граждан первого класса", чтобы их можно было использовать в виде бритвы?
Ответы
Ответ 1
Хорошо, решение было найдено с помощью этой статьи.
Сначала создаю класс с PreApplicationStartMethod
. Этот метод проверяет папку плагина и копирует DLL на AppDomain.DynamicDirectory
.
Затем каждую из этих dll загружаются с помощью BuildManager.AddReferencedAssembly
.
И вуаля, строго типизированные взгляды Бритвы компилируются красиво. Смотрите код здесь:
[assembly: PreApplicationStartMethod(typeof(MySolution.PluginHandler.PluginActivator), "Initialize")]
namespace MySolution.PluginHandler
{
public class PluginActivator
{
private static readonly DirectoryInfo PluginFolderInfo;
static PluginActivator() {
PluginFolderInfo = new DirectoryInfo(HostingEnvironment.MapPath("~/plugins"));
}
public static void Initialize() {
CopyPluginDlls(PluginFolderInfo, AppDomain.CurrentDomain.DynamicDirectory);
LoadPluginAssemblies(AppDomain.CurrentDomain.DynamicDirectory);
}
private static void CopyPluginDlls(DirectoryInfo sourceFolder, string destinationFolder)
{
foreach (var plug in sourceFolder.GetFiles("*.dll", SearchOption.AllDirectories)) {
if (!File.Exists(Path.Combine(destinationFolder, plug.Name))) {
File.Copy(plug.FullName, Path.Combine(destinationFolder, plug.Name), false);
}
}
}
private static void LoadPluginAssemblies(string dynamicDirectory)
{
foreach (var plug in Directory.GetFiles(dynamicDirectory, "*.dll", SearchOption.AllDirectories)) {
Assembly assembly = Assembly.Load(AssemblyName.GetAssemblyName(plug));
BuildManager.AddReferencedAssembly(assembly);
}
}
}
}
Я надеюсь, что это поможет другим программистам, которые хотят создать чистую плагиновую инфраструктуру с использованием этих новых технологий.
Ответ 2
Дэвид Эббо недавно написал о предкомпиляции просмотров Razor в сборках. Вы можете просмотреть сообщение здесь.
Вы должны быть в состоянии избежать регистрации сборок напрямую, динамически загружая сборки (обычно я использую для этого контейнер IoC), а затем вызываю BuildManager.AddReferencedAssembly для каждой сборки плагина.
Ответ 3
Проверьте MEF
Вы также можете сделать это с установщиками Windsor - Майк Хэдлоу хорошо ударил: http://mikehadlow.blogspot.com/2010/10/experimental-aspnet-mvc-add-ins-updated.html
Ответ 4
Пожалуйста, посмотрите исходный код NOPCommerce. У этого есть хорошая плагиновая структура, основанная на работе Shannon.
Ответ 5
Вы также можете использовать функцию "Area" в MVC3 и 4, вы можете создать приятную систему плагинов. Это дает разделение модели плагина обработки, просмотра и контроллера в собственной сборке.
Ответ 6
Вы можете найти это полезным http://www.adverseconditionals.com/2011/07/portable-aspnet-code-using.html
Я начал создавать два проекта
MyLibrary
MyLibrary.Templates
и иметь представления в виде содержимого в .Templates и добавляться в качестве ссылок и устанавливаться в EmbeddedResource в MyLibrary. Люди, которые хотят переопределить представления, могут установить проект .Templates.