c# 插件热插拔的方式动态加载dll文件

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;
        }
    }
}

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

从前是晴天

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值