在 ASP.NET Core 里实现 插件式开发 + DLL 热加载,本质是:

  1. 把功能模块(插件)编译成独立的 .dll
  2. 运行时动态加载这些程序集(Assembly);
  3. 提供隔离、卸载、更新能力,避免内存泄露或锁文件。

🔑 核心要点

1. 插件目录

准备一个文件夹,例如:Plugins/,存放编译好的插件 DLL。

2. 插件接口约定

所有插件遵循一个接口或抽象基类,便于主程序调用:



public interface IPlugin
{
    string Name { get; }
    string Execute(string input);
}

插件示例(单独编译成 DLL):

public class HelloPlugin : IPlugin
{
    public string Name => "HelloPlugin";

    public string Execute(string input)
    {
        return $"Hello, {input}!";
    }
}


3. 动态加载插件

ASP.NET Core 中常见两种方式:

✅ AssemblyLoadContext(推荐)

支持卸载,适合“热加载”场景。

using System.Reflection;
using System.Runtime.Loader;

public class PluginLoadContext : AssemblyLoadContext
{
    private AssemblyDependencyResolver _resolver;

    public PluginLoadContext(string pluginPath) : base(isCollectible: true)
    {
        _resolver = new AssemblyDependencyResolver(pluginPath);
    }

    protected override Assembly Load(AssemblyName assemblyName)
    {
        string assemblyPath = _resolver.ResolveAssemblyToPath(assemblyName);
        if (assemblyPath != null)
        {
            return LoadFromAssemblyPath(assemblyPath);
        }
        return null;
    }
}

加载插件:

public class PluginManager
{
    private readonly List<IPlugin> _plugins = new();
    private PluginLoadContext _context;

    public void LoadPlugin(string pluginPath)
    {
        _context = new PluginLoadContext(pluginPath);
        var assembly = _context.LoadFromAssemblyPath(pluginPath);
        var types = assembly.GetTypes().Where(t => typeof(IPlugin).IsAssignableFrom(t) && !t.IsInterface);

        foreach (var type in types)
        {
            var plugin = (IPlugin)Activator.CreateInstance(type);
            _plugins.Add(plugin);
        }
    }

    public IEnumerable<IPlugin> GetPlugins() => _plugins;

    public void Unload()
    {
        _context.Unload();
        GC.Collect();
        GC.WaitForPendingFinalizers();
    }
}


4. ASP.NET Core 集成

可以做成一个 API 控制器,用于调用/热加载:

[ApiController]
[Route("api/plugins")]
public class PluginController : ControllerBase
{
    private readonly PluginManager _pluginManager;

    public PluginController(PluginManager pluginManager)
    {
        _pluginManager = pluginManager;
    }

    [HttpPost("load")]
    public IActionResult Load([FromBody] string path)
    {
        _pluginManager.LoadPlugin(path);
        return Ok("Plugin loaded.");
    }

    [HttpGet("exec")]
    public IActionResult Exec(string input)
    {
        var results = _pluginManager.GetPlugins().Select(p => p.Execute(input));
        return Ok(results);
    }

    [HttpPost("unload")]
    public IActionResult Unload()
    {
        _pluginManager.Unload();
        return Ok("Plugin unloaded.");
    }
}


⚠️ 注意事项

  1. 程序集锁定:.NET Framework 时代会锁 DLL,.NET Core 用 AssemblyLoadContext 解决。
  2. 依赖冲突:插件依赖的包最好和主程序隔离,可用独立目录。
  3. 安全性:加载外部 DLL 要小心执行恶意代码,可加签名校验。
  4. 性能优化:频繁加载卸载要考虑内存清理,调用 GC.Collect() 强制释放。

👉 总结:
在 ASP.NET Core 里做 DLL 热加载插件系统,推荐用 AssemblyLoadContext 实现插件隔离和卸载。核心就是 约定接口 + 插件目录 + 动态加载 + 管理器控制

要不要我帮你写一个 完整的 Demo 项目结构(包含主程序 + 插件工程 + 控制器接口),方便你直接跑?