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

基于接口开发插件时如何调用对象内部实现且不暴露给插件

可行实现方案推荐

方案1:职责拆分(优先推荐)

这是最符合单一职责原则的实现方式,将用户操作逻辑从用户实体中剥离,统一放到用户管理器中,通过接口隔离区分公共访问能力和内部访问能力,完全消除类型转换需求。
实现逻辑:

  • 定义两套接口:公共接口对插件可见,仅包含插件需要的成员;内部接口对主程序集可见,继承公共接口,补充内部需要的操作方法。
  • 内部组件依赖内部接口,插件仅依赖公共接口。
    代码示例:
// 公共接口,对插件程序集可见
public interface IUserManager
{
    IReadOnlyCollection<IUser> Users { get; }
}

// 内部接口,仅主程序集可见
internal interface IUserManagerInternal : IUserManager
{
    void DeleteUser(IUser user);
    void DeleteAllUsers();
}

public interface IUser
{
    string Name { get; }
}

class UserImpl : IUser
{
    public string Name { get; }
    // 仅保留实体属性,操作逻辑移到管理器
}

class UserManager : IUserManagerInternal
{
    public IReadOnlyCollection<IUser> Users { get; }

    public void DeleteAllUsers()
    {
        foreach(var user in Users)
        {
            DeleteUser(user);
        }
    }

    public void DeleteUser(IUser user)
    {
        if (user is not UserImpl impl)
            throw new ArgumentException("无效用户实例", nameof(user));
        // 执行删除逻辑
    }
}

// 内部组件依赖内部接口
class NetworkController
{
    private readonly IUserManagerInternal _userManager;
    public void ReceiveDeleteMessage(string name)
    {
        var user = _userManager.Users.Single(x => x.Name == name);
        _userManager.DeleteUser(user); // 无需类型转换,直接调用
    }
}

// 插件仅依赖公共接口
class Plugin
{
    public Plugin(IUserManager userManager)
    {
        Console.WriteLine(userManager.Users.First().Name);
        // 完全接触不到删除相关能力
    }
}

该方案无类型转换开销,接口边界清晰,单元测试时直接mock对应接口即可,无需额外配置。

方案2:internal方法 + 单元测试可见配置

适合不想调整现有代码结构的小型项目,直接通过访问修饰符控制方法可见性:

  1. 将UserImpl的Delete方法访问修饰符从public改为internal
  2. 在主程序集的配置文件中添加[assembly: InternalsVisibleTo("你的单元测试项目名")],允许单元测试项目访问internal成员
    插件程序集未被授予internal访问权限,就算拿到UserImpl实例也无法调用Delete方法,主程序集内部可直接调用该方法。

方案3:internal内部接口 + 显式接口实现

如果你希望保留实体上的操作方法,可以对原有内部接口方案做优化,彻底避免接口泄露:

  1. 给IInternalUser添加internal修饰符,插件程序集完全看不到该接口类型
  2. 显式实现IInternalUser的Delete方法,仅当实例被转换为IInternalUser类型时才能访问该方法
    代码示例:
// 内部接口,仅主程序集可见
internal interface IInternalUser : IUser
{
    void Delete();
}

class UserImpl : IInternalUser
{
    public string Name { get; }
    // 显式实现接口
    void IInternalUser.Delete()
    {
        // 执行删除逻辑
    }
}

// 内部调用示例
if(user is IInternalUser internalUser)
{
    internalUser.Delete();
}

该方案下插件完全没有途径访问到Delete方法,类型转换仅存在于主程序集内部,可控性高。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 17:36:02