框架更新

This commit is contained in:
Bob.Song
2025-10-29 17:59:43 +08:00
parent fc18c8626a
commit a2cb248512
429 changed files with 7173 additions and 38748 deletions

View File

@@ -0,0 +1,259 @@
using Fantasy.SourceGenerator.Common;
using Microsoft.CodeAnalysis;
namespace Fantasy.SourceGenerator.Generators
{
/// <summary>
/// 程序集初始化器生成器
/// 为每个 Fantasy 项目生成 ModuleInitializer在程序集加载时自动注册到框架
/// 支持 Native AOT无需运行时反射
/// </summary>
[Generator]
public class AssemblyInitializerGenerator : IIncrementalGenerator
{
public void Initialize(IncrementalGeneratorInitializationContext context)
{
// 获取编译信息
var compilationProvider = context.CompilationProvider;
// 注册源代码输出
context.RegisterSourceOutput(compilationProvider, (spc, compilation) =>
{
GenerateModuleInitializer(spc, compilation);
});
}
private static void GenerateModuleInitializer(
SourceProductionContext context,
Compilation compilation)
{
// 检查是否定义了 FANTASY_NET 或 FANTASY_UNITY 预编译符号
if (!CompilationHelper.HasFantasyDefine(compilation))
{
// 不是 Fantasy 框架项目,跳过代码生成
return;
}
var assemblyName = compilation.AssemblyName ?? "Unknown";
// 检测是否是 Unity 环境
var isUnity = CompilationHelper.IsUnityCompilation(compilation);
var builder = new SourceCodeBuilder();
// 添加文件头
builder.AppendLine(GeneratorConstants.AutoGeneratedHeader);
// 添加 using
if (isUnity)
{
builder.AddUsings(
"System",
"UnityEngine"
);
}
else
{
builder.AddUsings(
"System",
"System.Runtime.CompilerServices"
);
}
builder.AppendLine();
// 开始命名空间
builder.BeginNamespace(GeneratorConstants.GeneratedNamespace);
// 添加类注释
builder.AddXmlComment($"Auto-generated assembly initializer for {assemblyName}");
builder.AddXmlComment("This class is automatically invoked when the assembly is loaded via ModuleInitializer");
// 开始类定义
builder.BeginClass("AssemblyInitializer", "internal static");
// 添加字段
builder.AppendLine("private static bool _initialized;");
builder.AppendLine("private static long _assemblyManifestId;");
builder.AppendLine();
// 生成 ModuleInitializer 方法
GenerateInitializeMethod(builder, assemblyName, isUnity);
// 生成卸载方法
GenerateUnloadMethod(builder, isUnity);
// 结束 AssemblyInitializer 类
builder.EndClass();
builder.AppendLine();
// 生成 AssemblyMarker 类(用于强制加载程序集)
// 类名包含程序集名称以避免冲突,将特殊字符替换为下划线
var markerClassName = assemblyName.Replace("-", "_").Replace(".", "_") + "_AssemblyMarker";
builder.AddXmlComment($"Public marker class for forcing {assemblyName} assembly load");
builder.AddXmlComment("Access this type to ensure the assembly is loaded and ModuleInitializer executes");
builder.BeginClass(markerClassName, "public static");
builder.AppendLine("/// <summary>");
builder.AppendLine("/// Call this method to ensure the assembly is loaded");
builder.AppendLine("/// This is useful when loading assemblies dynamically via reflection");
builder.AppendLine("/// </summary>");
builder.BeginMethod("public static void EnsureLoaded()");
builder.AppendLine("// Accessing this method ensures the assembly is loaded");
builder.AppendLine("// ModuleInitializer will execute automatically when assembly loads");
builder.EndMethod();
builder.EndClass();
// 结束命名空间
builder.EndNamespace();
// 输出源代码
context.AddSource("AssemblyInitializer.g.cs", builder.ToString());
}
private static void GenerateInitializeMethod(SourceCodeBuilder builder, string assemblyName, bool isUnity)
{
if (isUnity)
{
builder.AddXmlComment(
"Unity runtime initializer - automatically called when entering play mode or on app start");
builder.AppendLine("[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.AfterAssembliesLoaded)]");
builder.BeginMethod("internal static void Initialize()");
}
else
{
builder.AddXmlComment("Module initializer - automatically called when assembly is loaded");
builder.AppendLine("[ModuleInitializer]");
builder.BeginMethod("internal static void Initialize()");
}
// 防止重复初始化
builder.AppendLine("if (_initialized)");
builder.OpenBrace();
builder.AppendLine("return;");
builder.CloseBrace();
builder.AppendLine();
builder.AppendLine("_initialized = true;");
builder.AppendLine();
// 获取程序集并计算唯一标识
builder.AddComment("Get assembly and calculate manifest ID");
builder.AppendLine("var assembly = typeof(AssemblyInitializer).Assembly;");
builder.AppendLine(
$"_assemblyManifestId = Fantasy.Helper.HashCodeHelper.ComputeHash64(assembly.GetName().Name ?? \"{assemblyName}\");");
builder.AppendLine();
// 注册卸载事件(用于热更新支持)
builder.AddComment("Register auto-unload for collectible AssemblyLoadContext (hot-reload support)");
if (isUnity)
{
builder.AppendLine(
"#if !UNITY_EDITOR && !UNITY_STANDALONE && !UNITY_ANDROID && !UNITY_IOS && !UNITY_WEBGL");
}
builder.AppendLine("var loadContext = System.Runtime.Loader.AssemblyLoadContext.GetLoadContext(assembly);");
builder.AppendLine(
"if (loadContext != null && loadContext != System.Runtime.Loader.AssemblyLoadContext.Default)");
builder.OpenBrace();
builder.AppendLine("loadContext.Unloading += OnAssemblyUnloading;");
builder.CloseBrace();
if (isUnity)
{
builder.AppendLine("#endif");
}
builder.AppendLine();
// 声明所有可能的注册器变量
builder.AddComment("Declare registrar variables");
builder.AppendLine("Fantasy.Assembly.INetworkProtocolRegistrar? networkProtocolRegistrar = null;");
builder.AppendLine("Fantasy.Assembly.IEventSystemRegistrar? eventSystemRegistrar = null;");
builder.AppendLine("Fantasy.Assembly.IEntitySystemRegistrar? entitySystemRegistrar = null;");
builder.AppendLine("Fantasy.Assembly.IMessageHandlerResolver? messageHandlerResolverRegistrar = null;");
builder.AppendLine(
"Fantasy.Assembly.IEntityTypeCollectionRegistrar? entityTypeCollectionRegistrar = null;");
builder.AppendLine(
"Fantasy.Assembly.INetworkProtocolOpCodeResolver? networkProtocolOpCodeResolverRegistrar = null;");
builder.AppendLine(
"Fantasy.Assembly.INetworkProtocolResponseTypeResolver? networkProtocolResponseTypeResolverRegistrar = null;");
builder.AppendLine("#if FANTASY_NET", false);
builder.AppendLine(
"Fantasy.Assembly.ISeparateTableRegistrar? separateTableRegistrar = null;");
builder.AppendLine("#endif", false);
builder.AppendLine();
// 尝试创建各个注册器(如果存在)
builder.AddComment("Try to create registrars if they were generated in this assembly");
GenerateTryCreateRegistrar(builder, "NetworkProtocol", "networkProtocolRegistrar");
GenerateTryCreateRegistrar(builder, "EventSystem", "eventSystemRegistrar");
GenerateTryCreateRegistrar(builder, "EntitySystem", "entitySystemRegistrar");
GenerateTryCreateRegistrar(builder, "MessageHandlerResolver", "messageHandlerResolverRegistrar");
GenerateTryCreateRegistrar(builder, "EntityTypeCollection", "entityTypeCollectionRegistrar");
GenerateTryCreateRegistrar(builder, "NetworkProtocolOpCodeResolver", "networkProtocolOpCodeResolverRegistrar");
GenerateTryCreateRegistrar(builder, "NetworkProtocolResponseTypeResolver", "networkProtocolResponseTypeResolverRegistrar");
builder.AppendLine("#if FANTASY_NET", false);
GenerateTryCreateRegistrar(builder, "SeparateTable", "separateTableRegistrar");
builder.AppendLine("#endif", false);
builder.AppendLine();
// 注册到框架
builder.AddComment("Register complete AssemblyManifest to the framework");
builder.AppendLine("#if FANTASY_NET", false);
builder.AppendLine("Fantasy.Assembly.AssemblyManifest.Register(");
builder.Indent();
builder.AppendLine("_assemblyManifestId,");
builder.AppendLine("assembly,");
builder.AppendLine("networkProtocolRegistrar,");
builder.AppendLine("eventSystemRegistrar,");
builder.AppendLine("entitySystemRegistrar,");
builder.AppendLine("messageHandlerResolverRegistrar,");
builder.AppendLine("entityTypeCollectionRegistrar,");
builder.AppendLine("separateTableRegistrar,");
builder.AppendLine("networkProtocolOpCodeResolverRegistrar,");
builder.AppendLine("networkProtocolResponseTypeResolverRegistrar);");
builder.Unindent();
builder.AppendLine("#endif", false);
builder.AppendLine("#if FANTASY_UNITY", false);
builder.AppendLine("Fantasy.Assembly.AssemblyManifest.Register(");
builder.Indent();
builder.AppendLine("_assemblyManifestId,");
builder.AppendLine("assembly,");
builder.AppendLine("networkProtocolRegistrar,");
builder.AppendLine("eventSystemRegistrar,");
builder.AppendLine("entitySystemRegistrar,");
builder.AppendLine("messageHandlerResolverRegistrar,");
builder.AppendLine("entityTypeCollectionRegistrar,");
builder.AppendLine("networkProtocolOpCodeResolverRegistrar,");
builder.AppendLine("networkProtocolResponseTypeResolverRegistrar);");
builder.Unindent();
builder.AppendLine("#endif", false);
builder.EndMethod();
}
private static void GenerateUnloadMethod(SourceCodeBuilder builder, bool isUnity)
{
builder.AppendLine();
builder.AddXmlComment("Called when AssemblyLoadContext is unloading (for hot-reload support)");
// Unity 环境下AssemblyLoadContext 仅在非编辑器/非独立平台可用
if (isUnity)
{
builder.AppendLine("#if !UNITY_EDITOR && !UNITY_STANDALONE && !UNITY_ANDROID && !UNITY_IOS && !UNITY_WEBGL");
}
builder.BeginMethod("private static void OnAssemblyUnloading(System.Runtime.Loader.AssemblyLoadContext context)");
builder.AddComment("Unregister from framework");
builder.AppendLine("if (_assemblyManifestId != 0)");
builder.OpenBrace();
builder.AppendLine("Fantasy.Assembly.AssemblyManifest.Unregister(_assemblyManifestId);");
builder.CloseBrace();
builder.EndMethod();
if (isUnity)
{
builder.AppendLine("#endif");
}
}
private static void GenerateTryCreateRegistrar(
SourceCodeBuilder builder,
string registrarName,
string variableName)
{
var typeName = $"Fantasy.Generated.{registrarName}Registrar";
builder.AppendLine($"{variableName} = new {typeName}();");
}
}
}

