You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让plugin.dll调用core-application功能?插件架构交互技术问询

嘿,这在插件架构里属于典型的宿主-插件反向调用问题——插件需要调用宿主(你的core-application)已有的服务对吧?我给你分享几个在.NET环境下最实用的解决方案,从低耦合到快速实现都有:

方案1:定义共享抽象接口(最推荐,符合设计原则)

这是插件架构的标准做法,核心是用依赖倒置原则解耦插件和宿主:

  1. 先创建一个独立的共享类库(比如命名为 Core.Abstractions),里面只放宿主需要暴露给插件的抽象接口,比如你的Logging功能:
// Core.Abstractions 类库中的代码
public interface ILogger
{
    void Log(string message);
}
  1. 在你的core-application中,让已有的Logging实现类继承这个接口:
// core-application 中的代码
public class StandardLogger : ILogger
{
    // 这里就是你已经配置好的Logging逻辑,比如写入standard-log.txt
    public void Log(string message)
    {
        File.AppendAllText("standard-log.txt", $"{DateTime.Now:yyyy-MM-dd HH:mm:ss} - {message}{Environment.NewLine}");
    }
}
  1. 插件(plugin1.dll)只需要引用这个Core.Abstractions类库,不需要直接引用core-application。然后在插件的入口类中,通过构造函数或方法参数接收ILogger实例:
// plugin1.dll 中的代码
public class TimeViewerPlugin
{
    private readonly ILogger _hostLogger;

    // 通过构造函数注入宿主提供的Logger
    public TimeViewerPlugin(ILogger hostLogger)
    {
        _hostLogger = hostLogger;
    }

    public void ShowAndLogCurrentTime()
    {
        var currentTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
        Console.WriteLine($"当前时间:{currentTime}");
        // 直接调用宿主的Logging功能
        _hostLogger.Log($"用户查看时间:{currentTime}");
    }
}
  1. 最后在core-application加载插件时,把自己的StandardLogger实例传递给插件:
// core-application 中加载插件的代码
var pluginAssembly = Assembly.LoadFrom(@"modules\plugin1.dll");
var pluginType = pluginAssembly.GetType("TimeViewerPlugin");

// 传入宿主已配置好的Logger实例
var loggerInstance = new StandardLogger();
var pluginInstance = Activator.CreateInstance(pluginType, loggerInstance);

// 调用插件的功能方法
var showTimeMethod = pluginType.GetMethod("ShowAndLogCurrentTime");
showTimeMethod.Invoke(pluginInstance, null);

这个方案的优势是完全解耦,插件只依赖抽象,后续宿主升级只要接口不变,插件就不用改动,扩展性极强。

方案2:静态服务入口(快速实现,适合小型项目)

如果不想额外创建共享类库,可以在core-application中暴露一个静态的服务入口,但这种方式耦合度较高,适合快速验证:

  1. 在core-application中定义一个静态类,暴露已配置好的Logger实例:
// core-application 中的代码
public static class CoreServiceLocator
{
    // 初始化时把已配置好的Logger赋值进来
    public static ILogger Logger { get; set; }
}

// 程序启动时初始化
CoreServiceLocator.Logger = new StandardLogger();
  1. 插件直接引用core-application的程序集,然后调用静态属性:
// plugin1.dll 中的代码
public void ShowAndLogCurrentTime()
{
    var currentTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
    Console.WriteLine($"当前时间:{currentTime}");
    CoreServiceLocator.Logger.Log($"用户查看时间:{currentTime}");
}

这种方式简单直接,但插件和宿主强耦合,宿主升级时可能会影响插件,适合小项目或快速原型开发。

方案3:事件通知机制(适合单向通知场景)

如果插件不需要直接调用宿主方法,只是需要触发宿主执行某个操作,可以用事件机制:

  1. 插件中定义一个事件,当需要记录时间时触发:
// plugin1.dll 中的代码
public class TimeViewerPlugin
{
    // 定义事件,传递需要记录的时间字符串
    public event Action<string> OnTimeNeedToLog;

    public void ShowCurrentTime()
    {
        var currentTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
        Console.WriteLine($"当前时间:{currentTime}");
        // 触发事件,通知宿主记录
        OnTimeNeedToLog?.Invoke(currentTime);
    }
}
  1. core-application加载插件时,订阅这个事件,用自己的Logger处理:
// core-application 中加载插件的代码
var pluginAssembly = Assembly.LoadFrom(@"modules\plugin1.dll");
var pluginType = pluginAssembly.GetType("TimeViewerPlugin");
var pluginInstance = Activator.CreateInstance(pluginType);

// 订阅插件的事件,用宿主的Logger处理
var eventInfo = pluginType.GetEvent("OnTimeNeedToLog");
eventInfo.AddEventHandler(pluginInstance, new Action<string>(time => 
{
    var logger = new StandardLogger();
    logger.Log($"用户查看时间:{time}");
}));

// 调用插件方法
var showTimeMethod = pluginType.GetMethod("ShowCurrentTime");
showTimeMethod.Invoke(pluginInstance, null);

这种方式插件完全不知道宿主的Logger存在,只负责触发事件,宿主自己处理逻辑,解耦程度也很高,但只适合单向通知的场景。


内容的提问来源于stack exchange,提问作者Zesa Rex

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 09:17:55