# Priority 生成器 > 自动实现 IPrioritized 接口,为类添加优先级标记 Priority 生成器通过源代码生成器自动实现 `IPrioritized` 接口,简化优先级标记和排序逻辑的实现。 ## 概述 ### 核心功能 - **自动实现接口**:自动实现 `IPrioritized` 接口的 `Priority` 属性 - **优先级标记**:通过特性参数指定优先级值 - **编译时生成**:在编译时生成代码,零运行时开销 - **类型安全**:编译时类型检查,避免运行时错误 ### 适用场景 - 系统初始化顺序控制 - 事件处理器优先级排序 - 服务注册顺序管理 - 需要按优先级排序的任何场景 ## 基础使用 ### 标记优先级 使用 `[Priority]` 特性为类标记优先级: ```csharp using GFramework.SourceGenerators.Abstractions.Bases; [Priority(10)] public partial class MySystem { // 自动生成 IPrioritized 接口实现 } ``` ### 生成代码 编译器会自动生成如下代码: ```csharp // #nullable enable namespace YourNamespace; partial class MySystem : global::GFramework.Core.Abstractions.Bases.IPrioritized { /// /// 获取优先级值: 10 /// public int Priority => 10; } ``` ### 使用生成的优先级 生成的 `Priority` 属性可用于排序: ```csharp using GFramework.Core.Abstractions.Bases; // 获取所有实现了 IPrioritized 的系统 var systems = new List { 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.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.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(); foreach (var system in systems) { system.Init(); } } } ``` ### 事件处理器优先级 控制事件处理器的执行顺序: ```csharp using GFramework.Core.Abstractions.Events; // 关键事件处理器最先执行 [Priority(PriorityGroup.Critical)] public partial class CriticalEventHandler : IEventHandler { public void Handle(CriticalEvent e) { // 处理关键事件 } } // 普通处理器在中间执行 [Priority(PriorityGroup.Normal)] public partial class NormalEventHandler : IEventHandler { public void Handle(CriticalEvent e) { // 处理普通逻辑 } } // 日志记录器最后执行 [Priority(PriorityGroup.Deferred)] public partial class EventLogger : IEventHandler { public void Handle(CriticalEvent e) { // 记录日志 } } ``` 事件总线按优先级调用处理器: ```csharp public class EventBus : IEventBus { public void Send(TEvent e) where TEvent : IEvent { // 获取所有处理器并按优先级排序 var handlers = this.GetAllByPriority>(); 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()` 而非 `GetAll()` 的场景: **错误示例**: ```csharp // ❌ 不推荐:可能未按优先级排序 var systems = context.GetAll(); ``` **正确示例**: ```csharp // ✅ 推荐:确保按优先级排序 var systems = context.GetAllByPriority(); ``` ### 分析器规则 当满足以下条件时,分析器会报告 `GF_Priority_Usage_001` 诊断: 1. 类型实现了 `IPrioritized` 接口 2. 使用了 `GetAll()` 方法 3. 建议改用 `GetAllByPriority()` 方法 ## 诊断信息 ### 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 /// /// 输入系统,优先级 -100,需要最先初始化以接收输入事件 /// [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 : ISystem { public void Init() { // 泛型系统的初始化 } } ``` ### 与其他特性组合 Priority 可以与其他源代码生成器特性组合使用: ```csharp using GFramework.SourceGenerators.Abstractions.Bases; using GFramework.SourceGenerators.Abstractions.Logging; using GFramework.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(); 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.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(); foreach (var system in systems) { await system.InitAsync(); } } } ``` ## 相关文档 - [Source Generators 概述](./index.md) - [ContextAware 生成器](./context-aware-generator.md) - [系统初始化](../core/system.md)