如何在Razor Pages应用程序中从插件动态加载页面? [英] How to dynamically load pages from plugins in Razor Pages application?

查看:333
本文介绍了如何在Razor Pages应用程序中从插件动态加载页面?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用Razor Pages应用程序处理插件.

I'm trying to deal with plugins using Razor Pages application.

解决方案由3个项目组成:一个Razor Pages应用程序和两个Razor类库(RCL).应用程序不得静态引用RCL项目,它们必须作为插件加载:

Solution consists of 3 projects: one Razor Pages application and two Razor Class Libraries (RCL). Application must not refer RCL projects statically, they must be loaded as plugins:

页面内部没有特殊之处.功能页面仅生成简单的HTML.索引页建立了一种菜单.

There's nothing special inside pages. Feature pages just produce simple HTML. Index page builds a sort of menu.

索引页模型:

public class IndexModel : PageModel
{
    public IEnumerable<MenuItem> MenuItems { get; private set; }

    public void OnGet()
    {
        MenuItems = new List<MenuItem>
        {
            new MenuItem { Route = "FeatureA", Title = "Feature A" },
            new MenuItem { Route = "FeatureB", Title = "Feature B" }
        };
    }
}

索引页:

@page
@model IndexModel
@{
    ViewData["Title"] = "Home page";
}

<div class="text-center">
    <div class="navbar-collapse collapse d-sm-inline-flex flex-sm-row-reverse">
        <ul class="navbar-nav flex-grow-1">
            @foreach (var item in Model.MenuItems)
            {
                <li class="nav-item">
                    <a class="nav-link text-dark" asp-area="" asp-page="/@item.Route">@item.Title</a>
                </li>
            }
        </ul>
    </div>
</div>

我运行该应用程序时,有一些菜单项,但是它们的href是空的:

When I run the app, there are menu items, but their hrefs are empty:

<div class="text-center">
    <div class="navbar-collapse collapse d-sm-inline-flex flex-sm-row-reverse">
        <ul class="navbar-nav flex-grow-1">
                <li class="nav-item">
                    <a class="nav-link text-dark" href="">Feature A</a>
                </li>
                <li class="nav-item">
                    <a class="nav-link text-dark" href="">Feature B</a>
                </li>
        </ul>
    </div>
</div>

当然,所有程序集(应用程序和功能部件)都在同一目录中.

Of course, all assemblies (app and feature ones) are in the same directory.

菜单在以下两种情况下有效:

Menu works in two following cases:

  • 如果我在App项目中引用RCL项目,这会杀死插件的想法;
  • 或者如果我将App.deps.jsonFeatureLib_AFeatureLib_B作为从属关系(只需从第一种情况保存deps文件,删除引用,重建所有文件,复制保存的deps文件).
  • either if I refer RCL projects in App project, which kills plugins idea;
  • or if I put App.deps.json with FeatureLib_A and FeatureLib_B as dependecies (just save deps file from first case, remove references, rebuild all, copy saved deps file).

此外,我试图在Startup类中急切地加载RCL程序集. 程序集正在加载,但是Index页面的行为相同.

Also, I've tried to eagerly load RCL assemblies in Startup class. Assemblies are being loaded, but Index page behaves the same.

有没有办法告诉ASP基础结构使用RCL程序集而不修改deps文件?我想念什么?

Is there any way to tell ASP infrastructure to use RCL assemblies without modifying deps file? What am I missing?

推荐答案

我已经弄清楚了.

基本思想是为ApplicationPartManager提供适当的应用程序部分.
重要的是要注意:

The basic idea is to give ApplicationPartManager appropriate application parts.
It's important to note that:

  • 代码"程序集(例如FeatureLib_A.dll)必须添加为AssemblyPart;
  • 视图"程序集(例如FeatureLib_A.Views.dll)必须作为CompiledRazorAssemblyPart添加.
  • "code" assemblies (e.g. FeatureLib_A.dll) must be added as AssemblyPart;
  • "view" assemblies (e.g. FeatureLib_A.Views.dll) must be added as CompiledRazorAssemblyPart.

示例代码:

public class Startup
{
    // ...

    public void ConfigureServices(IServiceCollection services)
    {
        var assemblyLoader = new DotNetCoreAssemblyLoader(searchPattern: "FeatureLib*.dll");

        services.AddMvc()
            .ConfigureApplicationPartManager(_ =>
            {
                foreach (var assembly in assemblyLoader.Assemblies)
                {
                    if (assembly.FullName.Contains("Views"))
                    {
                        _.ApplicationParts.Add(new CompiledRazorAssemblyPart(assembly));
                    }
                    else
                    {
                        _.ApplicationParts.Add(new AssemblyPart(assembly));
                    }
                }
            })
            .SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
    }

    // ...
}

DotNetCoreAssemblyLoader是一个自定义类,它使用给定的搜索模式查找程序集文件,并通过AssemblyLoadContext.Default.LoadFromAssemblyPath加载程序集.

DotNetCoreAssemblyLoader is a custom class, which looks for assembly files using given search pattern, and loads assemblies via AssemblyLoadContext.Default.LoadFromAssemblyPath.

这篇关于如何在Razor Pages应用程序中从插件动态加载页面?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