View File

@@ -0,0 +1,338 @@
using Fantasy.SourceGenerator.Common;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using System.Collections.Generic;
using System.Linq;
using System.Text;
#pragma warning disable CS8602 // Dereference of a possibly null reference.
namespace Fantasy.SourceGenerator.Generators
{
/// <summary>
/// Entity System 注册代码生成器
/// 自动生成 EntityComponent 所需的 System 注册代码,替代运行时反射
/// </summary>
[Generator]
public partial class EntitySystemGenerator : IIncrementalGenerator
{
public void Initialize(IncrementalGeneratorInitializationContext context)
{
// 查找所有实现了 IEntitySystem 相关接口的类
var systemTypes = context.SyntaxProvider
.CreateSyntaxProvider(
predicate: static (node, _) => IsSystemClass(node),
transform: static (ctx, _) => GetSystemTypeInfo(ctx))
.Where(static info => info != null)
.Collect();
// 组合编译信息和找到的类型
var compilationAndTypes = context.CompilationProvider.Combine(systemTypes);
// 注册源代码输出
context.RegisterSourceOutput(compilationAndTypes, static (spc, source) =>
{
// 检查1: 是否定义了 FANTASY_NET 或 FANTASY_UNITY 预编译符号
if (!CompilationHelper.HasFantasyDefine(source.Left))
{
return;
}
// 检查2: 是否引用了 Fantasy 框架的核心类型
if (source.Left.GetTypeByMetadataName("Fantasy.Assembly.IEntitySystemRegistrar") == null)
{
return;
}
GenerateRegistrationCode(spc, source.Left, source.Right!);
});
}
private static EntitySystemTypeInfo? GetSystemTypeInfo(GeneratorSyntaxContext context)
{
var classDecl = (ClassDeclarationSyntax)context.Node;
if (context.SemanticModel.GetDeclaredSymbol(classDecl) is not INamedTypeSymbol symbol || !symbol.IsInstantiable())
{
return null;
}
var baseType = symbol.BaseType;
if (!baseType.IsGenericType)
{
return null;
}
return baseType.Name switch
{
"AwakeSystem" => EntitySystemTypeInfo.Create(EntitySystemType.AwakeSystem, symbol),
"UpdateSystem" => EntitySystemTypeInfo.Create(EntitySystemType.UpdateSystem, symbol),
"DestroySystem" => EntitySystemTypeInfo.Create(EntitySystemType.DestroySystem, symbol),
"DeserializeSystem" => EntitySystemTypeInfo.Create(EntitySystemType.DeserializeSystem, symbol),
"LateUpdateSystem" => EntitySystemTypeInfo.Create(EntitySystemType.LateUpdateSystem, symbol),
_ => null
};
}
private static void GenerateRegistrationCode(
SourceProductionContext context,
Compilation compilation,
IEnumerable<EntitySystemTypeInfo> systemTypes)
{
var entitySystemTypeInfos = systemTypes.ToList();
// 获取当前程序集名称(仅用于注释)
var assemblyName = compilation.AssemblyName ?? "Unknown";
// 生成代码文件
var builder = new SourceCodeBuilder();
// 添加文件头
builder.AppendLine(GeneratorConstants.AutoGeneratedHeader);
// 添加 using
builder.AddUsings(
"System",
"System.Collections.Generic",
"Fantasy.Assembly",
"Fantasy.Entitas",
"Fantasy.Entitas.Interface"
);
builder.AppendLine();
// 开始命名空间(固定使用 Fantasy.Generated
builder.BeginNamespace("Fantasy.Generated");
// 开始类定义(实现 IEntitySystemRegistrar 接口)
builder.AddXmlComment($"Auto-generated Entity System registration class for {assemblyName}");
builder.BeginClass("EntitySystemRegistrar", "internal sealed", "IEntitySystemRegistrar");
// 生成字段用于存储 System 实例
GenerateFields(builder, entitySystemTypeInfos);
// 生成注册方法
GenerateRegisterMethod(builder, entitySystemTypeInfos);
// 生成反注册方法
GenerateUnRegisterMethod(builder, entitySystemTypeInfos);
// 结束类和命名空间
builder.EndClass();
builder.EndNamespace();
// 输出源代码
context.AddSource("EntitySystemRegistrar.g.cs", builder.ToString());
}
private static void GenerateFields(SourceCodeBuilder builder, List<EntitySystemTypeInfo> entitySystemTypeInfos)
{
builder.AddComment("Store registered entity system for UnRegister");
if (!entitySystemTypeInfos.Any())
{
return;
}
foreach (var eventSystemTypeInfo in entitySystemTypeInfos)
{
var fieldName = $"_{eventSystemTypeInfo.TypeName.ToCamelCase()}";
builder.AppendLine($"private {eventSystemTypeInfo.GlobalTypeFullName} {fieldName} = new {eventSystemTypeInfo.GlobalTypeFullName}();");
builder.AppendLine($"private const long _typeHashCode{fieldName} = {eventSystemTypeInfo.EntityTypeHashCode};");
}
builder.AppendLine();
}
private static void GenerateRegisterMethod(SourceCodeBuilder builder, List<EntitySystemTypeInfo> entitySystemTypeInfos)
{
builder.AddXmlComment("Register all Entity Systems to the dictionaries");
builder.AppendLine("#if FANTASY_NET", false);
builder.BeginMethod(
"public void RegisterSystems(" +
"Dictionary<long, Action<Entity>> awakeSystems, " +
"Dictionary<long, Action<Entity>> updateSystems, " +
"Dictionary<long, Action<Entity>> destroySystems, " +
"Dictionary<long, Action<Entity>> deserializeSystems)");
builder.AppendLine("#endif", false);
builder.Unindent();
builder.AppendLine("#if FANTASY_UNITY", false);
builder.BeginMethod(
"public void RegisterSystems(" +
"Dictionary<long, Action<Entity>> awakeSystems, " +
"Dictionary<long, Action<Entity>> updateSystems, " +
"Dictionary<long, Action<Entity>> destroySystems, " +
"Dictionary<long, Action<Entity>> deserializeSystems, " +
"Dictionary<long, Action<Entity>> lateUpdateSystems)");
builder.AppendLine("#endif", false);
if (entitySystemTypeInfos.Any())
{
foreach (var systemTypeInfo in entitySystemTypeInfos)
{
var fieldName = $"_{systemTypeInfo.TypeName.ToCamelCase()}";
switch (systemTypeInfo.EntitySystemType)
{
case EntitySystemType.AwakeSystem:
{
builder.AppendLine($"awakeSystems.Add(_typeHashCode{fieldName}, {fieldName}.Invoke);");
continue;
}
case EntitySystemType.UpdateSystem:
{
builder.AppendLine($"updateSystems.Add(_typeHashCode{fieldName}, {fieldName}.Invoke);");
continue;
}
case EntitySystemType.DestroySystem:
{
builder.AppendLine($"destroySystems.Add(_typeHashCode{fieldName}, {fieldName}.Invoke);");
continue;
}
case EntitySystemType.DeserializeSystem:
{
builder.AppendLine($"deserializeSystems.Add(_typeHashCode{fieldName}, {fieldName}.Invoke);");
continue;
}
case EntitySystemType.LateUpdateSystem:
{
builder.AppendLine("#if FANTASY_UNITY", false);
builder.AppendLine($"awakeSystems.Add(_typeHashCode{fieldName}, {fieldName}.Invoke);");
builder.AppendLine("#endif", false);
continue;
}
}
}
}
builder.EndMethod();
builder.AppendLine();
}
private static void GenerateUnRegisterMethod(SourceCodeBuilder builder, List<EntitySystemTypeInfo> entitySystemTypeInfos)
{
builder.AddXmlComment("Unregister all Entity Systems from the dictionaries");
builder.AppendLine("#if FANTASY_NET", false);
builder.BeginMethod(
"public void UnRegisterSystems(" +
"Dictionary<long, Action<Entity>> awakeSystems, " +
"Dictionary<long, Action<Entity>> updateSystems, " +
"Dictionary<long, Action<Entity>> destroySystems, " +
"Dictionary<long, Action<Entity>> deserializeSystems)");
builder.AppendLine("#endif", false);
builder.Unindent();
builder.AppendLine("#if FANTASY_UNITY", false);
builder.BeginMethod(
"public void UnRegisterSystems(" +
"Dictionary<long, Action<Entity>> awakeSystems, " +
"Dictionary<long, Action<Entity>> updateSystems, " +
"Dictionary<long, Action<Entity>> destroySystems, " +
"Dictionary<long, Action<Entity>> deserializeSystems, " +
"Dictionary<long, Action<Entity>> lateUpdateSystems)");
builder.AppendLine("#endif", false);
if (entitySystemTypeInfos.Any())
{
foreach (var systemTypeInfo in entitySystemTypeInfos)
{
var fieldName = $"_{systemTypeInfo.TypeName.ToCamelCase()}";
switch (systemTypeInfo.EntitySystemType)
{
case EntitySystemType.AwakeSystem:
{
builder.AppendLine($"awakeSystems.Remove(_typeHashCode{fieldName});");
continue;
}
case EntitySystemType.UpdateSystem:
{
builder.AppendLine($"updateSystems.Remove(_typeHashCode{fieldName});");
continue;
}
case EntitySystemType.DestroySystem:
{
builder.AppendLine($"destroySystems.Remove(_typeHashCode{fieldName});");
continue;
}
case EntitySystemType.DeserializeSystem:
{
builder.AppendLine($"deserializeSystems.Remove(_typeHashCode{fieldName});");
continue;
}
case EntitySystemType.LateUpdateSystem:
{
builder.AppendLine("#if FANTASY_UNITY", false);
builder.AppendLine($"lateUpdateSystem.Remove(_typeHashCode{fieldName});");
builder.AppendLine("#endif", false);
continue;
}
}
}
}
builder.EndMethod();
builder.AppendLine();
}
private static bool IsSystemClass(SyntaxNode node)
{
if (node is not ClassDeclarationSyntax classDecl)
{
return false;
}
// 必须有基类型列表(继承抽象类)
if (classDecl.BaseList == null || classDecl.BaseList.Types.Count == 0)
{
return false;
}
// 快速检查是否包含可能的 EntitySystem 基类名称
var baseListText = classDecl.BaseList.ToString();
return baseListText.Contains("AwakeSystem") ||
baseListText.Contains("UpdateSystem") ||
baseListText.Contains("DestroySystem") ||
baseListText.Contains("DeserializeSystem") ||
baseListText.Contains("LateUpdateSystem");
}
private enum EntitySystemType
{
None,
AwakeSystem,
UpdateSystem,
DestroySystem,
DeserializeSystem,
LateUpdateSystem
}
private sealed class EntitySystemTypeInfo
{
public readonly EntitySystemType EntitySystemType;
public readonly string GlobalTypeFullName;
public readonly string TypeFullName;
public readonly string TypeName;
public readonly long EntityTypeHashCode; // 预计算的实体类型哈希值
public readonly string EntityTypeFullName; // 实体类型的完整名称(用于注释)
private EntitySystemTypeInfo(
EntitySystemType entitySystemType,
string globalTypeFullName,
string typeFullName,
string typeName,
long entityTypeHashCode,
string entityTypeFullName)
{
EntitySystemType = entitySystemType;
GlobalTypeFullName = globalTypeFullName;
TypeFullName = typeFullName;
TypeName = typeName;
EntityTypeHashCode = entityTypeHashCode;
EntityTypeFullName = entityTypeFullName;
}
public static EntitySystemTypeInfo Create(EntitySystemType entitySystemType, INamedTypeSymbol symbol)
{
// 获取泛型参数 T (例如AwakeSystem<T> 中的 T)
var entityType = symbol.BaseType?.TypeArguments.FirstOrDefault();
var entityTypeFullName = entityType?.GetFullName(false) ?? "Unknown";
// 使用与运行时相同的算法计算哈希值
var entityTypeHashCode = HashCodeHelper.ComputeHash64(entityTypeFullName);
return new EntitySystemTypeInfo(
entitySystemType,
symbol.GetFullName(),
symbol.GetFullName(false),
symbol.Name,
entityTypeHashCode,
entityTypeFullName);
}
}
}
}

