T2FGame.Action 1.0.0

There is a newer version of this package available.
See the version list below for details.
dotnet add package T2FGame.Action --version 1.0.0
                    
NuGet\Install-Package T2FGame.Action -Version 1.0.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="T2FGame.Action" Version="1.0.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="T2FGame.Action" Version="1.0.0" />
                    
Directory.Packages.props
<PackageReference Include="T2FGame.Action" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add T2FGame.Action --version 1.0.0
                    
#r "nuget: T2FGame.Action, 1.0.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package T2FGame.Action@1.0.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=T2FGame.Action&version=1.0.0
                    
Install as a Cake Addin
#tool nuget:?package=T2FGame.Action&version=1.0.0
                    
Install as a Cake Tool

T2FGame.Action

T2FGame 框架的 Action 处理层,提供类似 ioGame BarSkeleton 的业务处理框架。

功能特性

  • Action 注解:声明式路由配置
  • Pipeline 处理链:可扩展的请求处理管道
  • 参数绑定:自动解析请求参数和上下文
  • 模块间调用:支持跨模块 Action 调用
  • Result → ResponseMessage 转换:函数式错误处理集成

安装

<PackageReference Include="T2FGame.Action" />

核心概念

Action 控制器

类似于 ioGame 的 ActionController,使用注解声明路由:

[ActionController(cmd: CmdModule.User)]
public class UserController
{
    private readonly IUserService _userService;

    public UserController(IUserService userService)
    {
        _userService = userService;
    }

    /// <summary>
    /// 用户登录
    /// </summary>
    [ActionMethod(subCmd: UserCmd.Login, Description = "用户登录")]
    public async Task<LoginResponse> Login(LoginRequest request, FlowContext context)
    {
        var result = await _userService.LoginAsync(request.Username, request.Password);

        // 设置认证状态
        context.SetAuthenticated(result.UserId);

        return new LoginResponse
        {
            UserId = result.UserId,
            Token = result.Token
        };
    }

    /// <summary>
    /// 获取用户信息(需要认证)
    /// </summary>
    [ActionMethod(subCmd: UserCmd.GetInfo, RequireAuth = true)]
    public async Task<UserInfo> GetUserInfo(FlowContext context)
    {
        var user = await _userService.GetByIdAsync(context.UserId);
        return user.ToProto();
    }
}

FlowContext(请求上下文)

public abstract class FlowContext
{
    // 基本信息
    public abstract string SessionId { get; }
    public abstract long UserId { get; }
    public abstract bool IsAuthenticated { get; }
    public abstract int CmdMerge { get; }
    public abstract int MessageId { get; }

    // 原始请求数据
    public abstract byte[]? RequestData { get; }

    // 认证管理
    public abstract bool SetAuthenticated(long userId);

    // 响应发送
    public abstract ValueTask SendAsync(IMessage response);
    public abstract ValueTask SendRawAsync(byte[] data);

    // 元数据
    public abstract string? GetMetadata(string key);
    public abstract void SetMetadata(string key, string value);
}

Pipeline 处理链

内置处理器

处理器 顺序 功能
ValidationHandler 100 参数验证
AuthenticationHandler 200 认证检查
CacheHandler 300 响应缓存
ActionInvokerHandler 500 执行 Action
ExceptionHandler 900 异常处理
LoggingHandler 950 日志记录
MetricsHandler 980 指标统计

自定义处理器

public class RateLimitHandler : IActionHandler
{
    public int Order => 150; // 在认证之前
    public string Name => "RateLimit";

    private readonly IRateLimiter _rateLimiter;

    public RateLimitHandler(IRateLimiter rateLimiter)
    {
        _rateLimiter = rateLimiter;
    }

    public async ValueTask<bool> HandleAsync(ActionPipelineContext context)
    {
        var key = $"rate:{context.FlowContext.SessionId}:{context.ActionInfo.CmdMerge}";

        if (!await _rateLimiter.TryAcquireAsync(key))
        {
            context.SetResponse(ResponseMessage.Failure(
                context.ActionInfo.CmdMerge,
                ErrorCodes.RateLimited,
                "请求过于频繁"));
            return false; // 中断管道
        }

        return true; // 继续执行
    }
}

注册处理器

services.AddSingleton<IActionHandler, RateLimitHandler>();

模块间调用

[ActionController(cmd: CmdModule.Battle)]
public class BattleController
{
    [ActionMethod(subCmd: BattleCmd.Start)]
    public async Task<BattleStartResponse> StartBattle(
        BattleStartRequest request,
        FlowContext context)
    {
        // 调用用户模块获取玩家信息
        var userInfo = await context.ModuleInvoker.InvokeAsync<UserInfo>(
            CmdKit.Merge(CmdModule.User, UserCmd.GetInfo),
            context.UserId);

        // 创建战斗
        var battle = await CreateBattle(userInfo, request);

        return new BattleStartResponse { BattleId = battle.Id };
    }
}

