Skip to content

Extensions 包使用说明

概述

Extensions 包提供了一系列扩展方法,简化了框架各个接口的使用。通过扩展方法,可以用更简洁的语法访问框架功能,提高代码可读性和开发效率。

扩展方法类别

1. ContextAware 扩展 (ContextAwareExtensions.cs)

为 IContextAware 提供扩展方法,允许直接从实现了 IContextAware 的对象获取架构组件。

GetSystem 扩展方法

csharp
public static TSystem? GetSystem<TSystem>(this IContextAware contextAware) 
    where TSystem : class, ISystem

使用示例:

csharp
// 在实现了 IContextAware 的类中使用
public class PlayerController : IController
{
    public void UpdateUI()
    {
        // 直接通过 this 调用
        var playerSystem = this.GetSystem<PlayerSystem>();
        var inventorySystem = this.GetSystem<InventorySystem>();
    }
}

GetModel 扩展方法

csharp
public static TModel? GetModel<TModel>(this IContextAware contextAware) 
    where TModel : class, IModel

使用示例:

csharp
public class PlayerController : IController
{
    public void UpdateStats()
    {
        // 获取模型
        var playerModel = this.GetModel<PlayerModel>();
        var inventoryModel = this.GetModel<InventoryModel>();
        
        // 使用模型数据
        playerModel.Health += 10;
    }
}

GetUtility 扩展方法

csharp
public static TUtility? GetUtility<TUtility>(this IContextAware contextAware) 
    where TUtility : class, IUtility

使用示例:

csharp
public class GameModel : AbstractModel, IContextAware
{
    protected override void OnInit()
    {
        // 获取工具
        var timeUtility = this.GetUtility<TimeUtility>();
        var storageUtility = this.GetUtility<StorageUtility>();
    }
}

SendCommand 扩展方法

// 发送无返回值的命令
public static void SendCommand(this IContextAware contextAware, ICommand command)

// 发送带返回值的命令
public static TResult SendCommand<TResult>(this IContextAware contextAware, ICommand<TResult> command)

使用示例:

public class GameController : IController
{
    public void OnStartButtonClicked()
    {
        // 发送命令实例
        this.SendCommand(new StartGameCommand());
        
        // 发送带返回值的命令
        var result = this.SendCommand(new CalculateScoreCommand());
    }
}

SendQuery 扩展方法

public static TResult SendQuery<TResult>(this IContextAware contextAware, IQuery<TResult> query)

使用示例:

public class InventoryController : IController
{
    public void ShowInventory()
    {
        // 发送查询获取数据
        var items = this.SendQuery(new GetInventoryItemsQuery());
        var gold = this.SendQuery(new GetPlayerGoldQuery());
        
        UpdateInventoryUI(items, gold);
    }
}

SendEvent 扩展方法

// 发送无参事件
public static void SendEvent<T>(this IContextAware contextAware) where T : new()

// 发送事件实例
public static void SendEvent<T>(this IContextAware contextAware, T e) where T : class

使用示例:

public class PlayerModel : AbstractModel, IContextAware
{
    public void TakeDamage(int damage)
    {
        Health -= damage;
        
        if (Health <= 0)
        {
            // 方式1:发送无参事件
            this.SendEvent<PlayerDiedEvent>();
            
            // 方式2:发送带数据的事件
            this.SendEvent(new PlayerDiedEvent 
            { 
                Position = Position,
                Cause = "Damage" 
            });
        }
    }
}

RegisterEvent 扩展方法

public static IUnRegister RegisterEvent<TEvent>(this IContextAware contextAware, Action<TEvent> handler)

使用示例:

public class GameController : IController
{
    private IUnRegisterList _unregisterList = new UnRegisterList();
    
    public void Initialize()
    {
        // 注册事件监听
        this.RegisterEvent<GameStartedEvent>(OnGameStarted)
            .AddToUnregisterList(_unregisterList);
            
        this.RegisterEvent<PlayerLevelUpEvent>(OnPlayerLevelUp)
            .AddToUnregisterList(_unregisterList);
    }
    