View File

@@ -0,0 +1,180 @@
using Fantasy.SourceGenerator.Common;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Syntax;
namespace Fantasy.SourceGenerator.Generators
{
[Generator]
public partial class EntityTypeCollectionGenerate : IIncrementalGenerator
{
public void Initialize(IncrementalGeneratorInitializationContext context)
{
// 查找所有实现了 EventSystem 相关抽象类的类
var protoBufTypes = context.SyntaxProvider
.CreateSyntaxProvider(
predicate: static (node, _) => IsEntityClass(node),
transform: static (ctx, _) => GetEntityTypeInfo(ctx))
.Where(static info => info != null)
.Collect();
// 组合编译信息和找到的类型
var compilationAndTypes = context.CompilationProvider.Combine(protoBufTypes);
// 注册源代码输出
context.RegisterSourceOutput(compilationAndTypes, static (spc, source) =>
{
// 检查1: 是否定义了 FANTASY_NET 或 FANTASY_UNITY 预编译符号
if (!CompilationHelper.HasFantasyDefine(source.Left))
{
return;
}
// 检查2: 是否引用了 Fantasy 框架的核心类型
if (source.Left.GetTypeByMetadataName("Fantasy.Assembly.IEntityTypeCollectionRegistrar") == null)
{
return;
}
GenerateRegistrationCode(spc, source.Left, source.Right!);
});
}
/// <summary>
/// 生成注册代码
/// </summary>
private static void GenerateRegistrationCode(
SourceProductionContext context,
Compilation compilation,
IEnumerable<EntityTypeInfo> entityTypeInfos)
{
var entityTypeList = entityTypeInfos.ToList();
// 获取当前程序集名称(仅用于注释)
var assemblyName = compilation.AssemblyName ?? "Unknown";
var builder = new SourceCodeBuilder();
// 添加文件头
builder.AppendLine(GeneratorConstants.AutoGeneratedHeader);
// 添加 using
builder.AddUsings(
"System",
"System.Collections.Generic",
"Fantasy.Assembly",
"Fantasy.DataStructure.Collection",
"Fantasy.Event"
);
builder.AppendLine();
// 开始命名空间(固定使用 Fantasy.Generated
builder.BeginNamespace("Fantasy.Generated");
// 开始类定义(实现 IEntityTypeCollectionRegistrar 接口)
builder.AddXmlComment($"Automatically generated Entity Type collection class for {assemblyName}");
builder.BeginClass("EntityTypeCollectionRegistrar", "internal sealed", "IEntityTypeCollectionRegistrar");
// 生成 GetEntityTypes 方法
GetEntityTypesMethod(builder, entityTypeList);
builder.AppendLine();
// 结束类和命名空间
builder.EndClass();
builder.EndNamespace();
// 输出源代码
context.AddSource("EntityTypeCollectionRegistrar.g.cs", builder.ToString());
}
private static void GetEntityTypesMethod(SourceCodeBuilder builder, List<EntityTypeInfo> entityTypeInfos)
{
builder.AddXmlComment("All Entity Types");
builder.BeginMethod("public List<Type> GetEntityTypes()");
if (entityTypeInfos.Any())
{
builder.AppendLine($"return new List<Type>({entityTypeInfos.Count})");
builder.AppendLine("{");
builder.Indent();
foreach (var system in entityTypeInfos)
{
builder.AppendLine($"typeof({system.EntityTypeFullName}),");
}
builder.Unindent();
builder.AppendLine("};");
builder.AppendLine();
}
else
{
builder.AppendLine($"return new List<Type>();");
}
builder.EndMethod();
}
private static bool IsEntityClass(SyntaxNode node)
{
if (node is not ClassDeclarationSyntax classDecl)
{
return false;
}
// 必须有基类型列表(实现接口)
return classDecl.BaseList != null && classDecl.BaseList.Types.Any();
}
private static EntityTypeInfo? GetEntityTypeInfo(GeneratorSyntaxContext context)
{
var classDecl = (ClassDeclarationSyntax)context.Node;
var semanticModel = context.SemanticModel;
// 检查是否继承自 Entity 或 Entity<T>
if (!InheritsFromEntity(classDecl, semanticModel))
{
return null;
}
var symbol = context.SemanticModel.GetDeclaredSymbol(classDecl) as INamedTypeSymbol;
if (symbol == null || !symbol.IsInstantiable())
{
return null;
}
return new EntityTypeInfo(
symbol.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat),
symbol.Name
);
}
private static bool InheritsFromEntity(ClassDeclarationSyntax classDecl, SemanticModel semanticModel)
{
if (classDecl.BaseList == null)
{
return false;
}
foreach (var baseType in classDecl.BaseList.Types)
{
var typeInfo = semanticModel.GetTypeInfo(baseType.Type);
var baseTypeSymbol = typeInfo.Type as INamedTypeSymbol;
if (baseTypeSymbol == null)
{
continue;
}
// 检查是否是 Entity非泛型
if (baseTypeSymbol.Name == "Entity" && baseTypeSymbol.Arity == 0)
{
return true;
}
// 检查是否是 Entity<T>(泛型)
if (baseTypeSymbol.IsGenericType)
{
var originalDef = baseTypeSymbol.OriginalDefinition;
if (originalDef.Name == "Entity" && originalDef.Arity == 1)
{
return true;
}
}
}
return false;
}
private sealed record EntityTypeInfo(
string EntityTypeFullName,
string EntityTypeName
);
}
}

