# Priority 生成器

> 自动实现 IPrioritized 接口，为类添加优先级标记

Priority 生成器通过源代码生成器自动实现 `IPrioritized` 接口，简化优先级标记和排序逻辑的实现。

## 概述

### 核心功能

- **自动实现接口**：自动实现 `IPrioritized` 接口的 `Priority` 属性
- **优先级标记**：通过特性参数指定优先级值
- **编译时生成**：在编译时生成代码，零运行时开销
- **类型安全**：编译时类型检查，避免运行时错误

### 适用场景

- 系统初始化顺序控制
- 事件处理器优先级排序
- 服务注册顺序管理
- 需要按优先级排序的任何场景

## 基础使用

### 标记优先级

使用 `[Priority]` 特性为类标记优先级：

```csharp
using GFramework.Core.SourceGenerators.Abstractions.Bases;

[Priority(10)]
public partial class MySystem
{
    // 自动生成 IPrioritized 接口实现
}
```

### 生成代码

编译器会自动生成如下代码：

```csharp
// <auto-generated/>
#nullable enable

namespace YourNamespace;

partial class MySystem : global::GFramework.Core.Abstractions.Bases.IPrioritized
{
    /// <summary>
    /// 获取优先级值: 10
    /// </summary>
    public int Priority => 10;
}
```

### 使用生成的优先级

生成的 `Priority` 属性可用于排序：

```csharp
using GFramework.Core.Abstractions.Bases;

// 获取所有实现了 IPrioritized 的系统
var systems = new List<IPrioritized> { system1, system2, system3 };

// 按优先级排序（值越小，优先级越高）
var sorted = systems.OrderBy(s => s.Priority).ToList();

// 依次初始化
foreach (var system in sorted)
{
    system.Initialize();
}
```

## 优先级值语义

### 值的含义

| 优先级值范围 | 含义    | 使用场景             |
|--------|-------|------------------|
| 负数     | 高优先级  | 核心系统、关键事件处理器     |
| 0      | 默认优先级 | 普通系统、一般事件处理器     |
| 正数     | 低优先级  | 可延迟初始化的系统、非关键处理器 |

### PriorityGroup 常量

推荐使用 `PriorityGroup` 预定义常量来标记优先级：

```csharp
using GFramework.Core.Abstractions.Bases;
using GFramework.Core.SourceGenerators.Abstractions.Bases;

[Priority(PriorityGroup.Critical)]  // -100
public partial class InputSystem : AbstractSystem { }

[Priority(PriorityGroup.High)]      // -50
public partial class PhysicsSystem : AbstractSystem { }

[Priority(PriorityGroup.Normal)]    // 0
public partial class GameplaySystem : AbstractSystem { }

[Priority(PriorityGroup.Low)]       // 50
public partial class AudioSystem : AbstractSystem { }

[Priority(PriorityGroup.Deferred)]  // 100
public partial class CleanupSystem : AbstractSystem { }
```

**PriorityGroup 常量定义**：

```csharp
namespace GFramework.Core.Abstractions.Bases;

public static class PriorityGroup
{
    public const int Critical = -100;   // 关键：输入、网络等
    public const int High = -50;        // 高：物理、碰撞等
    public const int Normal = 0;        // 正常：游戏逻辑等
    public const int Low = 50;          // 低：音频、特效等
    public const int Deferred = 100;    // 延迟：清理、统计等
}
```

## 使用场景

### 系统初始化顺序

控制系统初始化的顺序，确保依赖关系正确：

```csharp
using GFramework.Core.Abstractions.Systems;
using GFramework.Core.SourceGenerators.Abstractions.Bases;
using GFramework.Core.Abstractions.Bases;

// 输入系统最先初始化
[Priority(PriorityGroup.Critical)]
public partial class InputSystem : AbstractSystem
{
    protected override void OnInit()
    {
        // 初始化输入处理
    }
}

// 物理系统次之
[Priority(PriorityGroup.High)]
public partial class PhysicsSystem : AbstractSystem
{
    protected override void OnInit()
    {
        // 初始化物理引擎
    }
}

// 游戏逻辑系统在中间
[Priority(PriorityGroup.Normal)]
public partial class GameplaySystem : AbstractSystem
{
    protected override void OnInit()
    {
        // 初始化游戏逻辑
    }
}

// 音频系统可以稍后
[Priority(PriorityGroup.Low)]
public partial class AudioSystem : AbstractSystem
{
    protected override void OnInit()
    {
        // 初始化音频引擎
    }
}
```

