1,webapi主程序中定义插件接口
2,定义一个dll帮助类代码如下:
using System.Runtime.Loader;
namespace LabPluginApi.Utils
{
public static class DllHelper
{
public static List<ILabPlugin> _labPlugins = new List<ILabPlugin>();
private static string _pluginFolder = Path.Combine(Directory.GetCurrentDirectory(), "Plugins");
/// <summary>
/// 重新加载
/// </summary>
public static void ReLoadDll()
{
if (!Directory.Exists(_pluginFolder))
Directory.CreateDirectory(_pluginFolder);
_labPlugins = new List<ILabPlugin>();
foreach (var dllPath in Directory.GetFiles(_pluginFolder, "*.dll"))
{
try
{
var assemblyLoadContext = new AssemblyLoadContext(Path.GetFileNameWithoutExtension(dllPath), true);
var assembly = assemblyLoadContext.LoadFromAssemblyPath(dllPath);
var pluginTypes = assembly.GetTypes()
.Where(t => typeof(ILabPlugin).IsAssignableFrom(t) && !t.IsInterface && !t.IsAbstract);
foreach (var pluginType in pluginTypes)
{
if (Activator.CreateInstance(pluginType) is ILabPlugin pluginInstance)
{
if (pluginInstance != null)
_labPlugins.Add((pluginInstance));
}
}
}
catch (Exception ex)
{
Console.WriteLine($"Failed to load assembly {dllPath}: {ex.Message}");
}
}
}
/// <summary>
/// 卸载
/// </summary>
public static void UnLoadDll(string pluginName)
{
var plugin = DllHelper._labPlugins.FirstOrDefault(p => p.Name == pluginName);
if (plugin != null)
{
DllHelper._labPlugins.Remove(plugin);
//物理删除文件
//FileAttributes attributes = System.IO.File.GetAttributes(filePath);
//if ((attributes & FileAttributes.ReadOnly) == FileAttributes.ReadOnly)
//{
// System.IO.File.SetAttributes(filePath, attributes & ~FileAttributes.ReadOnly);
//}
//System.IO.File.Delete(filePath);
}
}
/// <summary>
/// 执行插件方法
/// </summary>
/// <param name="pluginName">插件名称</param>
/// <param name="input">参数</param>
public static void ExecutePlugin(string pluginName,string input)
{
var plugin = DllHelper._labPlugins.FirstOrDefault(p => p.Name == pluginName);
if (plugin != null)
{
var result = plugin.Execute(input);
}
}
}
}
3,新建类库项目,引用主项目。然后继承并且实现定义的接口 ILabPlugin
4,生成或者发布类库项目,把生成的dll文件,放在主项目的Plugins。在主项目开启运行的时候调用reload方法加载dll。
5,然后可以在主程序中通过dllhelper帮助类进行使用插件的方法了
using LabPluginApi.interfaces;
using LabPluginApi.Models;
using LabPluginApi.Utils;
using Microsoft.AspNetCore.Components.Forms;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using NetTaste;
namespace LabPluginApi.Controllers
{
[Route("api/{DynamicParam}/[controller]")]
[ApiController]
public class ApiDllController : ControllerBase
{
private readonly string _dynamicParam;
private static ILabPlugin _pluginInstance;
public ApiDllController(IHttpContextAccessor httpContextAccessor)
{
_dynamicParam = httpContextAccessor.HttpContext.GetRouteValue("DynamicParam")?.ToString();
}
[HttpPost("Save")]
public string Save(DashboardConfigInputDto inputDto)
{
var instance = ApiDllHelper._labPlugins.FirstOrDefault(x => x.Name == _dynamicParam);
if (instance != null)
instance.Save(inputDto);
return string.Empty;
}
[Route("Query")]
[HttpGet]
public string Query([FromQuery] SearchDashboardConfigDto inputDto)
{
var instance = ApiDllHelper._labPlugins.FirstOrDefault(x => x.Name == _dynamicParam);
if (instance != null)
instance.Query(inputDto);
return string.Empty;
}
[Route("PostRequest")]
[HttpPost]
public string PostRequest([FromBody] object obj)
{
var instance = ApiDllHelper._labPlugins.FirstOrDefault(x => x.Name == _dynamicParam);
if (instance != null)
instance.Execute("function", obj);
return string.Empty;
}
[Route("GetRequest")]
[HttpPost]
public string GetRequest([FromQuery] string Id, string Name)
{
var instance = ApiDllHelper._labPlugins.FirstOrDefault(x => x.Name == _dynamicParam);
if (instance != null)
instance.Execute("function", new { Id, Name });
return string.Empty;
}
[Route("GetRequest1")]
[HttpPost]
public string GetRequest1([FromQuery] string Title)
{
var instance = ApiDllHelper._labPlugins.FirstOrDefault(x => x.Name == _dynamicParam);
if (instance != null)
instance.Execute("GetRequest1", new { Title });
return string.Empty;
}
}
}