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

C# SDK命令模式优化:规避请求执行方法直接调用的方案咨询

解决方案:泛型约束+内部接口隔离

针对你的问题,核心是要隔离命令的执行入口,同时让执行器能直接处理具体命令类型,避免冗余和类型转换。下面是一套贴合C#特性的实现方案:

核心思路

  1. 用内部可见性接口封装命令的执行逻辑,对外隐藏Execute方法,强制外部只能通过SDK统一入口调用。
  2. 用泛型约束让执行器直接绑定具体命令类型,无需类型转换或分支判断。
  3. 拆分公共属性与执行逻辑,既保证外部能正常设置命令参数,又能保护执行流程不被绕过。

代码实现

1. 定义隔离层接口与基类

// 仅SDK内部可见的命令执行接口,对外完全隐藏
internal interface IInternalCommand
{
    void Validate();
    void Execute();
}

// 对外暴露的命令基类,仅包含公共参数属性
public abstract class CommandBase
{
    // 示例公共参数:所有命令共享的请求ID
    public Guid RequestId { get; init; } = Guid.NewGuid();
}

2. 实现具体命令

每个命令继承公共基类并实现内部执行接口,外部无法直接访问Validate和Execute:

public class CreateUserCommand : CommandBase, IInternalCommand
{
    // 对外可见的业务参数
    public string Username { get; init; }
    public string Email { get; init; }

    // 仅SDK内部可调用的校验逻辑
    void IInternalCommand.Validate()
    {
        if (string.IsNullOrWhiteSpace(Username))
            throw new ArgumentException("用户名不能为空");
        if (!Email.Contains("@"))
            throw new ArgumentException("邮箱格式不合法");
    }

    // 仅SDK内部可调用的执行逻辑
    void IInternalCommand.Execute()
    {
        // 具体业务操作:比如写入数据库、调用服务等
        Console.WriteLine($"创建用户:{Username}(邮箱:{Email})");
    }
}

public class DeleteUserCommand : CommandBase, IInternalCommand
{
    public Guid UserId { get; init; }

    void IInternalCommand.Validate()
    {
        if (UserId == Guid.Empty)
            throw new ArgumentException("用户ID不能为空");
    }

    void IInternalCommand.Execute()
    {
        Console.WriteLine($"删除用户:{UserId}");
    }
}

3. 泛型命令执行器

通过泛型约束直接绑定具体命令类型,无需转换,逻辑清晰无冗余:

internal class CommandExecutor<TCommand> 
    where TCommand : CommandBase, IInternalCommand
{
    public void Run(TCommand command)
    {
        // 调用命令自身的校验
        (command as IInternalCommand).Validate();
        // 执行命令逻辑
        (command as IInternalCommand).Execute();
    }
}

4. SDK统一入口

对外暴露唯一执行入口,在这里做全局校验(比如权限、请求合法性),然后分发到对应执行器:

public static class SdkCommandRunner
{
    public static void Execute<TCommand>(TCommand command) 
        where TCommand : CommandBase, IInternalCommand
    {
        // 全局统一校验:比如请求ID合法性、SDK权限校验等
        if (command.RequestId == Guid.Empty)
            throw new InvalidOperationException("请求ID不能为空");

        // 直接用泛型执行器处理,无需分支或反射
        var executor = new CommandExecutor<TCommand>();
        executor.Run(command);
    }
}

外部调用示例

外部代码只能通过SDK入口执行命令,无法直接访问命令的Execute方法:

// 创建命令并设置参数
var createCmd = new CreateUserCommand
{
    Username = "zhangsan",
    Email = "zhangsan@example.com"
};

// 必须通过SDK入口执行,无法直接调用createCmd.Execute()
SdkCommandRunner.Execute(createCmd);

var deleteCmd = new DeleteUserCommand
{
    UserId = Guid.NewGuid()
};
SdkCommandRunner.Execute(deleteCmd);

方案优势

  • 彻底防止误用:Execute方法被内部接口隐藏,外部代码无法绕过SDK入口直接调用。
  • 无冗余/类型转换:泛型执行器直接绑定具体命令类型,全程不需要强制转换或分支判断。
  • 扩展性强:新增命令时只需继承CommandBase并实现IInternalCommand,无需修改现有执行器或入口代码。
  • 职责清晰:全局校验在入口处理,命令专属校验在命令内部实现,执行逻辑与参数分离。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 11:43:11