From 24a348466812e97a2e2cbe49a44138bb87021283 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=88=E6=80=9D=E6=B5=B7?= <1464576565@qq.com> Date: Mon, 23 Mar 2026 14:45:55 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1.移除了旧的冗余生成接口 2.编辑器更定制的细致化UI生成接口 3.接口开放给其它包继承生成 --- .../GenerateWindow/UISettingEditorWindow.cs | 150 +++++++++++--- Editor/UI/Helper/IUIGeneratorRuleHelper.cs | 114 ----------- .../UI/Helper/IUIGeneratorRuleHelper.cs.meta | 3 - Editor/UI/Helper/UIGeneratorRuleServices.cs | 16 +- Editor/UI/Helper/UIScriptGeneratorHelper.cs | 191 +++++++++++------- Editor/UI/UIConfig/UIGenerateConfiguration.cs | 12 +- 6 files changed, 257 insertions(+), 229 deletions(-) delete mode 100644 Editor/UI/Helper/IUIGeneratorRuleHelper.cs delete mode 100644 Editor/UI/Helper/IUIGeneratorRuleHelper.cs.meta diff --git a/Editor/UI/GenerateWindow/UISettingEditorWindow.cs b/Editor/UI/GenerateWindow/UISettingEditorWindow.cs index e34655c..532a9b9 100644 --- a/Editor/UI/GenerateWindow/UISettingEditorWindow.cs +++ b/Editor/UI/GenerateWindow/UISettingEditorWindow.cs @@ -31,7 +31,10 @@ namespace AlicizaX.UI.Editor private SerializedProperty commonDataProperty; private SerializedProperty regexConfigsProperty; private SerializedProperty scriptGenerateConfigsProperty; - private SerializedProperty generatorRuleHelperProperty; + private SerializedProperty identifierFormatterTypeProperty; + private SerializedProperty resourcePathResolverTypeProperty; + private SerializedProperty scriptCodeEmitterTypeProperty; + private SerializedProperty scriptFileWriterTypeProperty; private SerializedProperty excludeKeywordsProperty; private ReorderableList regexList; @@ -43,14 +46,20 @@ namespace AlicizaX.UI.Editor private TextAsset importText; private string previewLabel; private string previewCompLabel; - private List scriptGeneratorHelperTypes = new(); - private int scriptGeneratorHelperSelectIndex; + private List identifierFormatterTypes = new(); + private List resourcePathResolverTypes = new(); + private List scriptCodeEmitterTypes = new(); + private List scriptFileWriterTypes = new(); + private int identifierFormatterSelectIndex; + private int resourcePathResolverSelectIndex; + private int scriptCodeEmitterSelectIndex; + private int scriptFileWriterSelectIndex; private void OnEnable() { BindConfiguration(); SetupLists(); - RefreshScriptGeneratorHelperTypes(); + RefreshGeneratorServiceTypes(); RefreshPreview(); } @@ -76,7 +85,10 @@ namespace AlicizaX.UI.Editor commonDataProperty = serializedConfig.FindProperty(nameof(UIGenerateConfiguration.UIGenerateCommonData)); regexConfigsProperty = serializedConfig.FindProperty(nameof(UIGenerateConfiguration.UIElementRegexConfigs)); scriptGenerateConfigsProperty = serializedConfig.FindProperty(nameof(UIGenerateConfiguration.UIScriptGenerateConfigs)); - generatorRuleHelperProperty = serializedConfig.FindProperty(nameof(UIGenerateConfiguration.UIScriptGeneratorRuleHelper)); + identifierFormatterTypeProperty = serializedConfig.FindProperty(nameof(UIGenerateConfiguration.UIIdentifierFormatterTypeName)); + resourcePathResolverTypeProperty = serializedConfig.FindProperty(nameof(UIGenerateConfiguration.UIResourcePathResolverTypeName)); + scriptCodeEmitterTypeProperty = serializedConfig.FindProperty(nameof(UIGenerateConfiguration.UIScriptCodeEmitterTypeName)); + scriptFileWriterTypeProperty = serializedConfig.FindProperty(nameof(UIGenerateConfiguration.UIScriptFileWriterTypeName)); excludeKeywordsProperty = commonDataProperty?.FindPropertyRelative(nameof(UIGenerateCommonData.ExcludeKeywords)); } @@ -256,7 +268,7 @@ namespace AlicizaX.UI.Editor { BindConfiguration(); SetupLists(); - RefreshScriptGeneratorHelperTypes(); + RefreshGeneratorServiceTypes(); RefreshPreview(); } @@ -333,33 +345,44 @@ namespace AlicizaX.UI.Editor private void DrawCommonPane() { EditorGUILayout.BeginVertical("box"); - EditorGUILayout.LabelField("General Generation Settings", EditorStyles.boldLabel); - EditorGUILayout.Space(4f); EditorGUILayout.PropertyField( commonDataProperty.FindPropertyRelative(nameof(UIGenerateCommonData.ComCheckSplitName)), - new GUIContent("Component Split", "Example: Button#Close")); + new GUIContent("组件分割符", "例如: Button#Close")); EditorGUILayout.PropertyField( commonDataProperty.FindPropertyRelative(nameof(UIGenerateCommonData.ComCheckEndName)), - new GUIContent("Component End", "Example: @End")); + new GUIContent("组件结尾符", "例如: @End")); EditorGUILayout.PropertyField( commonDataProperty.FindPropertyRelative(nameof(UIGenerateCommonData.ArrayComSplitName)), - new GUIContent("Array Split", "Example: *Item")); + new GUIContent("数组分割", "例如: *Item")); EditorGUILayout.PropertyField( commonDataProperty.FindPropertyRelative(nameof(UIGenerateCommonData.GeneratePrefix)), - new GUIContent("Generate Prefix")); + new GUIContent("生成脚本前缀")); - int nextIndex = EditorGUILayout.Popup( - "Generator Rule Helper", - scriptGeneratorHelperSelectIndex, - scriptGeneratorHelperTypes.ToArray()); - if (nextIndex != scriptGeneratorHelperSelectIndex && - nextIndex >= 0 && - nextIndex < scriptGeneratorHelperTypes.Count) - { - scriptGeneratorHelperSelectIndex = nextIndex; - generatorRuleHelperProperty.stringValue = scriptGeneratorHelperTypes[nextIndex]; - } + DrawTypePopup( + "Identifier Formatter", + identifierFormatterTypeProperty, + identifierFormatterTypes, + ref identifierFormatterSelectIndex, + typeof(DefaultUIIdentifierFormatter).FullName); + DrawTypePopup( + "Resource Path Resolver", + resourcePathResolverTypeProperty, + resourcePathResolverTypes, + ref resourcePathResolverSelectIndex, + typeof(DefaultUIResourcePathResolver).FullName); + DrawTypePopup( + "Script Code Emitter", + scriptCodeEmitterTypeProperty, + scriptCodeEmitterTypes, + ref scriptCodeEmitterSelectIndex, + typeof(DefaultUIScriptCodeEmitter).FullName); + DrawTypePopup( + "Script File Writer", + scriptFileWriterTypeProperty, + scriptFileWriterTypes, + ref scriptFileWriterSelectIndex, + typeof(DefaultUIScriptFileWriter).FullName); GUILayout.Space(8f); excludeList.DoLayoutList(); @@ -460,26 +483,87 @@ namespace AlicizaX.UI.Editor ApplyConfigChanges(); } - private void RefreshScriptGeneratorHelperTypes() + private void RefreshGeneratorServiceTypes() { - scriptGeneratorHelperTypes = AlicizaX.Utility.Assembly - .GetRuntimeTypeNames(typeof(IUIGeneratorRuleHelper)) + RefreshTypeOptions( + typeof(IUIIdentifierFormatter), + identifierFormatterTypeProperty, + typeof(DefaultUIIdentifierFormatter).FullName, + ref identifierFormatterTypes, + ref identifierFormatterSelectIndex); + RefreshTypeOptions( + typeof(IUIResourcePathResolver), + resourcePathResolverTypeProperty, + typeof(DefaultUIResourcePathResolver).FullName, + ref resourcePathResolverTypes, + ref resourcePathResolverSelectIndex); + RefreshTypeOptions( + typeof(IUIScriptCodeEmitter), + scriptCodeEmitterTypeProperty, + typeof(DefaultUIScriptCodeEmitter).FullName, + ref scriptCodeEmitterTypes, + ref scriptCodeEmitterSelectIndex); + RefreshTypeOptions( + typeof(IUIScriptFileWriter), + scriptFileWriterTypeProperty, + typeof(DefaultUIScriptFileWriter).FullName, + ref scriptFileWriterTypes, + ref scriptFileWriterSelectIndex); + } + + private static void RefreshTypeOptions( + Type interfaceType, + SerializedProperty property, + string defaultTypeName, + ref List options, + ref int selectedIndex) + { + options = AlicizaX.Utility.Assembly + .GetRuntimeTypeNames(interfaceType) .Distinct(StringComparer.Ordinal) .OrderBy(typeName => typeName, StringComparer.Ordinal) .ToList(); - if (scriptGeneratorHelperTypes.Count == 0) + if (!options.Contains(defaultTypeName)) { - scriptGeneratorHelperTypes.Add(typeof(DefaultUIGeneratorRuleHelper).FullName); + options.Insert(0, defaultTypeName); } - string currentType = generatorRuleHelperProperty?.stringValue; - if (!string.IsNullOrEmpty(currentType) && !scriptGeneratorHelperTypes.Contains(currentType)) + string currentType = string.IsNullOrWhiteSpace(property?.stringValue) ? defaultTypeName : property.stringValue; + if (!string.IsNullOrEmpty(currentType) && !options.Contains(currentType)) { - scriptGeneratorHelperTypes.Insert(0, currentType); + options.Insert(0, currentType); } - scriptGeneratorHelperSelectIndex = Mathf.Max(0, scriptGeneratorHelperTypes.IndexOf(currentType)); + selectedIndex = Mathf.Max(0, options.IndexOf(currentType)); + } + + private static void DrawTypePopup( + string label, + SerializedProperty property, + List options, + ref int selectedIndex, + string defaultTypeName) + { + if (property == null || options == null || options.Count == 0) + { + return; + } + + int currentIndex = selectedIndex; + if (currentIndex < 0 || currentIndex >= options.Count) + { + string currentType = string.IsNullOrWhiteSpace(property.stringValue) ? defaultTypeName : property.stringValue; + currentIndex = Mathf.Max(0, options.IndexOf(currentType)); + selectedIndex = currentIndex; + } + + int nextIndex = EditorGUILayout.Popup(label, currentIndex, options.ToArray()); + if (nextIndex >= 0 && nextIndex < options.Count && nextIndex != currentIndex) + { + selectedIndex = nextIndex; + property.stringValue = options[nextIndex]; + } } private List CollectComponentTypeNamesFallback() @@ -596,7 +680,7 @@ namespace AlicizaX.UI.Editor { BindConfiguration(); SetupLists(); - RefreshScriptGeneratorHelperTypes(); + RefreshGeneratorServiceTypes(); RefreshPreview(); Repaint(); } diff --git a/Editor/UI/Helper/IUIGeneratorRuleHelper.cs b/Editor/UI/Helper/IUIGeneratorRuleHelper.cs deleted file mode 100644 index a7ec723..0000000 --- a/Editor/UI/Helper/IUIGeneratorRuleHelper.cs +++ /dev/null @@ -1,114 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using AlicizaX.UI.Runtime; -using UnityEngine; - -namespace AlicizaX.UI.Editor -{ - internal interface IContextualUIGeneratorRuleHelper - { - string GetClassGenerateName(UIGenerationContext context); - - string GetUIResourceSavePath(UIGenerationContext context); - - bool CheckCanGenerate(UIGenerationContext context); - - string GetReferenceNamespace(UIGenerationContext context); - - string GetVariableContent(UIGenerationContext context); - - void WriteUIScriptContent(UIGenerationContext context, string scriptContent); - } - - public interface IUIGeneratorRuleHelper - { - string GetPrivateComponentByNameRule(string regexName, string componetName, EBindType bindType); - - string GetPublicComponentByNameRule(string variableName); - - string GetClassGenerateName(GameObject targetObject, UIScriptGenerateData scriptGenerateData); - - string GetUIResourceSavePath(GameObject targetObject, UIScriptGenerateData scriptGenerateData); - - void WriteUIScriptContent(GameObject targetObject, string className, string scriptContent, UIScriptGenerateData scriptGenerateData); - - bool CheckCanGenerate(GameObject targetObject, UIScriptGenerateData scriptGenerateData); - - string GetReferenceNamespace(List uiBindDatas); - - string GetVariableContent(List uiBindDatas); - } - - - public class DefaultUIGeneratorRuleHelper : IUIGeneratorRuleHelper, IContextualUIGeneratorRuleHelper - { - private readonly IUIIdentifierFormatter _identifierFormatter; - private readonly IUIResourcePathResolver _resourcePathResolver; - private readonly IUIScriptCodeEmitter _scriptCodeEmitter; - private readonly IUIScriptFileWriter _scriptFileWriter; - - public DefaultUIGeneratorRuleHelper() - : this( - new DefaultUIIdentifierFormatter(), - new DefaultUIResourcePathResolver(), - new DefaultUIScriptCodeEmitter(), - new DefaultUIScriptFileWriter()) - { - } - - internal DefaultUIGeneratorRuleHelper( - IUIIdentifierFormatter identifierFormatter, - IUIResourcePathResolver resourcePathResolver, - IUIScriptCodeEmitter scriptCodeEmitter, - IUIScriptFileWriter scriptFileWriter) - { - _identifierFormatter = identifierFormatter ?? throw new ArgumentNullException(nameof(identifierFormatter)); - _resourcePathResolver = resourcePathResolver ?? throw new ArgumentNullException(nameof(resourcePathResolver)); - _scriptCodeEmitter = scriptCodeEmitter ?? throw new ArgumentNullException(nameof(scriptCodeEmitter)); - _scriptFileWriter = scriptFileWriter ?? throw new ArgumentNullException(nameof(scriptFileWriter)); - } - - public string GetPrivateComponentByNameRule(string regexName, string componentName, EBindType bindType) - => _identifierFormatter.GetPrivateComponentName(regexName, componentName, bindType); - - public string GetPublicComponentByNameRule(string variableName) - => _identifierFormatter.GetPublicComponentName(variableName); - - public string GetClassGenerateName(GameObject targetObject, UIScriptGenerateData scriptGenerateData) - => _identifierFormatter.GetClassName(targetObject); - - string IContextualUIGeneratorRuleHelper.GetClassGenerateName(UIGenerationContext context) - => _identifierFormatter.GetClassName(context.TargetObject); - - public string GetUIResourceSavePath(GameObject targetObject, UIScriptGenerateData scriptGenerateData) - => _resourcePathResolver.GetResourcePath(targetObject, scriptGenerateData); - - string IContextualUIGeneratorRuleHelper.GetUIResourceSavePath(UIGenerationContext context) - => _resourcePathResolver.GetResourcePath(context.TargetObject, context.ScriptGenerateData); - - public void WriteUIScriptContent(GameObject targetObject, string className, string scriptContent, UIScriptGenerateData scriptGenerateData) - => _scriptFileWriter.Write(targetObject, className, scriptContent, scriptGenerateData); - - void IContextualUIGeneratorRuleHelper.WriteUIScriptContent(UIGenerationContext context, string scriptContent) - => _scriptFileWriter.Write(context.TargetObject, context.ClassName, scriptContent, context.ScriptGenerateData); - - public bool CheckCanGenerate(GameObject targetObject, UIScriptGenerateData scriptGenerateData) - => _resourcePathResolver.CanGenerate(targetObject, scriptGenerateData); - - bool IContextualUIGeneratorRuleHelper.CheckCanGenerate(UIGenerationContext context) - => _resourcePathResolver.CanGenerate(context.TargetObject, context.ScriptGenerateData); - - public string GetReferenceNamespace(List uiBindDatas) - => _scriptCodeEmitter.GetReferenceNamespaces(uiBindDatas); - - string IContextualUIGeneratorRuleHelper.GetReferenceNamespace(UIGenerationContext context) - => _scriptCodeEmitter.GetReferenceNamespaces(context.BindDatas?.ToList()); - - public string GetVariableContent(List uiBindDatas) - => _scriptCodeEmitter.GetVariableContent(uiBindDatas, GetPublicComponentByNameRule); - - string IContextualUIGeneratorRuleHelper.GetVariableContent(UIGenerationContext context) - => _scriptCodeEmitter.GetVariableContent(context.BindDatas?.ToList(), GetPublicComponentByNameRule); - } -} diff --git a/Editor/UI/Helper/IUIGeneratorRuleHelper.cs.meta b/Editor/UI/Helper/IUIGeneratorRuleHelper.cs.meta deleted file mode 100644 index 277a8db..0000000 --- a/Editor/UI/Helper/IUIGeneratorRuleHelper.cs.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: 2df48f035545426a83a384df3411755a -timeCreated: 1762516569 \ No newline at end of file diff --git a/Editor/UI/Helper/UIGeneratorRuleServices.cs b/Editor/UI/Helper/UIGeneratorRuleServices.cs index d1a4c27..d793cc7 100644 --- a/Editor/UI/Helper/UIGeneratorRuleServices.cs +++ b/Editor/UI/Helper/UIGeneratorRuleServices.cs @@ -10,7 +10,7 @@ using UnityEngine; namespace AlicizaX.UI.Editor { - internal interface IUIIdentifierFormatter + public interface IUIIdentifierFormatter { string GetPrivateComponentName(string regexName, string componentName, EBindType bindType); @@ -19,26 +19,26 @@ namespace AlicizaX.UI.Editor string GetClassName(GameObject targetObject); } - internal interface IUIResourcePathResolver + public interface IUIResourcePathResolver { string GetResourcePath(GameObject targetObject, UIScriptGenerateData scriptGenerateData); bool CanGenerate(GameObject targetObject, UIScriptGenerateData scriptGenerateData); } - internal interface IUIScriptCodeEmitter + public interface IUIScriptCodeEmitter { string GetReferenceNamespaces(List uiBindDatas); string GetVariableContent(List uiBindDatas, Func publicNameFactory); } - internal interface IUIScriptFileWriter + public interface IUIScriptFileWriter { void Write(GameObject targetObject, string className, string scriptContent, UIScriptGenerateData scriptGenerateData); } - internal sealed class DefaultUIIdentifierFormatter : IUIIdentifierFormatter + public sealed class DefaultUIIdentifierFormatter : IUIIdentifierFormatter { private static readonly HashSet CSharpKeywords = new HashSet(StringComparer.Ordinal) { @@ -138,7 +138,7 @@ namespace AlicizaX.UI.Editor } } - internal sealed class DefaultUIResourcePathResolver : IUIResourcePathResolver + public sealed class DefaultUIResourcePathResolver : IUIResourcePathResolver { public string GetResourcePath(GameObject targetObject, UIScriptGenerateData scriptGenerateData) { @@ -244,7 +244,7 @@ namespace AlicizaX.UI.Editor } } - internal sealed class DefaultUIScriptCodeEmitter : IUIScriptCodeEmitter + public sealed class DefaultUIScriptCodeEmitter : IUIScriptCodeEmitter { public string GetReferenceNamespaces(List uiBindDatas) { @@ -305,7 +305,7 @@ namespace AlicizaX.UI.Editor } } - internal sealed class DefaultUIScriptFileWriter : IUIScriptFileWriter + public sealed class DefaultUIScriptFileWriter : IUIScriptFileWriter { public void Write(GameObject targetObject, string className, string scriptContent, UIScriptGenerateData scriptGenerateData) { diff --git a/Editor/UI/Helper/UIScriptGeneratorHelper.cs b/Editor/UI/Helper/UIScriptGeneratorHelper.cs index 798b927..eb04069 100644 --- a/Editor/UI/Helper/UIScriptGeneratorHelper.cs +++ b/Editor/UI/Helper/UIScriptGeneratorHelper.cs @@ -60,56 +60,93 @@ namespace AlicizaX.UI.Editor private const string GenerateInstanceIdKey = "AlicizaX.UI.Generate.InstanceId"; private const string GenerateAssetPathKey = "AlicizaX.UI.Generate.AssetPath"; private static UIGenerateConfiguration _uiGenerateConfiguration; - private static IUIGeneratorRuleHelper _uiGeneratorRuleHelper; + private static IUIIdentifierFormatter _identifierFormatter; + private static IUIResourcePathResolver _resourcePathResolver; + private static IUIScriptCodeEmitter _scriptCodeEmitter; + private static IUIScriptFileWriter _scriptFileWriter; private static readonly List _uiBindDatas = new List(); private static readonly HashSet _arrayComponents = new HashSet(StringComparer.Ordinal); private static readonly Dictionary _componentTypeCache = new Dictionary(StringComparer.Ordinal); - private static IUIGeneratorRuleHelper UIGeneratorRuleHelper - { - get - { - var configuredHelperTypeName = string.IsNullOrWhiteSpace(UIConfiguration.UIScriptGeneratorRuleHelper) - ? typeof(DefaultUIGeneratorRuleHelper).FullName - : UIConfiguration.UIScriptGeneratorRuleHelper; - - if (_uiGeneratorRuleHelper == null || _uiGeneratorRuleHelper.GetType().FullName != configuredHelperTypeName) - { - InitializeRuleHelper(); - } - - return _uiGeneratorRuleHelper; - } - } - - private static IContextualUIGeneratorRuleHelper ContextualUIGeneratorRuleHelper => - UIGeneratorRuleHelper as IContextualUIGeneratorRuleHelper; - private static UIGenerateConfiguration UIConfiguration => _uiGenerateConfiguration ??= UIGenerateConfiguration.Instance; - private static IUIGeneratorRuleHelper InitializeRuleHelper() + private static IUIIdentifierFormatter IdentifierFormatter => + ResolveConfiguredService( + ref _identifierFormatter, + UIConfiguration.UIIdentifierFormatterTypeName, + typeof(DefaultUIIdentifierFormatter), + nameof(IUIIdentifierFormatter)); + + private static IUIResourcePathResolver ResourcePathResolver => + ResolveConfiguredService( + ref _resourcePathResolver, + UIConfiguration.UIResourcePathResolverTypeName, + typeof(DefaultUIResourcePathResolver), + nameof(IUIResourcePathResolver)); + + private static IUIScriptCodeEmitter ScriptCodeEmitter => + ResolveConfiguredService( + ref _scriptCodeEmitter, + UIConfiguration.UIScriptCodeEmitterTypeName, + typeof(DefaultUIScriptCodeEmitter), + nameof(IUIScriptCodeEmitter)); + + private static IUIScriptFileWriter ScriptFileWriter => + ResolveConfiguredService( + ref _scriptFileWriter, + UIConfiguration.UIScriptFileWriterTypeName, + typeof(DefaultUIScriptFileWriter), + nameof(IUIScriptFileWriter)); + + private static T ResolveConfiguredService(ref T cachedService, string configuredTypeName, Type defaultType, string serviceName) + where T : class { - var ruleHelperTypeName = UIConfiguration.UIScriptGeneratorRuleHelper; - if (string.IsNullOrWhiteSpace(ruleHelperTypeName)) + var resolvedTypeName = string.IsNullOrWhiteSpace(configuredTypeName) ? defaultType.FullName : configuredTypeName; + if (cachedService != null && cachedService.GetType().FullName == resolvedTypeName) { - ruleHelperTypeName = typeof(DefaultUIGeneratorRuleHelper).FullName; + return cachedService; } - var ruleHelperType = AlicizaX.Utility.Assembly.GetType(ruleHelperTypeName); - if (ruleHelperType == null) + var configuredType = AlicizaX.Utility.Assembly.GetType(resolvedTypeName); + if (configuredType == null || !typeof(T).IsAssignableFrom(configuredType)) { - Debug.LogError($"UIScriptGeneratorHelper: Could not load UI ScriptGeneratorHelper {ruleHelperTypeName}"); - return null; + if (!string.Equals(resolvedTypeName, defaultType.FullName, StringComparison.Ordinal)) + { + Debug.LogError( + $"UIScriptGeneratorHelper: Could not load {serviceName} type '{resolvedTypeName}'. Falling back to {defaultType.FullName}."); + } + + configuredType = defaultType; } - _uiGeneratorRuleHelper = Activator.CreateInstance(ruleHelperType) as IUIGeneratorRuleHelper; - if (_uiGeneratorRuleHelper == null) + cachedService = Activator.CreateInstance(configuredType, true) as T; + if (cachedService != null) { - Debug.LogError($"UIScriptGeneratorHelper: Failed to instantiate {ruleHelperTypeName} as IUIGeneratorRuleHelper."); + return cachedService; } - return _uiGeneratorRuleHelper; + if (configuredType != defaultType) + { + Debug.LogError( + $"UIScriptGeneratorHelper: Failed to instantiate {resolvedTypeName} as {serviceName}. Falling back to {defaultType.FullName}."); + cachedService = Activator.CreateInstance(defaultType, true) as T; + } + + if (cachedService == null) + { + Debug.LogError($"UIScriptGeneratorHelper: Failed to instantiate fallback {defaultType.FullName} as {serviceName}."); + } + + return cachedService; + } + + private static bool EnsureGenerationStrategyReady() + { + return IdentifierFormatter != null && + ResourcePathResolver != null && + ScriptCodeEmitter != null && + ScriptFileWriter != null; } private static Type ResolveUIElementComponentType(string uiName) @@ -275,7 +312,7 @@ namespace AlicizaX.UI.Editor continue; } - var keyName = UIGeneratorRuleHelper.GetPrivateComponentByNameRule(com, node.name, EBindType.None); + var keyName = GetPrivateComponentName(com, node.name, EBindType.None); if (_uiBindDatas.Exists(data => data.Name == keyName)) { Debug.LogError($"Duplicate key found: {keyName}"); @@ -305,7 +342,7 @@ namespace AlicizaX.UI.Editor return; } - var keyName = UIGeneratorRuleHelper.GetPrivateComponentByNameRule(string.Empty, node.name, EBindType.Widget); + var keyName = GetPrivateComponentName(string.Empty, node.name, EBindType.Widget); if (_uiBindDatas.Exists(data => data.Name == keyName)) { Debug.LogError($"Duplicate key found: {keyName}"); @@ -347,7 +384,7 @@ namespace AlicizaX.UI.Editor { return componentArray.Select(com => { - var keyName = UIGeneratorRuleHelper.GetPrivateComponentByNameRule(com, nodeName, EBindType.ListCom); + var keyName = GetPrivateComponentName(com, nodeName, EBindType.ListCom); return new UIBindData(keyName, new List(), null, EBindType.ListCom); }).ToList(); } @@ -427,8 +464,7 @@ namespace AlicizaX.UI.Editor return; } - var ruleHelper = UIGeneratorRuleHelper; - if (ruleHelper == null) + if (!EnsureGenerationStrategyReady()) { return; } @@ -439,10 +475,10 @@ namespace AlicizaX.UI.Editor var generationContext = new UIGenerationContext(targetObject, scriptGenerateData, _uiBindDatas) { AssetPath = UIGenerateQuick.GetPrefabAssetPath(targetObject), - ClassName = GetClassGenerateName(ruleHelper, targetObject, scriptGenerateData) + ClassName = GetClassGenerateName(targetObject, scriptGenerateData) }; - if (!CheckCanGenerate(ruleHelper, generationContext)) + if (!CheckCanGenerate(generationContext)) { CleanupContext(); return; @@ -456,7 +492,7 @@ namespace AlicizaX.UI.Editor return; } - GenerateScript(generationContext, ruleHelper); + GenerateScript(generationContext); } private static void InitializeGenerationContext(GameObject targetObject) @@ -498,50 +534,63 @@ namespace AlicizaX.UI.Editor return UIGenerationValidationResult.Success(); } - private static void GenerateScript(UIGenerationContext context, IUIGeneratorRuleHelper ruleHelper) + private static void GenerateScript(UIGenerationContext context) { var templateText = File.ReadAllText(UIGlobalPath.TemplatePath); - var processedText = ProcessTemplateText(context, templateText, ruleHelper); + var processedText = ProcessTemplateText(context, templateText); EditorPrefs.SetString(GenerateTypeNameKey, context.FullTypeName); - if (ContextualUIGeneratorRuleHelper != null) - { - ContextualUIGeneratorRuleHelper.WriteUIScriptContent(context, processedText); - return; - } - - ruleHelper.WriteUIScriptContent(context.TargetObject, context.ClassName, processedText, context.ScriptGenerateData); + WriteScriptContent(context, processedText); } - private static string ProcessTemplateText(UIGenerationContext context, string templateText, IUIGeneratorRuleHelper ruleHelper) + private static string ProcessTemplateText(UIGenerationContext context, string templateText) { - var contextualRuleHelper = ContextualUIGeneratorRuleHelper; return templateText - .Replace("#ReferenceNameSpace#", contextualRuleHelper != null ? contextualRuleHelper.GetReferenceNamespace(context) : ruleHelper.GetReferenceNamespace(_uiBindDatas)) + .Replace("#ReferenceNameSpace#", GetReferenceNamespace(context)) .Replace("#ClassNameSpace#", context.ScriptGenerateData.NameSpace) .Replace("#ClassName#", context.ClassName) - .Replace("#TagName#", contextualRuleHelper != null ? contextualRuleHelper.GetUIResourceSavePath(context) : ruleHelper.GetUIResourceSavePath(context.TargetObject, context.ScriptGenerateData)) + .Replace("#TagName#", GetResourceSavePath(context)) .Replace("#LoadType#", context.ScriptGenerateData.LoadType.ToString()) - .Replace("#Variable#", contextualRuleHelper != null ? contextualRuleHelper.GetVariableContent(context) : ruleHelper.GetVariableContent(_uiBindDatas)); + .Replace("#Variable#", GetVariableContent(context)); } - private static string GetClassGenerateName(IUIGeneratorRuleHelper ruleHelper, GameObject targetObject, UIScriptGenerateData scriptGenerateData) + private static string GetClassGenerateName(GameObject targetObject, UIScriptGenerateData scriptGenerateData) { - if (ContextualUIGeneratorRuleHelper != null) - { - return ContextualUIGeneratorRuleHelper.GetClassGenerateName(new UIGenerationContext(targetObject, scriptGenerateData, _uiBindDatas)); - } - - return ruleHelper.GetClassGenerateName(targetObject, scriptGenerateData); + return IdentifierFormatter.GetClassName(targetObject); } - private static bool CheckCanGenerate(IUIGeneratorRuleHelper ruleHelper, UIGenerationContext context) + private static bool CheckCanGenerate(UIGenerationContext context) { - if (ContextualUIGeneratorRuleHelper != null) - { - return ContextualUIGeneratorRuleHelper.CheckCanGenerate(context); - } + return ResourcePathResolver.CanGenerate(context.TargetObject, context.ScriptGenerateData); + } - return ruleHelper.CheckCanGenerate(context.TargetObject, context.ScriptGenerateData); + private static string GetPrivateComponentName(string regexName, string componentName, EBindType bindType) + { + return IdentifierFormatter.GetPrivateComponentName(regexName, componentName, bindType); + } + + private static string GetPublicComponentName(string variableName) + { + return IdentifierFormatter.GetPublicComponentName(variableName); + } + + private static string GetResourceSavePath(UIGenerationContext context) + { + return ResourcePathResolver.GetResourcePath(context.TargetObject, context.ScriptGenerateData); + } + + private static string GetReferenceNamespace(UIGenerationContext context) + { + return ScriptCodeEmitter.GetReferenceNamespaces(_uiBindDatas); + } + + private static string GetVariableContent(UIGenerationContext context) + { + return ScriptCodeEmitter.GetVariableContent(_uiBindDatas, GetPublicComponentName); + } + + private static void WriteScriptContent(UIGenerationContext context, string scriptContent) + { + ScriptFileWriter.Write(context.TargetObject, context.ClassName, scriptContent, context.ScriptGenerateData); } [DidReloadScripts] @@ -559,6 +608,12 @@ namespace AlicizaX.UI.Editor return; } + if (!EnsureGenerationStrategyReady()) + { + CleanupContext(); + return; + } + _uiBindDatas.Clear(); _arrayComponents.Clear(); diff --git a/Editor/UI/UIConfig/UIGenerateConfiguration.cs b/Editor/UI/UIConfig/UIGenerateConfiguration.cs index dad99db..98aede5 100644 --- a/Editor/UI/UIConfig/UIGenerateConfiguration.cs +++ b/Editor/UI/UIConfig/UIGenerateConfiguration.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using AlicizaX.UI.Runtime; using UnityEngine; @@ -14,13 +14,19 @@ namespace AlicizaX.UI.Editor [Header("UI脚本生成配置(支持多个项目)")] public List UIScriptGenerateConfigs = new List(); - [Header("UI脚本生成辅助类")] public string UIScriptGeneratorRuleHelper; + [Header("UI脚本生成辅助类")] public string UIIdentifierFormatterTypeName; + + public string UIResourcePathResolverTypeName; + + public string UIScriptCodeEmitterTypeName; + + public string UIScriptFileWriterTypeName; } [Serializable] public class UIGenerateCommonData { - [Header("命名规则")] [Tooltip("组件检查分隔符,例如:Button#Close")] + [Tooltip("组件检查分隔符,例如:Button#Close")] public string ComCheckSplitName = "#"; [Tooltip("组件结尾分隔符,例如:@End")] public string ComCheckEndName = "@";