完成插件的服务端和客户端扩展

This commit is contained in:
FalconFly 2023-12-18 14:35:39 +08:00
parent ed42d18013
commit 5f9dbb238a
5 changed files with 109 additions and 22 deletions

View File

@ -3,8 +3,8 @@ using Microsoft.AspNetCore.Mvc.ApplicationParts;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
namespace Falcon.SugarApi.Plugin.Client
{
@ -17,14 +17,15 @@ namespace Falcon.SugarApi.Plugin.Client
/// 注册当前程序集中的控制器
/// </summary>
/// <param name="services">服务集合</param>
/// <param name="assembly">要注册的程序集</param>
/// <returns>服务集合</returns>
public static IServiceCollection AddPluginsController(this IServiceCollection services) {
var pluginAssembly = Assembly.GetExecutingAssembly();
var part = new AssemblyPart(pluginAssembly);
public static IServiceCollection AddPluginsController(this IServiceCollection services,Assembly assembly) {
var part = new AssemblyPart(assembly);
services.AddControllers().ConfigureApplicationPartManager(apm => {
if(!apm.ApplicationParts.Contains(part)) {
apm.ApplicationParts.Add(part);
if(apm.ApplicationParts.Any(a => a.Name == part.Name)) {
return;
}
apm.ApplicationParts.Add(part);
});
return services;
}

View File

@ -1 +1,29 @@
## 插件客户端方法
## 插件客户端方法
在插件程序集中实现IServicePlugin接口并在AddServices方法中注册插件相关服务。
~~~c#
/// <summary>
/// 实现组件注册类
/// </summary>
public class ServicePiugin:IServicePlugin
{
/// <summary>
/// 添加组件服务
/// </summary>
/// <param name="services">服务集合</param>
/// <param name="configuration">配置参数</param>
/// <returns>服务集合</returns>
public IServiceCollection AddServices(IServiceCollection services,IConfiguration configuration) {
//检查是否配置组件配置
if(!configuration.GetSection("baseevent").Exists()) {
return services;
}
//注册本程序集中的组件控制器
services.AddPluginsController(this.GetType().Assembly);
//返回服务集合
return services;
}
}
~~~

View File

@ -8,13 +8,8 @@
### 实现方式
1. 业务模块实现IServicePiugin接口实现插件模块注册。
1.1 注册控制器Controller。未找到注册方法
1.2 注册后台任务BackGroundTask可以实现注册到服务集合内。
1.3 注册配置Options及其他相关类。
2. 工具模块位于Falcon.SugarApi.Plugin内。
2.1 定义IServicePiugin接口。
2.2 定义FindPluginService相关方法用于发现业务模块的IServicePiugin实现。
3. WebAPI模块主网站调用FindPluginService相关方法注册业务插件负责其他模块的创建和注册。
1.1 通过services.AddPluginsController注册控制器。
1.2 后台任务实现BackGroundTask通过services.AddHostedService注册到服务集合内。
2. WebAPI模块主网站通过services.AddPluginService方法注册组件。
### 目前主要问题
1. 无法在业务模块内注册Controller不起作用。

View File

@ -1,11 +1,14 @@
using Microsoft.AspNetCore.Mvc.ApplicationParts;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.FileProviders;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Text;
using System.Threading.Tasks;
@ -29,9 +32,45 @@ namespace Falcon.SugarApi.Plugin.Service
if(name == null) {
return services;
}
foreach(var pluginName in pluginNames) {
var pa = AssemblyLoadHelp.ALCLoad(pluginName);
foreach(Type type in pa.GetTypes()) {
List<Assembly> plugin = new();
var basePath = AppDomain.CurrentDomain.BaseDirectory;
var pluginPath = @"plugin";
foreach(var pn in pluginNames) {
var pf = pn.EndsWith(".dll") ? pn : pn + ".dll";
pf = Path.IsPathRooted(pf) ? pf : Path.Combine(basePath,pluginPath,pf);
if(!File.Exists(pf)) {
pf = Path.IsPathRooted(pn) ? pf : Path.Combine(basePath,pn);
pf = pf.EndsWith(".dll") ? pf : pf + ".dll";
}
if(!File.Exists(pf)) {
throw new FileNotFoundException(pf);
}
var pa = AssemblyLoadHelp.ALCLoad(pf);
if(pa != null) {
plugin.Add(pa);
}
}
services.AddPluginService(config,plugin.ToArray());
return services;
}
/// <summary>
/// 注册插件。
/// <para>查找插件中的IServicePlugin实现并运行其中的AddServices方法注册和初始化插件</para>
/// </summary>
/// <param name="services">服务集合</param>
/// <param name="config">应用程序配置</param>
/// <param name="plugins">插件程序集数组</param>
/// <returns>服务集合</returns>
public static IServiceCollection AddPluginService(this IServiceCollection services,IConfiguration config,params Assembly[] plugins) {
var name = typeof(IServicePlugin).FullName;
if(name == null) {
return services;
}
foreach(Assembly ass in plugins) {
foreach(Type type in ass.GetTypes()) {
if(type == null || !type.IsPublic || type.GetInterface(name) == null) {
continue;
}
@ -39,12 +78,17 @@ namespace Falcon.SugarApi.Plugin.Service
if(tname == null) {
continue;
}
if(type.Assembly.CreateInstance(tname) is not IServicePlugin obj) {
continue;
}
obj.AddServices(services,config);
try {
obj.AddServices(services,config);
}
catch(Exception ex) {
throw new Exception($"注册插件{type.FullName}.IServicePlugin.AddServices]方法时发生异常。",ex);
}
}
}
return services;
}

View File

@ -1 +1,20 @@
## 服务端调用方法
## 服务端调用方法
直接调用以下方法注册组件提供组件名称组件必须位于应用程序根目录或plugin目录内。
~~~c#
/// <summary>
/// 注册插件服务
/// </summary>
/// <param name="services">服务集合</param>
/// <param name="configuration">应用程序配置</param>
private void AddPlugins(IServiceCollection services,IConfiguration configuration) {
try {
services.AddPluginService(configuration,"His.Service.BaseEvent");
}
catch(Exception ex) {
throw new Exception("注册组件时发生异常",ex);
}
}
~~~