在架构中按优先级初始化：

```csharp
public class GameArchitecture : Architecture
{
    protected override void InitSystems()
    {
        // 获取所有系统并按优先级排序
        var systems = this.GetAllByPriority<ISystem>();

        foreach (var system in systems)
        {
            system.Init();
        }
    }
}
```

### 事件处理器优先级

控制事件处理器的执行顺序：

```csharp
using GFramework.Core.Abstractions.Events;

// 关键事件处理器最先执行
[Priority(PriorityGroup.Critical)]
public partial class CriticalEventHandler : IEventHandler<CriticalEvent>
{
    public void Handle(CriticalEvent e)
    {
        // 处理关键事件
    }
}

// 普通处理器在中间执行
[Priority(PriorityGroup.Normal)]
public partial class NormalEventHandler : IEventHandler<CriticalEvent>
{
    public void Handle(CriticalEvent e)
    {
        // 处理普通逻辑
    }
}

// 日志记录器最后执行
[Priority(PriorityGroup.Deferred)]
public partial class EventLogger : IEventHandler<CriticalEvent>
{
    public void Handle(CriticalEvent e)
    {
        // 记录日志
    }
}
```

事件总线按优先级调用处理器：

```csharp
public class EventBus : IEventBus
{
    public void Send<TEvent>(TEvent e) where TEvent : IEvent
    {
        // 获取所有处理器并按优先级排序
        var handlers = this.GetAllByPriority<IEventHandler<TEvent>>();

        foreach (var handler in handlers)
        {
            handler.Handle(e);
        }
    }
}
```

### 服务排序

控制多个服务实现的优先级：

```csharp
// 高优先级服务
[Priority(PriorityGroup.High)]
public partial class PremiumService : IService
{
    public void Execute()
    {
        // 优先执行
    }
}

// 默认服务
[Priority(PriorityGroup.Normal)]
public partial class DefaultService : IService
{
    public void Execute()
    {
        // 默认执行
    }
}

// 后备服务
[Priority(PriorityGroup.Low)]
public partial class FallbackService : IService
{
    public void Execute()
    {
        // 最后备选
    }
}
```

## 与 PriorityUsageAnalyzer 集成

### GF_Priority_Usage_001 诊断

`PriorityUsageAnalyzer` 分析器会检测应该使用 `GetAllByPriority<T>()` 而非 `GetAll<T>()` 的场景：

**错误示例**：

```csharp
// ❌ 不推荐：可能未按优先级排序
var systems = context.GetAll<ISystem>();
```

**正确示例**：

```csharp
// ✅ 推荐：确保按优先级排序
var systems = context.GetAllByPriority<ISystem>();
```

### 分析器规则

当满足以下条件时，分析器会报告 `GF_Priority_Usage_001` 诊断：

1. 类型实现了 `IPrioritized` 接口
2. 使用了 `GetAll<T>()` 方法
3. 建议改用 `GetAllByPriority<T>()` 方法

## 诊断信息

### GF_Priority_001 - 只能应用于类

**错误信息**：`Priority attribute can only be applied to classes`

**场景**：将 `[Priority]` 特性应用于非类类型

```csharp
[Priority(10)]
public interface IMyInterface  // ❌ 错误
{
}

[Priority(10)]
public struct MyStruct  // ❌ 错误
{
}
```

**解决方案**：只在类上使用 `[Priority]` 特性

```csharp
[Priority(10)]
public partial class MyClass  // ✅ 正确
{
}
```

### GF_Priority_002 - 已实现 IPrioritized 接口

**错误信息**：`Type '{ClassName}' already implements IPrioritized interface`

**场景**：类已手动实现 `IPrioritized` 接口

```csharp
[Priority(10)]
public partial class MySystem : IPrioritized  // ❌ 冲突
{
    public int Priority => 10;  // 手动实现
}
```

**解决方案**：移除 `[Priority]` 特性或移除手动实现