View File

@@ -0,0 +1,305 @@
using Fantasy.SourceGenerator.Common;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using System.Collections.Generic;
using System.Linq;
using System.Text;
// ReSharper disable AssignNullToNotNullAttribute
namespace Fantasy.SourceGenerator.Generators
{
/// <summary>
/// Event System 注册代码生成器
/// 自动生成 EventComponent 所需的 Event System 注册代码,替代运行时反射
/// </summary>
[Generator]
public partial class EventSystemGenerator : IIncrementalGenerator
{
public void Initialize(IncrementalGeneratorInitializationContext context)
{
// 查找所有实现了 EventSystem 相关抽象类的类
var eventSystemTypes = context.SyntaxProvider
.CreateSyntaxProvider(
predicate: static (node, _) => IsEventSystemClass(node),
transform: static (ctx, _) => GetEventSystemTypeInfo(ctx))
.Where(static info => info != null)
.Collect();
// 组合编译信息和找到的类型
var compilationAndTypes = context.CompilationProvider.Combine(eventSystemTypes);
// 注册源代码输出
context.RegisterSourceOutput(compilationAndTypes, static (spc, source) =>
{
// 检查1: 是否定义了 FANTASY_NET 或 FANTASY_UNITY 预编译符号
if (!CompilationHelper.HasFantasyDefine(source.Left))
{
return;
}
// 检查2: 是否引用了 Fantasy 框架的核心类型
if (source.Left.GetTypeByMetadataName("Fantasy.Assembly.IEventSystemRegistrar") == null)
{
return;
}
GenerateRegistrationCode(spc, source.Left, source.Right!);
});
}
/// <summary>
/// 提取 EventSystem 类型信息
/// </summary>
private static EventSystemTypeInfo? GetEventSystemTypeInfo(GeneratorSyntaxContext context)
{
var classDecl = (ClassDeclarationSyntax)context.Node;
if (context.SemanticModel.GetDeclaredSymbol(classDecl) is not INamedTypeSymbol symbol || !symbol.IsInstantiable())
{
return null;
}
if (symbol.BaseType == null)
{
return null;
}
var baseType = symbol.BaseType;
if (!baseType.IsGenericType)
{
return null;
}
return baseType.Name switch
{
"EventSystem" => EventSystemTypeInfo.Create(EventSystemType.EventSystem, symbol),
"AsyncEventSystem" => EventSystemTypeInfo.Create(EventSystemType.AsyncEventSystem, symbol),
"SphereEventSystem" => EventSystemTypeInfo.Create(EventSystemType.SphereEventSystem, symbol),
_ => null
};
}
/// <summary>
/// 生成注册代码
/// </summary>
private static void GenerateRegistrationCode(
SourceProductionContext context,
Compilation compilation,
IEnumerable<EventSystemTypeInfo> eventSystemTypes)
{
var eventSystems = eventSystemTypes.ToList();
// 获取当前程序集名称(仅用于注释)
var assemblyName = compilation.AssemblyName ?? "Unknown";
// 生成代码文件
var builder = new SourceCodeBuilder();
// 添加文件头
builder.AppendLine(GeneratorConstants.AutoGeneratedHeader);
// 添加 using
builder.AddUsings(
"System",
"System.Collections.Generic",
"Fantasy.Assembly",
"Fantasy.DataStructure.Collection",
"Fantasy.Event"
);
builder.AppendLine();
// 开始命名空间(固定使用 Fantasy.Generated
builder.BeginNamespace("Fantasy.Generated");
// 开始类定义(实现 IEventSystemRegistrar 接口)
builder.AddXmlComment($"Auto-generated Event System registration class for {assemblyName}");
builder.BeginClass("EventSystemRegistrar", "internal sealed", "IEventSystemRegistrar");
// 生成字段用于存储已注册的事件处理器(用于 UnRegister
GenerateFields(builder, eventSystems);
// 生成 RegisterSystems 方法
GenerateRegisterMethod(builder, eventSystems);
// 生成 UnRegisterSystems 方法
GenerateUnRegisterMethod(builder, eventSystems);
// 生成 Dispose 方法
GenerateDisposeMethod(builder, eventSystems);
// 结束类和命名空间
builder.EndClass();
builder.EndNamespace();
// 输出源代码
context.AddSource("EventSystemRegistrar.g.cs", builder.ToString());
}
/// <summary>
/// 生成字段,用于存储已注册的事件处理器实例
/// </summary>
private static void GenerateFields(SourceCodeBuilder builder, List<EventSystemTypeInfo> eventSystems)
{
builder.AddComment("Store registered event handlers for UnRegister");
if (!eventSystems.Any())
{
return;
}
foreach (var eventSystemTypeInfo in eventSystems)
{
var fieldName = $"_{eventSystemTypeInfo.TypeName.ToCamelCase()}";
builder.AppendLine($"private {eventSystemTypeInfo.TypeFullName} {fieldName} = new {eventSystemTypeInfo.TypeFullName}();");
}
builder.AppendLine();
}
/// <summary>
/// 生成 RegisterSystems 方法
/// </summary>
private static void GenerateRegisterMethod(SourceCodeBuilder builder, List<EventSystemTypeInfo> eventSystems)
{
builder.AddXmlComment("Register all Event Systems to the containers");
builder.BeginMethod(
"public void RegisterSystems(" +
"OneToManyList<RuntimeTypeHandle, IEvent> events, " +
"OneToManyList<RuntimeTypeHandle, IEvent> asyncEvents, " +
"OneToManyList<RuntimeTypeHandle, IEvent> sphereEvents)");
if (eventSystems.Any())
{
foreach (var eventSystemTypeInfo in eventSystems)
{
var fieldName = $"_{eventSystemTypeInfo.TypeName.ToCamelCase()}";
switch (eventSystemTypeInfo.EventSystemType)
{
case EventSystemType.EventSystem:
{
builder.AppendLine($"events.Add({fieldName}.EventType().TypeHandle, {fieldName});");
continue;
}
case EventSystemType.AsyncEventSystem:
{
builder.AppendLine($"asyncEvents.Add({fieldName}.EventType().TypeHandle, {fieldName});");
continue;
}
case EventSystemType.SphereEventSystem:
{
builder.AppendLine($"sphereEvents.Add({fieldName}.EventType().TypeHandle, {fieldName});");
continue;
}
}
}
}
builder.EndMethod();
builder.AppendLine();
}
/// <summary>
/// 生成 UnRegisterSystems 方法
/// </summary>
private static void GenerateUnRegisterMethod(SourceCodeBuilder builder, List<EventSystemTypeInfo> eventSystems)
{
builder.AddXmlComment("Unregister all Event Systems from the containers (called on hot reload)");
builder.BeginMethod(
"public void UnRegisterSystems(" +
"OneToManyList<RuntimeTypeHandle, IEvent> events, " +
"OneToManyList<RuntimeTypeHandle, IEvent> asyncEvents, " +
"OneToManyList<RuntimeTypeHandle, IEvent> sphereEvents)");
if (eventSystems.Any())
{
foreach (var eventSystemTypeInfo in eventSystems)
{
var fieldName = $"_{eventSystemTypeInfo.TypeName.ToCamelCase()}";
switch (eventSystemTypeInfo.EventSystemType)
{
case EventSystemType.EventSystem:
{
builder.AppendLine($"events.RemoveValue({fieldName}.EventType().TypeHandle, {fieldName});");
continue;
}
case EventSystemType.AsyncEventSystem:
{
builder.AppendLine($"asyncEvents.RemoveValue({fieldName}.EventType().TypeHandle, {fieldName});");
continue;
}
case EventSystemType.SphereEventSystem:
{
builder.AppendLine($"sphereEvents.RemoveValue({fieldName}.EventType().TypeHandle, {fieldName});");
continue;
}
}
}
}
builder.EndMethod();
builder.AppendLine();
}
/// <summary>
/// 生成 Dispose 方法
/// </summary>
private static void GenerateDisposeMethod(SourceCodeBuilder builder, List<EventSystemTypeInfo> eventSystems)
{
builder.AddXmlComment("Dispose all resources");
builder.BeginMethod("public void Dispose()");
builder.AddComment("Clear all references");
if (eventSystems.Any())
{
foreach (var eventSystemTypeInfo in eventSystems)
{
var fieldName = $"_{eventSystemTypeInfo.TypeName.ToCamelCase()}";
builder.AppendLine($"{fieldName} = null;");
}
}
builder.EndMethod();
}
/// <summary>
/// 快速判断语法节点是否可能是 EventSystem 类
/// </summary>
private static bool IsEventSystemClass(SyntaxNode node)
{
if (node is not ClassDeclarationSyntax classDecl)
{
return false;
}
// 必须有基类型列表(继承抽象类)
if (classDecl.BaseList == null || classDecl.BaseList.Types.Count == 0)
{
return false;
}
// 快速检查是否包含可能的 EventSystem 基类名称
var baseListText = classDecl.BaseList.ToString();
return baseListText.Contains("AwakeSystem") ||
baseListText.Contains("AsyncEventSystem") ||
baseListText.Contains("SphereEventSystem");
}
private enum EventSystemType
{
None,
EventSystem, // EventSystem<T> 事件类
AsyncEventSystem, // AsyncEventSystem<T> 事件类
SphereEventSystem, // SphereEventSystem<T> 事件类
}
private sealed class EventSystemTypeInfo
{
public readonly EventSystemType EventSystemType;
public readonly string TypeFullName;
public readonly string TypeName;
private EventSystemTypeInfo(EventSystemType eventSystemType, string typeFullName, string typeName)
{
EventSystemType = eventSystemType;
TypeFullName = typeFullName;
TypeName = typeName;
}
public static EventSystemTypeInfo Create(EventSystemType eventSystemType, INamedTypeSymbol symbol)
{
return new EventSystemTypeInfo(
eventSystemType,
symbol.GetFullName(),
symbol.Name);
}
}
}
}

