插件模块
模块 也可以作为插件加载。这意味着您无需在解决方案中直接引用模块的程序集;相反,您可以在应用程序启动时像加载其他模块一样加载它。
基本用法
WebApplicationBuilder.AddApplicationAsync<T>() 扩展方法可以获取配置插件源的选项。
示例:从文件夹加载插件
await builder.AddApplicationAsync<MyPlugInDemoWebModule>(options =>
{
options.PlugInSources.AddFolder(@"D:\Temp\MyPlugIns");
});
- 这是典型 ASP.NET Core 应用程序的
Startup类。 PlugInSources.AddFolder获取一个文件夹路径,并加载该文件夹中的程序集(通常是dll文件)。
就这样。ABP 将在给定文件夹中发现模块,配置并初始化它们,就像常规模块一样。
插件源
options.PlugInSources 实际上是 IPlugInSource 实现的列表,AddFolder 只是以下表达式的简写形式:
options.PlugInSources.Add(new FolderPlugInSource(@"D:\Temp\MyPlugIns"));
AddFolder()仅查找给定文件夹中的程序集文件,但不查找子文件夹。您可以传递SearchOption.AllDirectories作为第二个参数,以递归方式从子文件夹中搜索插件。
还有两个内置的插件源实现:
PlugInSources.AddFiles()获取程序集(通常是dll)文件列表。这是使用FilePlugInSource类的简写形式。PlugInSources.AddTypes()获取模块类类型列表。如果您使用此方法,需要自己加载模块的程序集,但在需要时提供了灵活性。这是使用TypePlugInSource类的简写形式。
如果需要,您可以创建自己的 IPlugInSource 实现,并像其他插件源一样添加到 options.PlugInSources 中。
示例:创建一个简单插件
在解决方案中创建一个简单的类库项目:
您可以添加模块中需要使用的 ABP 包。至少,您应该将 Volo.Abp.Core 包添加到项目中。在要安装包的 .csproj 文件所在文件夹中执行以下命令:
abp add-package Volo.Abp.Core
如果尚未安装,您首先需要安装 ABP CLI。有关其他安装选项,请参阅 包详情页面。
每个 模块 必须声明一个从 AbpModule 派生的类。这里是一个简单的模块类,它在应用程序启动时解析服务并初始化:
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp;
using Volo.Abp.Modularity;
namespace MyPlugIn
{
public class MyPlungInModule : AbpModule
{
public override void OnApplicationInitialization(ApplicationInitializationContext context)
{
var myService = context.ServiceProvider
.GetRequiredService<MyService>();
myService.Initialize();
}
}
}
MyService 可以是注册到 依赖注入 系统中的任何类,如下所示:
using Microsoft.Extensions.Logging;
using Volo.Abp.DependencyInjection;
namespace MyPlugIn
{
public class MyService : ITransientDependency
{
private readonly ILogger<MyService> _logger;
public MyService(ILogger<MyService> logger)
{
_logger = logger;
}
public void Initialize()
{
_logger.LogInformation("MyService has been initialized");
}
}
}
构建项目,打开构建文件夹,找到 MyPlugIn.dll:
将 MyPlugIn.dll 复制到插件文件夹(此示例中为 D:\Temp\MyPlugIns)。
如果使用
build folder文件夹作为PlugInSources,请删除MyPlugIn.deps.json文件。
如果您已如上所述配置了主应用程序(请参阅基本用法部分),您应该在应用程序启动时看到 MyService has been initialized 日志。
示例:创建带有 Razor 页面的插件
创建包含视图的插件需要更多注意。
此示例假设您已使用应用程序启动模板和 MVC / Razor Pages UI 创建了一个新的 Web 应用程序。
在解决方案中创建一个新的类库项目:
编辑 .csproj 文件内容:
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<OutputType>Library</OutputType>
<IsPackable>true</IsPackable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared" Version="9.3.3" />
</ItemGroup>
</Project>
- 将
Sdk更改为Microsoft.NET.Sdk.Web。 - 添加了
OutputType和IsPackable属性。 - 添加了
Volo.Abp.AspNetCore.Mvc.UI.Theme.SharedNuGet 包。
依赖 Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared 包不是必需的。您可以引用更基础的包,如 Volo.Abp.AspNetCore.Mvc。但是,如果您要构建 UI 页面/组件,建议引用 Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared 包,因为它是最高级别的包,不依赖特定的 主题 。如果依赖特定主题没有问题,您可以直接引用主题的包,以便在插件中使用主题特定功能。
然后在插件中创建模块类:
using System.IO;
using System.Reflection;
using Microsoft.AspNetCore.Mvc.ApplicationParts;
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared;
using Volo.Abp.Modularity;
namespace MyMvcUIPlugIn
{
[DependsOn(typeof(AbpAspNetCoreMvcUiThemeSharedModule))]
public class MyMvcUIPlugInModule : AbpModule
{
public override void PreConfigureServices(ServiceConfigurationContext context)
{
PreConfigure<IMvcBuilder>(mvcBuilder =>
{
//添加插件程序集
mvcBuilder.PartManager.ApplicationParts.Add(new AssemblyPart(typeof(MyMvcUIPlugInModule).Assembly));
//如果插件模块包含 razor 视图,添加 CompiledRazorAssemblyPart。
mvcBuilder.PartManager.ApplicationParts.Add(new CompiledRazorAssemblyPart(typeof(MyMvcUIPlugInModule).Assembly));
});
}
}
}
- 依赖
AbpAspNetCoreMvcUiThemeSharedModule,因为我们添加了相关的 NuGet 包。 - 将插件的程序集作为
AssemblyPart和CompiledRazorAssemblyPart添加到 ASP.NET Core MVC 的PartManager中。这是 ASP.NET Core 要求的。否则,插件中的控制器或视图将无法工作。
现在您可以在 Pages 文件夹中添加 razor 页面,如 MyPlugInPage.cshtml:
@page
@model MyMvcUIPlugIn.Pages.MyPlugInPage
<h1>欢迎来到我的插件页面</h1>
<p>此页面位于插件模块内! :)</p>
现在,您可以构建插件项目。它将产生以下输出:
将 MyMvcUIPlugIn.dll 复制到插件文件夹(此示例中为 D:\Temp\MyPlugIns)。
如果您已如上所述配置了主应用程序(请参阅基本用法部分),您应该能够在应用程序运行时访问 /MyPlugInPage URL:
讨论
在现实世界中,您的插件可能有一些外部依赖项。此外,您的应用程序可能设计为支持插件。所有这些都是您自己的系统需求。ABP 所做的只是在应用程序启动时加载模块。您在模块内部做什么取决于您自己。
但是,我们可以为一些常见情况提供一些建议。
库依赖
对于包/dll 依赖项,您可以将相关的 dll 复制到插件文件夹中。ABP 会自动加载文件夹中的所有程序集,您的插件将按预期工作。
有关此情况的更多说明,请参阅 Microsoft 的文档。
数据库架构
如果您的模块使用关系数据库和 Entity Framework Core,它将需要在数据库中拥有其表。当应用程序使用插件时,有不同的方法确保表已创建。一些示例:
- 插件可以检查数据库表是否存在,并在应用程序启动时创建表,或者在插件已更新并需要一些架构更改时迁移它们。您可以使用 EF Core 的迁移 API 来实现这一点。
- 您可以改进
DbMigrator应用程序,以查找插件的迁移并执行它们。
可能有其他解决方案。例如,如果您的数据库管理员不允许您在应用程序代码中更改数据库架构,您可能需要手动将 SQL 文件发送给数据库管理员以应用于数据库。
插件示例
我们有一个示例,您可以从 abp-sample 存储库 下载。
抠丁客







