using Fantasy.SourceGenerator.Common; using Microsoft.CodeAnalysis; namespace Fantasy.SourceGenerator.Generators { /// /// 程序集初始化器生成器 /// 为每个 Fantasy 项目生成 ModuleInitializer,在程序集加载时自动注册到框架 /// 支持 Native AOT,无需运行时反射 /// [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("/// "); builder.AppendLine("/// Call this method to ensure the assembly is loaded"); builder.AppendLine("/// This is useful when loading assemblies dynamically via reflection"); builder.AppendLine("/// "); 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}();"); } } }