View File

@@ -0,0 +1,379 @@
using Fantasy.SourceGenerator.Common;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Syntax;
namespace Fantasy.SourceGenerator.Generators
{
[Generator]
public sealed class MessageHandlerGenerator : IIncrementalGenerator
{
public void Initialize(IncrementalGeneratorInitializationContext context)
{
// 查找所有实现了消息相关接口的类
var messageTypes = context.SyntaxProvider
.CreateSyntaxProvider(
predicate: static (node, _) => IsMessageHandlerClass(node),
transform: static (ctx, _) => GetMessageTypeInfo(ctx))
.Where(static info => info != null)
.Collect();
// 组合编译信息和找到的类型
var compilationAndTypes = context.CompilationProvider.Combine(messageTypes);
// 注册源代码输出
context.RegisterSourceOutput(compilationAndTypes, static (spc, source) =>
{
// 检查1: 是否定义了 FANTASY_NET 或 FANTASY_UNITY 预编译符号
if (!CompilationHelper.HasFantasyDefine(source.Left))
{
return;
}
// 检查2: 是否引用了 Fantasy 框架的核心类型
if (source.Left.GetTypeByMetadataName("Fantasy.Assembly.INetworkProtocolRegistrar") == null)
{
return;
}
GenerateRegistrationCode(spc, source.Left, source.Right!);
});
}
private static void GenerateRegistrationCode(
SourceProductionContext context,
Compilation compilation,
IEnumerable<MessageHandlerInfo> messageHandlerInfos)
{
var messageHandlers = new List<MessageHandlerInfo>();
var routeMessageHandlers = new List<MessageHandlerInfo>();
foreach (var messageHandlerInfo in messageHandlerInfos)
{
switch (messageHandlerInfo.HandlerType)
{
case HandlerType.MessageHandler:
{
messageHandlers.Add(messageHandlerInfo);
break;
}
case HandlerType.RouteMessageHandler:
{
routeMessageHandlers.Add(messageHandlerInfo);
break;
}
}
}
var assemblyName = compilation.AssemblyName ?? "Unknown";
var builder = new SourceCodeBuilder();
builder.AppendLine(GeneratorConstants.AutoGeneratedHeader);
builder.AddUsings(
"System",
"System.Collections.Generic",
"Fantasy.Assembly",
"Fantasy.DataStructure.Dictionary",
"Fantasy.Network.Interface",
"Fantasy.Network",
"Fantasy.Entitas",
"Fantasy.Async",
"System.Runtime.CompilerServices"
);
builder.AppendLine();
builder.BeginNamespace("Fantasy.Generated");
builder.AddXmlComment($"Auto-generated message handler registration class for {assemblyName}");
builder.BeginClass("MessageHandlerResolverRegistrar", "internal sealed", "IMessageHandlerResolver");
// 生成字段用于存储已注册的实例(用于 UnRegister
GenerateFields(builder, messageHandlers, routeMessageHandlers);
// 生成 Register 方法
GenerateRegistrationCode(builder, messageHandlers, routeMessageHandlers);
// 结束类和命名空间
builder.EndClass();
builder.EndNamespace();
// 输出源代码
context.AddSource("MessageHandlerResolverRegistrar.g.cs", builder.ToString());
}
private static void GenerateFields(SourceCodeBuilder builder, List<MessageHandlerInfo> messageHandlers, List<MessageHandlerInfo> routeMessageHandlers)
{
foreach (var messageHandlerInfo in messageHandlers)
{
builder.AppendLine($"private Func<Session, uint, uint, object, FTask> message_{messageHandlerInfo.TypeName} = new {messageHandlerInfo.TypeFullName}().Handle;");
}
foreach (var messageHandlerInfo in routeMessageHandlers)
{
builder.AppendLine($"private Func<Session, Entity, uint, object, FTask> routeMessage_{messageHandlerInfo.TypeName} = new {messageHandlerInfo.TypeFullName}().Handle;");
}
builder.AppendLine();
}
private static void GenerateRegistrationCode(SourceCodeBuilder builder, List<MessageHandlerInfo> messageHandlers, List<MessageHandlerInfo> routeMessageHandlers)
{
builder.AppendLine("[MethodImpl(MethodImplOptions.AggressiveInlining)]");
builder.BeginMethod("public int GetMessageHandlerCount()");
builder.AppendLine($"return {messageHandlers.Count};");
builder.EndMethod();
builder.AppendLine("[MethodImpl(MethodImplOptions.AggressiveInlining)]");
builder.BeginMethod("public int GetRouteMessageHandlerCount()");
builder.AppendLine($"return {routeMessageHandlers.Count};");
builder.EndMethod();
builder.AppendLine("[MethodImpl(MethodImplOptions.AggressiveInlining)]");
builder.BeginMethod("public bool MessageHandler(Session session, uint rpcId, uint protocolCode, object message)");
if (messageHandlers.Any())
{
builder.AppendLine("switch (protocolCode)");
builder.AppendLine("{");
builder.Indent();
foreach (var messageHandlerInfo in messageHandlers)
{
builder.AppendLine($"case {messageHandlerInfo.OpCode}:");
builder.AppendLine("{");
builder.Indent();
builder.AppendLine($"message_{messageHandlerInfo.TypeName}(session, rpcId, protocolCode, message).Coroutine();");
builder.AppendLine($"return true;");
builder.Unindent();
builder.AppendLine("}");
}
builder.AppendLine("default:");
builder.AppendLine("{");
builder.Indent();
builder.AppendLine($"return false;");
builder.Unindent();
builder.AppendLine("}");
builder.Unindent();
builder.AppendLine("}");
}
else
{
builder.AppendLine($"return false;");
}
builder.EndMethod();
builder.AppendLine("#if FANTASY_NET", false);
builder.AppendLine("[MethodImpl(MethodImplOptions.AggressiveInlining)]");
builder.BeginMethod("public async FTask<bool> RouteMessageHandler(Session session, Entity entity, uint rpcId, uint protocolCode, object message)");
if (routeMessageHandlers.Any())
{
builder.AppendLine("switch (protocolCode)");
builder.AppendLine("{");
builder.Indent();
foreach (var routeMessageHandler in routeMessageHandlers)
{
builder.AppendLine($"case {routeMessageHandler.OpCode}:");
builder.AppendLine("{");
builder.Indent();
builder.AppendLine($"await routeMessage_{routeMessageHandler.TypeName}(session, entity, rpcId, message);");
builder.AppendLine($"return true;");
builder.Unindent();
builder.AppendLine("}");
}
builder.AppendLine("default:");
builder.AppendLine("{");
builder.Indent();
builder.AppendLine($"await FTask.CompletedTask;");
builder.AppendLine($"return false;");
builder.Unindent();
builder.AppendLine("}");
builder.Unindent();
builder.AppendLine("}");
}
else
{
builder.AppendLine($"await FTask.CompletedTask;");
builder.AppendLine($"return false;");
}
builder.EndMethod();
builder.AppendLine("#endif", false);
}
private static bool IsMessageHandlerClass(SyntaxNode node)
{
if (node is not ClassDeclarationSyntax classDecl)
{
return false;
}
if (classDecl.BaseList == null || !classDecl.BaseList.Types.Any())
{
return false;
}
foreach (var baseType in classDecl.BaseList.Types)
{
var typeName = baseType.Type.ToString();
if (typeName.Contains("IMessageHandler") ||
typeName.Contains("IRouteMessageHandler") ||
typeName.Contains("Message<") ||
typeName.Contains("MessageRPC<") ||
typeName.Contains("Route<") ||
typeName.Contains("RouteRPC<") ||
typeName.Contains("Addressable<") ||
typeName.Contains("AddressableRPC<") ||
typeName.Contains("Roaming<") ||
typeName.Contains("RoamingRPC<"))
{
return true;
}
}
return false;
}
private static MessageHandlerInfo? GetMessageTypeInfo(GeneratorSyntaxContext context)
{
var classDecl = (ClassDeclarationSyntax)context.Node;
if (context.SemanticModel.GetDeclaredSymbol(classDecl) is not INamedTypeSymbol symbol ||
!symbol.IsInstantiable())
{
return null;
}
var baseType = symbol.BaseType;
if (baseType is not { IsGenericType: true } || baseType.TypeArguments.Length <= 0)
{
return null;
}
var baseTypeName = baseType.OriginalDefinition.ToDisplayString();
switch (baseTypeName)
{
case "Fantasy.Network.Interface.Message<T>":
case "Fantasy.Network.Interface.MessageRPC<TRequest, TResponse>":
{
return new MessageHandlerInfo(
HandlerType.MessageHandler,
symbol.GetFullName(),
symbol.Name,
GetOpCode(context, baseType, 0));
}
case "Fantasy.Network.Interface.Route<TEntity, TMessage>":
case "Fantasy.Network.Interface.RouteRPC<TEntity, TRouteRequest, TRouteResponse>":
case "Fantasy.Network.Interface.Addressable<TEntity, TMessage>":
case "Fantasy.Network.Interface.AddressableRPC<TEntity, TRouteRequest, TRouteResponse>":
case "Fantasy.Network.Interface.Roaming<TEntity, TMessage>":
case "Fantasy.Network.Interface.RoamingRPC<TEntity, TRouteRequest, TRouteResponse>":
{
return new MessageHandlerInfo(
HandlerType.RouteMessageHandler,
symbol.GetFullName(),
symbol.Name,
GetOpCode(context, baseType, 1));
}
}
return null;
}
private static uint? GetOpCode(GeneratorSyntaxContext context, INamedTypeSymbol baseType, int index)
{
if (baseType.TypeArguments.Length <= index)
{
return null;
}
var messageType = (INamedTypeSymbol)baseType.TypeArguments[index];
var messageName = messageType.Name;
var compilation = context.SemanticModel.Compilation;
// 策略1从消息类型所在程序集中搜索 OpCode 类
var messageAssembly = messageType.ContainingAssembly;
var namespaceName = messageType.ContainingNamespace.ToDisplayString();
// 遍历程序集中的所有类型,查找 OuterOpcode 或 InnerOpcode
var opCodeTypeNames = new[] { "OuterOpcode", "InnerOpcode" };
foreach (var opCodeTypeName in opCodeTypeNames)
{
var opCodeType = FindTypeInAssembly(messageAssembly.GlobalNamespace, namespaceName, opCodeTypeName);
if (opCodeType != null)
{
var opCodeField = opCodeType.GetMembers(messageName).OfType<IFieldSymbol>().FirstOrDefault();
if (opCodeField != null && opCodeField.IsConst && opCodeField.ConstantValue is uint constValue)
{
return constValue;
}
}
}
// 策略2如果策略1失败尝试从 OpCode() 方法的语法树中解析(仅适用于同项目中的消息)
var opCodeMethod = messageType.GetMembers("OpCode").OfType<IMethodSymbol>().FirstOrDefault();
if (opCodeMethod != null)
{
var opCodeSyntax = opCodeMethod.DeclaringSyntaxReferences.FirstOrDefault()?.GetSyntax() as MethodDeclarationSyntax;
if (opCodeSyntax?.Body != null)
{
var returnStatement = opCodeSyntax.Body.DescendantNodes()
.OfType<ReturnStatementSyntax>()
.FirstOrDefault();
if (returnStatement?.Expression != null)
{
var syntaxTree = opCodeSyntax.SyntaxTree;
if (compilation.ContainsSyntaxTree(syntaxTree))
{
var semanticModel = compilation.GetSemanticModel(syntaxTree);
// 尝试符号解析
var symbolInfo = semanticModel.GetSymbolInfo(returnStatement.Expression);
if (symbolInfo.Symbol is IFieldSymbol fieldSymbol && fieldSymbol.IsConst && fieldSymbol.ConstantValue is uint constValue2)
{
return constValue2;
}
// 尝试常量值解析
var constantValue = semanticModel.GetConstantValue(returnStatement.Expression);
if (constantValue.HasValue && constantValue.Value is uint uintValue)
{
return uintValue;
}
}
}
}
}
return null;
}
// 辅助方法:在程序集的命名空间中递归查找指定类型
private static INamedTypeSymbol? FindTypeInAssembly(INamespaceSymbol namespaceSymbol, string targetNamespace, string typeName)
{
// 如果当前命名空间匹配目标命名空间,查找类型
if (namespaceSymbol.ToDisplayString() == targetNamespace)
{
var type = namespaceSymbol.GetTypeMembers(typeName).FirstOrDefault();
if (type != null)
{
return type;
}
}
// 递归搜索子命名空间
foreach (var childNamespace in namespaceSymbol.GetNamespaceMembers())
{
var result = FindTypeInAssembly(childNamespace, targetNamespace, typeName);
if (result != null)
{
return result;
}
}
return null;
}
private enum HandlerType
{
None,
MessageHandler,
RouteMessageHandler
}
private sealed record MessageHandlerInfo(
HandlerType HandlerType,
string TypeFullName,
string TypeName,
uint? OpCode);
}
}

