命令和命令过滤器

    SuperSocket 中的命令设计出来是为了处理来自客户端的请求的, 它在业务逻辑处理之中起到了很重要的作用。

    命令类必须实现下面的基本命令接口, 根据你的需要选择实现同步命令或异步命令:

    请求包的处理代码应被放置于方法 “Execute” 或 “ExecuteAsync”之内。 每个命令都有自己的包含Name和Key的元数据。

    Name: 人们可以直接理解的名字; Key: 用于匹配接收到的包的Key的对象;

    我们可以通过给Command增加Attribute来定义它的元数据 (Name=’ShowVoltage’, Key=0x03):

    1. public class ShowVoltage : IAsyncCommand<StringPackageInfo>
    2. {
    3. public async ValueTask ExecuteAsync(IAppSession session, StringPackageInfo package)
    4. {
    5. ...
    6. }
    7. }

    请求处理代码必须被放置于方法 “Execute” or “ExecuteAsync” 之中,并且属性 “Keys” 的值用于匹配接收到请求实例(packageInfo)的Key。当一个请求实例(packageInfo) 被收到时,SuperSocket 将会通过匹配请求实例(package)的Key和命令的Keys的方法来查找用于处理该请求的命令。

    元数据中的Key的值是用于匹配接收到的包请求的。当一个包被接收到,SuperSocket会去通过包的Key去寻找拥有相同Key的命令,找到的命令将会用于处理这个包。

    但是,有个前提条件是包的类型必须实现接口 IKeyedPackageInfo (TKey 可以是任意元数据类型如 int,string,short 或 byte), 例如 StringPackageInfo:

    1. public class StringPackageInfo : IKeyedPackageInfo<string>

    举个例子, 如果你收到如下请求(package):

    1. Key: "ADD"
    2. Body: "1 2"

    于是 SuperSocket 将会寻找Key属性为”ADD”的命令。如果有个命令定义如下:

    如果你注册了此命令,SuperSocket就会找到该命令。

    1. hostBuilder.UseCommand((commandOptions) =>
    2. {
    3. // 一个一个的注册命令
    4. commandOptions.AddCommand<ADD>();
    5. //commandOptions.AddCommand<MULT>();
    6. //commandOptions.AddCommand<SUB>();
    7. // 注册程序集重的所有命令
    8. //commandOptions.AddCommandAssembly(typeof(SUB).GetTypeInfo().Assembly);
    9. }

    SuperSocket中的命令过滤器的作用类似于ASP.NET MVC中的Action Filter。 你可以用它来拦截命令的执行。命令过滤器被在命令运行的前后被调用。

    1. public class HelloCommandFilterAttribute : CommandFilterAttribute
    2. {
    3. public override void OnCommandExecuted(CommandExecutingContext commandContext)
    4. Console.WriteLine("Hello");
    5. }
    6. {
    7. Console.WriteLine("Bye bye");
    8. return true;
    9. }
    10. }

    异步命令过滤器:

    1. public class AsyncHelloCommandFilterAttribute : AsyncCommandFilterAttribute
    2. {
    3. public override async ValueTask OnCommandExecutedAsync(CommandExecutingContext commandContext)
    4. {
    5. Console.WriteLine("Hello");
    6. await Task.Delay(0);
    7. }
    8. public override async ValueTask<bool> OnCommandExecutingAsync(CommandExecutingContext commandContext)
    9. {
    10. Console.WriteLine("Bye bye");
    11. await Task.Delay(0);
    12. return true;
    13. }
    14. }

    在命令上应用命令过滤器:

    全局命令过滤器就是被应用在所有命令之上的命令过滤器。

    注册全局命令过滤器:

    1. hostBuilder.UseCommand((commandOptions) =>
    2. {
    3. commandOptions.AddCommand<COUNT>();
    4. commandOptions.AddCommand<COUNTDOWN>();
    5. commandOptions.AddGlobalCommandFilter<HitCountCommandFilterAttribute>();

    你可以吧命令程序集添加到配置文件的节点 “commands/assemblies” 下。与此同时,请确保此命令程序集被复制到的程序的运行目录。

    这是配置文件示例:

    1. {
    2. "serverOptions": {
    3. "name": "GameMsgServer",
    4. "listeners": [
    5. {
    6. "ip": "Any",
    7. "port": "2020"
    8. },
    9. {
    10. "ip": "192.168.3.1",
    11. "port": "2020"
    12. }
    13. ],
    14. "commands": {
    15. "assemblies": [
    16. {
    17. "name": "CommandAssemblyName"
    18. }
    19. ]
    20. }
    21. }
    22. }

    runtimeconfig.json

    1. {
    2. "runtimeOptions": {
    3. "Microsoft.NETCore.DotNetHostPolicy.SetAppPaths" : true
    4. }
    5. }