    private void OnGameStarted(GameStartedEvent e) { }
    private void OnPlayerLevelUp(PlayerLevelUpEvent e) { }
}

UnRegisterEvent 扩展方法

public static void UnRegisterEvent<TEvent>(this IContextAware contextAware, Action<TEvent> onEvent)

GetEnvironment 扩展方法

public static T? GetEnvironment<T>(this IContextAware contextAware) where T : class
public static IEnvironment GetEnvironment(this IContextAware contextAware)

2. Object 扩展 (ObjectExtensions.cs)

提供基于运行时类型判断的对象扩展方法,用于简化类型分支、链式调用和架构分派逻辑。

IfType 扩展方法

// 最简单的类型判断
public static bool IfType<T>(this object obj, Action<T> action)

// 带条件的类型判断
public static bool IfType<T>(
    this object obj, 
    Func<T, bool> predicate, 
    Action<T> action
)

// 条件判断,带不匹配时的处理
public static void IfType<T>(
    this object obj, 
    Action<T> whenMatch, 
    Action<object>? whenNotMatch = null
)

使用示例:

object obj = new MyRule();

// 简单类型判断
bool executed = obj.IfType<MyRule>(rule =>
{
    rule.Initialize();
});

// 带条件的类型判断
obj.IfType<MyRule>(
    r => r.Enabled,      // 条件
    r => r.Execute()     // 执行动作
);

// 带不匹配处理的类型判断
obj.IfType<IRule>(
    rule => rule.Execute(),
    other => Logger.Warn($"Unsupported type: {other.GetType()}")
);

IfType<T, TResult> 扩展方法

public static TResult? IfType<T, TResult>(
    this object obj,
    Func<T, TResult> func
)

使用示例:

object obj = new MyRule { Name = "TestRule" };

string? name = obj.IfType<MyRule, string>(r => r.Name);

As 和 Do 扩展方法

// 安全类型转换
public static T? As<T>(this object obj) where T : class

// 流式调用
public static T Do<T>(this T obj, Action<T> action)

使用示例:

// 安全类型转换
obj.As<MyRule>()
   ?.Execute();

// 流式调用
obj.As<MyRule>()
   ?.Do(r => r.Initialize())
   ?.Do(r => r.Execute());

// 组合使用
obj.As<MyRule>()
   ?.Do(rule => 
   {
       if (rule.Enabled)
           rule.Execute();
   });

SwitchType 扩展方法

public static void SwitchType(
    this object obj,
    params (Type type, Action<object> action)[] handlers
)

使用示例:

obj.SwitchType(
    (typeof(IRule), o => HandleRule((IRule)o)),
    (typeof(ISystem), o => HandleSystem((ISystem)o)),
    (typeof(IModel), o => HandleModel((IModel)o))
);

3. OrEvent 扩展 (OrEventExtensions.cs)

IEvent 提供事件组合功能。

OrEventExtensions

public static OrEvent Or(this IEvent self, IEvent e)

使用示例:

// 组合多个事件:当任意一个触发时执行
var onAnyInput = onKeyPressed.Or(onMouseClicked).Or(onTouchDetected);

onAnyInput.Register(() => 
{
    GD.Print("Any input detected!");
});

// 链式组合
var onAnyDamage = onPhysicalDamage
    .Or(onMagicDamage)
    .Or(onPoisonDamage);

4. UnRegisterList 扩展 (UnRegisterListExtension.cs)

IUnRegisterIUnRegisterList 提供批量管理功能。

UnRegisterListExtension

// 添加到注销列表
public static void AddToUnregisterList(this IUnRegister self, 
    IUnRegisterList unRegisterList)

// 批量注销
public static void UnRegisterAll(this IUnRegisterList self)

使用示例:

public class ComplexController : IController
{
    private IUnRegisterList _unregisterList = new UnRegisterList();
    
    public void Initialize()
    {
        // 所有注册都添加到列表中
        this.RegisterEvent<Event1>(OnEvent1)
            .AddToUnregisterList(_unregisterList);
            
        this.RegisterEvent<Event2>(OnEvent2)
            .AddToUnregisterList(_unregisterList);
            
        this.GetModel<Model1>().Property1.Register(OnProperty1Changed)
            .AddToUnregisterList(_unregisterList);
            
        this.GetModel<Model2>().Property2.Register(OnProperty2Changed)
            .AddToUnregisterList(_unregisterList);
    }
    