View File

@@ -0,0 +1,398 @@
using System.Linq;
using System.Text;
using Fantasy.SourceGenerator.Common;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Syntax;
#pragma warning disable CS0649 // Field is never assigned to, and will always have its default value
#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring as nullable.
namespace Fantasy.SourceGenerator.Generators;
[Generator]
internal partial class NetworkProtocolGenerator : IIncrementalGenerator
{
public void Initialize(IncrementalGeneratorInitializationContext context)
{
var networkProtocols = context.SyntaxProvider
.CreateSyntaxProvider(
predicate: static (node, _) => IsNetworkProtocolClass(node),
transform: static (ctx, _) => GetNetworkProtocolInfo(ctx))
.Where(static info => info != null)
.Collect();
var compilationAndTypes = context.CompilationProvider.Combine(networkProtocols);
context.RegisterSourceOutput(compilationAndTypes, static (spc, source) =>
{
if (!CompilationHelper.HasFantasyDefine(source.Left))
{
return;
}
if (source.Left.GetTypeByMetadataName("Fantasy.Assembly.INetworkProtocolRegistrar") == null)
{
return;
}
GenerateCode(spc, source.Left, source.Right!);
});
}
#region GenerateCode
private static void GenerateCode(
SourceProductionContext context,
Compilation compilation,
IEnumerable<NetworkProtocolTypeInfo> networkProtocolTypeInfos)
{
var networkProtocolTypeInfoList = networkProtocolTypeInfos.ToList();
// 获取当前程序集名称(仅用于注释)
var assemblyName = compilation.AssemblyName ?? "Unknown";
// 生成网络网络协议类型注册的类。
GenerateNetworkProtocolTypesCode(context, assemblyName, networkProtocolTypeInfoList);
// 生成OpCode辅助方法。
GenerateNetworkProtocolOpCodeResolverCode(context, assemblyName, networkProtocolTypeInfoList);
// 生成Request消息的ResponseType辅助方法。
GenerateNetworkProtocolResponseTypesResolverCode(context, assemblyName, networkProtocolTypeInfoList);
}
private static void GenerateNetworkProtocolTypesCode(
SourceProductionContext context,
string assemblyName,
List<NetworkProtocolTypeInfo> networkProtocolTypeInfoList)
{
var builder = new SourceCodeBuilder();
// 添加文件头
builder.AppendLine(GeneratorConstants.AutoGeneratedHeader);
// 添加 using
builder.AddUsings(
"System",
"System.Collections.Generic",
"Fantasy.Assembly",
"Fantasy.DataStructure.Collection"
);
// 开始命名空间(固定使用 Fantasy.Generated
builder.BeginNamespace("Fantasy.Generated");
// 开始类定义(实现 IEventSystemRegistrar 接口)
builder.AddXmlComment($"Auto-generated NetworkProtocol registration class for {assemblyName}");
builder.BeginClass("NetworkProtocolRegistrar", "internal sealed", "INetworkProtocolRegistrar");
builder.BeginMethod("public List<Type> GetNetworkProtocolTypes()");
if (networkProtocolTypeInfoList.Any())
{
builder.AppendLine($"return new List<Type>({networkProtocolTypeInfoList.Count})");
builder.AppendLine("{");
builder.Indent();
foreach (var system in networkProtocolTypeInfoList)
{
builder.AppendLine($"typeof({system.FullName}),");
}
builder.Unindent();
builder.AppendLine("};");
builder.AppendLine();
}
else
{
builder.AppendLine($"return new List<Type>();");
}
builder.EndMethod();
builder.AppendLine();
// 结束类和命名空间
builder.EndClass();
builder.EndNamespace();
// 输出源代码
context.AddSource("NetworkProtocolRegistrar.g.cs", builder.ToString());
}
private static void GenerateNetworkProtocolOpCodeResolverCode(
SourceProductionContext context,
string assemblyName,
List<NetworkProtocolTypeInfo> networkProtocolTypeInfoList)
{
var routeTypeInfos = networkProtocolTypeInfoList.Where(d => d.RouteType.HasValue).ToList();
var builder = new SourceCodeBuilder();
// 添加文件头
builder.AppendLine(GeneratorConstants.AutoGeneratedHeader);
// 添加 using
builder.AddUsings(
"System",
"System.Collections.Generic",
"Fantasy.Assembly",
"Fantasy.DataStructure.Collection",
"System.Runtime.CompilerServices"
);
builder.AppendLine();
// 开始命名空间(固定使用 Fantasy.Generated
builder.BeginNamespace("Fantasy.Generated");
// 开始类定义(实现 INetworkProtocolOpCodeResolver 接口)
builder.AddXmlComment($"Auto-generated NetworkProtocolOpCodeResolverRegistrar class for {assemblyName}");
builder.BeginClass("NetworkProtocolOpCodeResolverRegistrar", "internal sealed", "INetworkProtocolOpCodeResolver");
builder.AddXmlComment($"GetOpCodeCount");
builder.AppendLine("[MethodImpl(MethodImplOptions.AggressiveInlining)]");
builder.BeginMethod("public int GetOpCodeCount()");
builder.AppendLine($"return {networkProtocolTypeInfoList.Count};");
builder.EndMethod();
builder.AddXmlComment($"GetCustomRouteTypeCount");
builder.AppendLine("[MethodImpl(MethodImplOptions.AggressiveInlining)]");
builder.BeginMethod("public int GetCustomRouteTypeCount()");
builder.AppendLine($"return {routeTypeInfos.Count};");
builder.EndMethod();
// 开始定义GetOpCodeType方法
builder.AddXmlComment($"GetOpCodeType");
builder.AppendLine("[MethodImpl(MethodImplOptions.AggressiveInlining)]");
builder.BeginMethod("public Type GetOpCodeType(uint opCode)");
if (networkProtocolTypeInfoList.Any())
{
builder.AppendLine("switch (opCode)");
builder.AppendLine("{");
builder.Indent();
foreach (var networkProtocolTypeInfo in networkProtocolTypeInfoList)
{
builder.AppendLine($"case {networkProtocolTypeInfo.OpCode}:");
builder.AppendLine("{");
builder.Indent();
builder.AppendLine($"return typeof({networkProtocolTypeInfo.FullName});");
builder.Unindent();
builder.AppendLine("}");
}
builder.AppendLine("default:");
builder.AppendLine("{");
builder.Indent();
builder.AppendLine($"return null!;");
builder.Unindent();
builder.AppendLine("}");
builder.Unindent();
builder.AppendLine("}");
builder.AppendLine();
}
else
{
builder.AppendLine($"return null!;");
}
builder.EndMethod();
// 开始定义GetRouteType方法
builder.AddXmlComment($"CustomRouteType");
builder.AppendLine("[MethodImpl(MethodImplOptions.AggressiveInlining)]");
builder.BeginMethod("public int? GetCustomRouteType(uint opCode)");
if (routeTypeInfos.Any())
{
builder.AppendLine("switch (opCode)");
builder.AppendLine("{");
builder.Indent();
foreach (var routeTypeInfo in routeTypeInfos)
{
builder.AppendLine($"case {routeTypeInfo.OpCode}:");
builder.AppendLine("{");
builder.Indent();
builder.AppendLine($"return {routeTypeInfo.RouteType};");
builder.Unindent();
builder.AppendLine("}");
}
builder.AppendLine("default:");
builder.AppendLine("{");
builder.Indent();
builder.AppendLine($"return null;");
builder.Unindent();
builder.AppendLine("}");
builder.Unindent();
builder.AppendLine("}");
builder.AppendLine();
}
else
{
builder.AppendLine($"return null;");
}
builder.EndMethod();
builder.AppendLine();
// 结束类和命名空间
builder.EndClass();
builder.EndNamespace();
// 输出源代码
context.AddSource("NetworkProtocolOpCodeResolverRegistrar.g.cs", builder.ToString());
}
private static void GenerateNetworkProtocolResponseTypesResolverCode(
SourceProductionContext context,
string assemblyName,
List<NetworkProtocolTypeInfo> networkProtocolTypeInfoList)
{
var requestList = networkProtocolTypeInfoList.Where(d => d.ResponseType != null).ToList();
var builder = new SourceCodeBuilder();
// 添加文件头
builder.AppendLine(GeneratorConstants.AutoGeneratedHeader);
// 添加 using
builder.AddUsings(
"System",
"System.Collections.Generic",
"Fantasy.Assembly",
"Fantasy.DataStructure.Collection",
"System.Runtime.CompilerServices"
);
builder.AppendLine();
// 开始命名空间(固定使用 Fantasy.Generated
builder.BeginNamespace("Fantasy.Generated");
// 开始类定义(实现 IEventSystemRegistrar 接口)
builder.AddXmlComment($"Auto-generated NetworkProtocolResponseTypeResolverRegistrar class for {assemblyName}");
builder.BeginClass("NetworkProtocolResponseTypeResolverRegistrar", "internal sealed", "INetworkProtocolResponseTypeResolver");
builder.AddXmlComment($"GetOpCodeCount");
builder.AppendLine("[MethodImpl(MethodImplOptions.AggressiveInlining)]");
builder.BeginMethod("public int GetRequestCount()");
builder.AppendLine($"return {requestList.Count};");
builder.EndMethod();
// 开始定义GetOpCodeType方法
builder.AddXmlComment($"GetOpCodeType");
builder.AppendLine("[MethodImpl(MethodImplOptions.AggressiveInlining)]");
builder.BeginMethod("public Type GetResponseType(uint opCode)");
if (requestList.Any())
{
builder.AppendLine("switch (opCode)");
builder.AppendLine("{");
builder.Indent();
foreach (var request in requestList)
{
builder.AppendLine($"case {request.OpCode}:");
builder.AppendLine("{");
builder.Indent();
builder.AppendLine($"return typeof({request.ResponseType});");
builder.Unindent();
builder.AppendLine("}");
}
builder.AppendLine("default:");
builder.AppendLine("{");
builder.Indent();
builder.AppendLine($"return null!;");
builder.Unindent();
builder.AppendLine("}");
builder.Unindent();
builder.AppendLine("}");
builder.AppendLine();
}
else
{
builder.AppendLine($"return null!;");
}
builder.EndMethod();
builder.AppendLine();
// 结束类和命名空间
builder.EndClass();
builder.EndNamespace();
// 输出源代码
context.AddSource("NetworkProtocolResponseTypeResolverRegistrar.g.cs", builder.ToString());
}
#endregion
private static NetworkProtocolTypeInfo? GetNetworkProtocolInfo(GeneratorSyntaxContext context)
{
var classDecl = (ClassDeclarationSyntax)context.Node;
var symbol = context.SemanticModel.GetDeclaredSymbol(classDecl) as INamedTypeSymbol;
if (symbol == null || !symbol.IsInstantiable())
{
return null;
}
var baseType = symbol.BaseType;
if (baseType == null)
{
return null;
}
if (baseType.ToDisplayString() != "Fantasy.Network.Interface.AMessage")
{
return null;
}
// 获取 OpCode 方法的值
uint? opCodeValue = null;
var opCodeMethod = symbol.GetMembers("OpCode").OfType<IMethodSymbol>().FirstOrDefault();
var opCodeSyntax = opCodeMethod?.DeclaringSyntaxReferences.FirstOrDefault()?.GetSyntax() as MethodDeclarationSyntax;
if (opCodeSyntax?.Body != null)
{
var returnStatement = opCodeSyntax.Body.DescendantNodes()
.OfType<ReturnStatementSyntax>()
.FirstOrDefault();
if (returnStatement?.Expression != null)
{
var constantValue = context.SemanticModel.GetConstantValue(returnStatement.Expression);
if (constantValue.HasValue && constantValue.Value is uint uintValue)
{
opCodeValue = uintValue;
}
}
}
if (!opCodeValue.HasValue)
{
return null;
}
// 获取 ResponseType 属性及其类型
string? responseTypeName = null;
var responseTypeProperty = symbol.GetMembers("ResponseType").OfType<IPropertySymbol>().FirstOrDefault();
if (responseTypeProperty != null)
{
// 获取 ResponseType 属性的类型(例如 G2C_TestResponse
responseTypeName = responseTypeProperty.Type.GetFullName();
}
// 获取 RouteType 属性的值
int? routeTypeValue = null;
var routeTypeProperty = symbol.GetMembers("RouteType").OfType<IPropertySymbol>().FirstOrDefault();
var routeTypeSyntax = routeTypeProperty?.DeclaringSyntaxReferences.FirstOrDefault()?.GetSyntax() as PropertyDeclarationSyntax;
if (routeTypeSyntax?.ExpressionBody != null)
{
var constantValue = context.SemanticModel.GetConstantValue(routeTypeSyntax.ExpressionBody.Expression);
if (constantValue.HasValue && constantValue.Value is int intValue)
{
routeTypeValue = intValue;
}
}
return new NetworkProtocolTypeInfo(
symbol.GetFullName(),
opCodeValue.Value,
responseTypeName,
routeTypeValue
);
}
private static bool IsNetworkProtocolClass(SyntaxNode node)
{
if (node is not ClassDeclarationSyntax classDecl)
{
return false;
}
if (classDecl.BaseList == null)
{
return false;
}
foreach (var baseTypeSyntax in classDecl.BaseList.Types)
{
if (baseTypeSyntax.Type.ToString().Contains("AMessage"))
{
return true;
}
}
return false;
}
private sealed record NetworkProtocolTypeInfo(
string FullName,
uint OpCode,
string? ResponseType,
int? RouteType);
}

