Идея
Я пытаюсь создать модульное приложение .NET Core MVC, где я могу добавить «модули» (расширения), просто скопировав необходимые библиотеки в предопределенную папку.Приложение определяет набор зависимостей (DI), обработку ошибок и базовый макет;модули обеспечивают реальную логику приложения или страницы.
Мы создали доказательство концепции, используя ExtCore - концепция прекрасно работает, контроллеры добавляются автоматически, и «простые» представленияраспознается легко (те, которые установлены как 'Embedded Resource').
Challenge
Однако мне не нравится тот факт, что Views установлен на 'Embedded Resource', так какбудет небольшим ударом по производительности, поскольку страница Razor теперь создается во время выполнения.
Что мы попробовали
Поскольку .NET Core 2.1 теперь имеет возможность создавать Многоразовый пользовательский интерфейс Razor , я создал проект со ссылкой<Project Sdk="Microsoft.NET.Sdk.Razor">
и скомпилировал его в библиотеку Razor (* .Views.dll).
Когда я связываю библиотеку Razor View как зависимость проекта в (основном) приложении, все работает нормально.Тем не менее, цель по-прежнему состоит в том, чтобы сделать приложение полностью подключаемым и воспроизводить и разрешить включение библиотек, просто развернув их в папке.
Я пытался добиться этого, расширяя Razor View Engine с помощьюPhysicalFileProvider
, но он не распознает представления в библиотеке.
services.Configure<RazorViewEngineOptions>(opt =>
{
opt.FileProviders.Add(new PhysicalFileProvider("path/to/extension"));
});
Результатом всегда является исключение, сообщающее, что /Views/[controller]/[action].cshtml
не найдено.
Поиск других ответовЯ наткнулся на этот проект, который создает ViewLocationExpander
.Я попытался реализовать различные версии этой идеи без удачи - скорее всего потому, что это более старая концепция, основанная на .NET Core 1.x, в которой все еще используется зависимость проекта;хотя движок Razor View теперь ищет пространство имен сборки.
services.Configure<RazorViewEngineOptions>(opt =>
{
opt.FileProviders.Add(new PhysicalFileProvider("path/to/extension");
opt.ViewLocationExpanders.Add(new DynamicLocationExpander());
});
Где DynamicLocationExpander
выглядит так:
public class DynamicLocationExpander: IViewLocationExpander
{
public DynamicLocationExpander()
{
}
public void PopulateValues(ViewLocationExpanderContext context)
{
}
public IEnumerable<string> ExpandViewLocations(ViewLocationExpanderContext context, IEnumerable<string> viewLocations)
{
string assembly = ((ControllerActionDescriptor)context.ActionContext.ActionDescriptor)
.ControllerTypeInfo.AsType().Assembly.GetName().Name;
foreach (var viewLocation in viewLocations)
yield return $"{assembly}/{viewLocation}";
}
}
Вопрос
Как можномы динамически связываем библиотеку Razor View, содержащую предварительно скомпилированные представления, с Razor Engine в (родительском) приложении?