```csharp
// 方案1：移除特性，使用手动实现
public partial class MySystem : IPrioritized
{
    public int Priority => 10;
}

// 方案2：移除手动实现，使用生成器
[Priority(10)]
public partial class MySystem
{
    // 生成器自动实现
}
```

### GF_Priority_003 - 必须声明为 partial

**错误信息**：`Class '{ClassName}' must be declared as partial`

**场景**：类未声明为 `partial`

```csharp
[Priority(10)]
public class MySystem  // ❌ 缺少 partial
{
}
```

**解决方案**：添加 `partial` 关键字

```csharp
[Priority(10)]
public partial class MySystem  // ✅ 正确
{
}
```

### GF_Priority_004 - 优先级值无效

**错误信息**：`Priority value is invalid`

**场景**：特性参数无效或未提供

```csharp
[Priority]  // ❌ 缺少参数
public partial class MySystem
{
}
```

**解决方案**：提供有效的优先级值

```csharp
[Priority(10)]  // ✅ 正确
public partial class MySystem
{
}
```

### GF_Priority_005 - 不支持嵌套类

**错误信息**：`Nested class '{ClassName}' is not supported`

**场景**：在嵌套类中使用 `[Priority]` 特性

```csharp
public partial class OuterClass
{
    [Priority(10)]
    public partial class InnerClass  // ❌ 错误
    {
    }
}
```

**解决方案**：将嵌套类提取为独立的类

```csharp
[Priority(10)]
public partial class InnerClass  // ✅ 正确
{
}
```

## 最佳实践

### 1. 使用 PriorityGroup 常量

避免使用魔法数字，优先使用预定义常量：

```csharp
// ✅ 推荐：使用常量
[Priority(PriorityGroup.Critical)]
public partial class InputSystem { }

// ❌ 不推荐：魔法数字
[Priority(-100)]
public partial class InputSystem { }
```

### 2. 预留优先级间隔

为未来扩展预留间隔：

```csharp
public static class SystemPriority
{
    public const int Input = -100;
    public const int PrePhysics = -90;   // 预留扩展
    public const int Physics = -80;
    public const int PostPhysics = -70;  // 预留扩展
    public const int Gameplay = 0;
    public const int PostGameplay = 10;  // 预留扩展
    public const int Audio = 50;
    public const int Cleanup = 100;
}
```

### 3. 文档化优先级语义

为自定义优先级值添加注释：

```csharp
/// <summary>
/// 输入系统，优先级 -100，需要最先初始化以接收输入事件
/// </summary>
[Priority(PriorityGroup.Critical)]
public partial class InputSystem : AbstractSystem
{
}
```

### 4. 避免优先级冲突

当多个类有相同优先级时，执行顺序不确定。应避免依赖特定顺序：

```csharp
// ❌ 不推荐：相同优先级，顺序不确定
[Priority(0)]
public partial class SystemA { }

[Priority(0)]
public partial class SystemB { }

// ✅ 推荐：明确区分优先级
[Priority(-10)]
public partial class SystemA { }

[Priority(0)]
public partial class SystemB { }
```

### 5. 只在真正需要排序的场景使用

不要滥用优先级特性，只在确实需要排序的场景使用：

```csharp
// ✅ 推荐：需要排序的系统
[Priority(PriorityGroup.Critical)]
public partial class InputSystem : AbstractSystem { }

// ❌ 不推荐：不需要排序的工具类
[Priority(10)]
public static partial class MathHelper  // 静态工具类无需优先级
{
    public static int Add(int a, int b) => a + b;
}
```

## 高级场景

### 泛型类支持

Priority 特性支持泛型类：

```csharp
[Priority(20)]
public partial class GenericSystem<T> : ISystem
{
    public void Init()
    {
        // 泛型系统的初始化
    }
}
```

### 与其他特性组合

Priority 可以与其他源代码生成器特性组合使用：

```csharp
using GFramework.Core.SourceGenerators.Abstractions.Bases;
using GFramework.Core.SourceGenerators.Abstractions.Logging;
using GFramework.Core.SourceGenerators.Abstractions.Rule;

[Priority(PriorityGroup.High)]
[Log]
[ContextAware]
public partial class HighPrioritySystem : AbstractSystem
{
    protected override void OnInit()
    {
        Logger.Info("High priority system initialized");
    }
}
```

### 运行时优先级查询