View File

@@ -0,0 +1,267 @@
using Fantasy.SourceGenerator.Common;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using System.Collections.Generic;
using System.Linq;
using System.Text;
// ReSharper disable MemberHidesStaticFromOuterClass
namespace Fantasy.SourceGenerator.Generators
{
/// <summary>
/// SeparateTable 接口生成器
/// 自动生成 SeparateTable 所需的注册代码,替代运行时反射
/// </summary>
[Generator]
public partial class SeparateTableGenerator : IIncrementalGenerator
{
private static readonly SourceCodeBuilder SeparateTableInfo = new SourceCodeBuilder();
public void Initialize(IncrementalGeneratorInitializationContext context)
{
// 查找所有标记了 SeparateTableAttribute 的类
var attributedClasses = context.SyntaxProvider
.CreateSyntaxProvider(
predicate: static (node, _) => IsSeparateTableClass(node),
transform: static (ctx, _) => GetSeparateTableTypeInfo(ctx))
.Where(static info => info != null)
.Collect();
// 组合编译信息和找到的类型
var compilationAndTypes = context.CompilationProvider.Combine(attributedClasses);
// 注册源代码输出
context.RegisterSourceOutput(compilationAndTypes, static (spc, source) =>
{
// 检查1: 是否定义了 FANTASY_NET 预编译符号
if (!CompilationHelper.HasFantasyNETDefine(source.Left))
{
return;
}
// 检查2: 是否引用了 Fantasy 框架的核心类型
if (source.Left.GetTypeByMetadataName("Fantasy.Entitas.Interface.ISupportedSeparateTable") == null)
{
return;
}
GenerateRegistrationCode(spc, source.Left, source.Right!);
});
}
private static SeparateTableTypeInfo? GetSeparateTableTypeInfo(GeneratorSyntaxContext context)
{
var classDecl = (ClassDeclarationSyntax)context.Node;
if (context.SemanticModel.GetDeclaredSymbol(classDecl) is not INamedTypeSymbol symbol)
{
return null;
}
if (!symbol.InheritsFrom("Fantasy.Entitas.Entity"))
{
// 不是 Entity不处理
return null;
}
// 检查是否标记了 SeparateTableAttribute
var separateTableAttr = symbol.GetAttributes()
.Where(attr => attr.AttributeClass?.ToDisplayString() == "Fantasy.SeparateTable.SeparateTableAttribute").ToList();
if (!separateTableAttr.Any())
{
return null;
}
var separateTableInfo = new Dictionary<string, string>();
foreach (var attributeData in separateTableAttr)
{
if (attributeData.ConstructorArguments.Length < 2)
{
return null;
}
var rootTypeSymbol = attributeData.ConstructorArguments[0].Value as INamedTypeSymbol;
var collectionName = attributeData.ConstructorArguments[1].Value?.ToString();
if (rootTypeSymbol == null || collectionName == null)
{
return null;
}
separateTableInfo[rootTypeSymbol.GetFullName()] = collectionName;
}
return separateTableInfo.Any() ? SeparateTableTypeInfo.Create(symbol, separateTableInfo) : null;
}
private static void GenerateRegistrationCode(
SourceProductionContext context,
Compilation compilation,
IEnumerable<SeparateTableTypeInfo> separateTableTypeInfos)
{
SeparateTableInfo.Clear();
var separateTableTypeInfoList = separateTableTypeInfos.ToList();
// 获取当前程序集名称(仅用于注释)
var assemblyName = compilation.AssemblyName ?? "Unknown";
// 生成代码文件
var builder = new SourceCodeBuilder();
// 添加 using
builder.AddUsings(
"System",
"System.Collections.Generic",
"Fantasy.Assembly",
"Fantasy.Entitas",
"Fantasy.Entitas.Interface",
"Fantasy.Async"
);
builder.AppendLine();
// 开始命名空间(固定使用 Fantasy.Generated
builder.BeginNamespace("Fantasy.Generated");
// 开始类定义(实现 IEntitySystemRegistrar 接口)
builder.AddXmlComment($"Auto-generated Entity System registration class for {assemblyName}");
builder.BeginClass("SeparateTableRegistrar", "internal sealed", "ISeparateTableRegistrar");
// 生成字段用于存储已注册(用于 UnRegister
GenerateFields(builder, separateTableTypeInfoList);
// 生成注册方法
GenerateRegisterMethod(builder, separateTableTypeInfoList);
// 生成反注册方法
GenerateUnRegisterMethod(builder, separateTableTypeInfoList);
// 结束类
builder.EndClass();
// 生成数据库帮助类
builder.Append(GenerateGenerateSeparateTableGeneratedExtensions().ToString());
// 结束命名空间
builder.EndNamespace();
// 输出源代码
context.AddSource("SeparateTableRegistrar.g.cs", builder.ToString());
}
private static SourceCodeBuilder GenerateGenerateSeparateTableGeneratedExtensions()
{
var builder = new SourceCodeBuilder();
builder.AppendLine();
builder.Indent(1);
builder.AddXmlComment("分表组件扩展方法。");
builder.AppendLine("public static class SeparateTableGeneratedExtensions");
builder.AppendLine("{");
builder.Indent(1);
builder.AddXmlComment("从数据库加载指定实体的所有分表数据,并自动建立父子关系。");
builder.BeginMethod("public static FTask LoadWithSeparateTables<T>(this T entity) where T : Entity, new()");
builder.AppendLine("return entity.Scene.SeparateTableComponent.LoadWithSeparateTables(entity);");
builder.EndMethod();
builder.AddXmlComment("将实体及其所有分表组件保存到数据库中。");
builder.BeginMethod("public static FTask PersistAggregate<T>(this T entity) where T : Entity, new()");
builder.AppendLine("return entity.Scene.SeparateTableComponent.PersistAggregate(entity);");
builder.EndMethod();
builder.Unindent();
builder.AppendLine("}");
return builder;
}
private static void GenerateFields(SourceCodeBuilder builder, List<SeparateTableTypeInfo> separateTableTypeInfoList)
{
SeparateTableInfo.AppendLine("private readonly List<ISeparateTableRegistrar.SeparateTableInfo> _separateTableInfos = new List<ISeparateTableRegistrar.SeparateTableInfo>()");
SeparateTableInfo.Indent(2);
SeparateTableInfo.AppendLine("{");
SeparateTableInfo.Indent(1);
if (separateTableTypeInfoList.Any())
{
foreach (var separateTableTypeInfo in separateTableTypeInfoList)
{
foreach (var separateTableInfo in separateTableTypeInfo.SeparateTableInfo)
{
SeparateTableInfo.AppendLine(
$"new ISeparateTableRegistrar.SeparateTableInfo(typeof({separateTableInfo.Key}) ,typeof({separateTableTypeInfo.TypeFullName}) ,\"{separateTableInfo.Value}\"),");
}
}
}
SeparateTableInfo.Unindent();
SeparateTableInfo.AppendLine("};");
builder.AppendLine(SeparateTableInfo.ToString());
}
private static void GenerateRegisterMethod(SourceCodeBuilder builder, List<SeparateTableTypeInfo> separateTableTypeInfos)
{
builder.BeginMethod("public List<ISeparateTableRegistrar.SeparateTableInfo> Register()");
builder.AppendLine("return _separateTableInfos;");
builder.EndMethod();
builder.AppendLine();
}
private static void GenerateUnRegisterMethod(SourceCodeBuilder builder, List<SeparateTableTypeInfo> separateTableTypeInfos)
{
builder.BeginMethod("public List<ISeparateTableRegistrar.SeparateTableInfo> UnRegister()");
builder.AppendLine("return _separateTableInfos;");
builder.EndMethod();
builder.AppendLine();
}
private static bool IsSeparateTableClass(SyntaxNode node)
{
if (node is not ClassDeclarationSyntax classDecl)
{
return false;
}
// 快速检查是否有任何 Attribute
if (classDecl.AttributeLists.Count == 0)
{
return false;
}
// 检查是否标记了 SeparateTableAttribute
// 这里只做简单的语法级别检查,精确的语义检查在 GetSeparateTableTypeInfo 中进行
foreach (var attributeList in classDecl.AttributeLists)
{
foreach (var attribute in attributeList.Attributes)
{
var attributeName = attribute.Name.ToString();
// 匹配以下情况:
// 1. [SeparateTable(...)]
// 2. [SeparateTableAttribute(...)]
// 3. [Fantasy.Entitas.Interface.SeparateTable(...)]
// 4. [Fantasy.Entitas.Interface.SeparateTableAttribute(...)]
// 5. [global::Fantasy.Entitas.Interface.SeparateTable(...)]
if (attributeName == "SeparateTable" ||
attributeName == "SeparateTableAttribute" ||
attributeName == "Fantasy.Entitas.Interface.SeparateTable" ||
attributeName == "Fantasy.Entitas.Interface.SeparateTableAttribute" ||
attributeName == "global::Fantasy.Entitas.Interface.SeparateTable" ||
attributeName == "global::Fantasy.Entitas.Interface.SeparateTableAttribute")
{
return true;
}
}
}
return false;
}
private sealed class SeparateTableTypeInfo
{
public readonly Dictionary<string, string> SeparateTableInfo;
public readonly string TypeFullName;
public readonly string TypeName;
private SeparateTableTypeInfo(string typeFullName, string typeName,
Dictionary<string, string> separateTableInfo)
{
TypeFullName = typeFullName;
TypeName = typeName;
SeparateTableInfo = separateTableInfo;
}
public static SeparateTableTypeInfo Create(INamedTypeSymbol symbol,
Dictionary<string, string> separateTableInfo)
{
return new SeparateTableTypeInfo(
symbol.GetFullName(),
symbol.Name,
separateTableInfo);
}
}
}
}