Result 模式集成

使用 ResultExtensions

[ActionMethod(subCmd: UserCmd.UpdateInfo)]
public async Task<ResponseMessage> UpdateUserInfo(
    UpdateUserRequest request,
    FlowContext context)
{
    // 业务层返回 Result<T>
    Result<UserInfo> result = await _userService.UpdateAsync(
        context.UserId,
        request.Nickname);

    // 转换为 ResponseMessage
    return result.ToResponseMessage(context.CmdMerge);
}

// 带转换函数
[ActionMethod(subCmd: UserCmd.GetProfile)]
public async Task<ResponseMessage> GetProfile(FlowContext context)
{
    Result<User> result = await _userService.GetByIdAsync(context.UserId);

    return result.ToResponseMessage(
        context.CmdMerge,
        user => user.ToProfileProto()); // 转换函数
}

Action 注册

自动扫描注册

// 扫描程序集注册所有 Action
services.AddActionMethodRegistry(options =>
{
    options.ScanAssemblies(typeof(UserController).Assembly);
});

// 或指定多个程序集
services.AddActionMethodRegistry(options =>
{
    options.ScanAssemblies(
        typeof(UserController).Assembly,
        typeof(BattleController).Assembly);
});

手动注册

var registry = new ActionMethodRegistry();
registry.RegisterController<UserController>();
registry.RegisterController<BattleController>();

异常处理

内置异常处理器

public class GameExceptionHandler : IExceptionHandler
{
    public int Order => 0;

    public bool CanHandle(Exception exception) => exception is GameException;

    public ResponseMessage Handle(Exception exception, ActionPipelineContext context)
    {
        var gameEx = (GameException)exception;
        return ResponseMessage.Failure(
            context.ActionInfo.CmdMerge,
            gameEx.ErrorCode,
            gameEx.Message);
    }
}

指标统计

// 获取 Action 统计信息
var metrics = serviceProvider.GetService<InMemoryActionMetrics>();
var stats = metrics.GetAllStats();

foreach (var (cmdMerge, stat) in stats)
{
    Console.WriteLine($"Command: {CmdKit.CmdToString(cmdMerge)}");
    Console.WriteLine($"  Requests: {stat.RequestCount}");
    Console.WriteLine($"  Errors: {stat.ErrorCount}");
    Console.WriteLine($"  Avg Response Time: {stat.AverageResponseTimeMs:F2}ms");
    Console.WriteLine($"  Max Response Time: {stat.MaxResponseTimeMs}ms");
}

目录结构

T2FGame.Action/
├── Attributes/
│   ├── ActionControllerAttribute.cs  # 控制器注解
│   └── ActionMethodAttribute.cs      # 方法注解
├── Context/
│   ├── FlowContext.cs               # 请求上下文基类
│   └── ResponseMessage.cs           # 响应消息
├── Extensions/
│   └── ResultExtensions.cs          # Result 转换扩展
├── Invoker/
│   ├── IModuleInvoker.cs            # 模块调用接口
│   └── ModuleInvoker.cs             # 模块调用实现
├── Pipeline/
│   ├── ActionPipeline.cs            # 处理管道
│   ├── ActionPipelineContext.cs     # 管道上下文
│   ├── IActionHandler.cs            # 处理器接口
│   ├── IExceptionHandler.cs         # 异常处理器接口
│   ├── ErrorCodes.cs                # 错误码定义
│   └── Handlers/
│       ├── ValidationHandler.cs
│       ├── AuthenticationHandler.cs
│       ├── ActionInvokerHandler.cs
│       ├── ExceptionHandler.cs
│       ├── LoggingHandler.cs
│       └── MetricsHandler.cs
└── Registry/
    ├── ActionMethodRegistry.cs      # Action 注册表
    └── ActionMethodInfo.cs          # Action 元信息
Product Compatible and additional computed target framework versions.
.NET net9.0 is compatible.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (5)

Showing the top 5 NuGet packages that depend on T2FGame.Action:

Package Downloads
T2FGame

T2FGame Framework - A high-performance distributed game server framework inspired by ioGame. This meta-package includes all T2FGame components.

T2FGame.Network.Socket

T2FGame Framework - High-performance Socket server based on SuperSocket (TCP/UDP/WebSocket)

T2FGame.Cluster.Orleans

A high-performance game server framework

T2FGame.Room

T2FGame Framework - Game room framework for multiplayer games, inspired by ioGame's RoomKit

T2FGame.Cache.Redis

T2FGame Framework - Redis distributed cache implementation for high-performance caching

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.0.9 524 12/11/2025
1.0.8 521 12/11/2025
1.0.7 513 12/11/2025
1.0.6 510 12/11/2025
1.0.5 514 12/10/2025
1.0.4 522 12/10/2025
1.0.3 532 12/9/2025
1.0.2 434 12/8/2025
1.0.1 566 12/1/2025
1.0.0 252 11/28/2025
0.0.1 438 12/8/2025