可以在运行时查询优先级值：

```csharp
public void ProcessSystems()
{
    var systems = this.GetAllByPriority<ISystem>();

    foreach (var system in systems)
    {
        if (system is IPrioritized prioritized)
        {
            Console.WriteLine($"System: {system.GetType().Name}, Priority: {prioritized.Priority}");
        }

        system.Init();
    }
}
```

## 常见问题

### Q: 优先级值可以是任意整数吗？

**A**: 是的，优先级值可以是任何 `int` 类型的值。推荐使用 `PriorityGroup` 预定义常量或在项目中定义自己的优先级常量。

### Q: 多个类有相同优先级会怎样？

**A**: 当多个类有相同的优先级值时，它们的相对顺序是不确定的。建议为每个类设置不同的优先级值，或在文档中明确说明相同优先级类的执行顺序不保证。

### Q: 可以在运行时改变优先级吗？

**A**: 不可以。`Priority` 属性是只读的，值在编译时确定。如果需要运行时改变优先级，应手动实现 `IPrioritized` 接口。

```csharp
public class DynamicPrioritySystem : IPrioritized
{
    private int _priority;

    public int Priority => _priority;

    public void SetPriority(int value)
    {
        _priority = value;
    }
}
```

### Q: 优先级支持继承吗？

**A**: `[Priority]` 特性标记为 `Inherited = false`，不会被子类继承。每个子类需要独立标记优先级。

```csharp
[Priority(10)]
public partial class BaseSystem { }

public partial class DerivedSystem : BaseSystem  // 不会继承 Priority = 10
{
    // 需要重新标记
    // [Priority(20)]
}
```

### Q: 如何在不使用特性的情况下实现优先级？

**A**: 可以手动实现 `IPrioritized` 接口：

```csharp
public class ManualPrioritySystem : IPrioritized
{
    public int Priority => 10;

    // 手动实现提供更大的灵活性
    public int Priority => _config.Enabled ? 10 : 100;
}
```

### Q: 负数优先级和正数优先级的区别是什么？

**A**: 优先级值用于排序，通常值越小优先级越高：

- 负数（-100）：高优先级，最先执行
- 零（0）：默认优先级
- 正数（100）：低优先级，最后执行

具体含义取决于使用场景，但推荐遵循 `PriorityGroup` 定义的语义。

## 实际应用示例

### 游戏系统架构

完整的游戏系统初始化示例：

```csharp
using GFramework.Core.Abstractions.Systems;
using GFramework.Core.SourceGenerators.Abstractions.Bases;
using GFramework.Core.Abstractions.Bases;

// 输入系统（最先初始化）
[Priority(PriorityGroup.Critical)]
[Log]
public partial class InputSystem : AbstractSystem
{
    protected override void OnInit()
    {
        Logger.Info("Input system initialized");
    }
}

// 物理系统
[Priority(PriorityGroup.High)]
[Log]
public partial class PhysicsSystem : AbstractSystem
{
    protected override void OnInit()
    {
        Logger.Info("Physics system initialized");
    }
}

// 游戏逻辑系统
[Priority(PriorityGroup.Normal)]
[Log]
[ContextAware]
public partial class GameplaySystem : AbstractSystem
{
    protected override void OnInit()
    {
        Logger.Info("Gameplay system initialized");
    }
}

// 音频系统
[Priority(PriorityGroup.Low)]
[Log]
public partial class AudioSystem : AbstractSystem
{
    protected override void OnInit()
    {
        Logger.Info("Audio system initialized");
    }
}

// 清理系统（最后执行）
[Priority(PriorityGroup.Deferred)]
[Log]
public partial class CleanupSystem : AbstractSystem
{
    protected override void OnInit()
    {
        Logger.Info("Cleanup system initialized");
    }
}
```

在架构中初始化：

```csharp
public class GameArchitecture : Architecture
{
    protected override async Task InitAsync()
    {
        // 获取所有系统并按优先级排序
        var systems = this.GetAllByPriority<ISystem>();

        foreach (var system in systems)
        {
            await system.InitAsync();
        }
    }
}
```

## 相关文档

- [Source Generators 概述](./index.md)
- [ContextAware 生成器](./context-aware-generator.md)
- [系统初始化](../core/system.md)