    public void Cleanup()
    {
        // 一次性注销所有
        _unregisterList.UnRegisterAll();
    }
}

完整使用示例

Controller 示例

public partial class GameplayController : IController
{
    private IUnRegisterList _unregisterList = new UnRegisterList();
    
    public void Initialize()
    {
        // 使用扩展方法获取 Model
        var playerModel = this.GetModel<PlayerModel>();
        var gameModel = this.GetModel<GameModel>();
        
        // 使用扩展方法注册事件
        this.RegisterEvent<GameStartedEvent>(OnGameStarted)
            .AddToUnregisterList(_unregisterList);
        
        // 监听可绑定属性
        playerModel.Health.Register(OnHealthChanged)
            .AddToUnregisterList(_unregisterList);
    }
    
    public void Process(double delta)
    {
        // 发送命令
        this.SendCommand(new AttackCommand(targetId: 1));
        
        // 发送查询
        var hasPotion = this.SendQuery(new HasItemQuery("health_potion"));
        if (hasPotion)
        {
            this.SendCommand<UseHealthPotionCommand>();
        }
    }
    
    private void OnGameStarted(GameStartedEvent e)
    {
        Console.WriteLine("Game started!");
    }
    
    private void OnHealthChanged(int health)
    {
        UpdateHealthBar(health);
    }
    
    public void Cleanup()
    {
        _unregisterList.UnRegisterAll();
    }
}

Command 示例

public class ComplexGameCommand : AbstractCommand
{
    protected override void OnExecute()
    {
        // 获取多个组件
        var playerModel = this.GetModel<PlayerModel>();
        var gameSystem = this.GetSystem<GameSystem>();
        var timeUtility = this.GetUtility<TimeUtility>();
        
        // 执行业务逻辑
        var currentTime = timeUtility.GetCurrentTime();
        gameSystem.ProcessGameLogic(playerModel, currentTime);
        
        // 发送事件通知
        this.SendEvent(new GameStateChangedEvent());
        
        // 可以发送其他命令(谨慎使用)
        this.SendCommand<SaveGameCommand>();
    }
}

System 示例

public class AchievementSystem : AbstractSystem
{
    protected override void OnInit()
    {
        // 注册事件监听
        this.RegisterEvent<EnemyKilledEvent>(OnEnemyKilled);
        this.RegisterEvent<LevelCompletedEvent>(OnLevelCompleted);
    }
    
    private void OnEnemyKilled(EnemyKilledEvent e)
    {
        // 获取模型
        var playerModel = this.GetModel<PlayerModel>();
        playerModel.EnemyKillCount++;
        
        // 检查成就
        if (playerModel.EnemyKillCount >= 100)
        {
            // 发送成就解锁事件
            this.SendEvent(new AchievementUnlockedEvent 
            { 
                AchievementId = "kill_100_enemies" 
            });
        }
    }
    
    private void OnLevelCompleted(LevelCompletedEvent e)
    {
        // 发送查询
        var completionTime = this.SendQuery(new GetLevelTimeQuery(e.LevelId));
        
        if (completionTime < 60)
        {
            this.SendEvent(new AchievementUnlockedEvent 
            { 
                AchievementId = "speed_runner" 
            });
        }
    }
}

扩展方法的优势

  1. 简洁的语法 :不需要显式调用 GetContext()
  2. 类型安全:编译时检查类型
  3. 可读性高:代码意图更清晰
  4. 智能提示:IDE 可以提供完整的自动补全
  5. 链式调用:支持流式编程风格

注意事项

  1. 确保引用命名空间:

    csharp
    using GFramework.Core.extensions;
  2. 理解扩展方法本质:

    • 扩展方法是静态方法的语法糖
    • 不会改变原始类型的结构
    • 仅在编译时解析
  3. 性能考虑:

    • 扩展方法本身无性能开销
    • 实际调用的是底层方法

相关包

基于 Apache 2.0 许可证发布