diff --git a/src/BootstrapBlazor.Server/Services/ComponentAttributeCacheService.cs b/src/BootstrapBlazor.Server/Services/ComponentAttributeCacheService.cs index 764a73ed343..9aa35fffdc5 100644 --- a/src/BootstrapBlazor.Server/Services/ComponentAttributeCacheService.cs +++ b/src/BootstrapBlazor.Server/Services/ComponentAttributeCacheService.cs @@ -34,30 +34,23 @@ public static List GetAttributes(Type componentType) private static List GetAttributeCore(Type type) { - var attributes = new List(); var properties = type.GetProperties(BindingFlags.Public | BindingFlags.Instance); // 检查是否为 IComponent 实现类 if (typeof(IComponent).IsAssignableFrom(type)) { - properties = properties - .Where(p => p.GetCustomAttribute() != null) + properties = properties.Where(p => p.GetCustomAttribute() != null) .ToArray(); } var xmlDoc = GetXmlDocumentation(type.Assembly); - foreach (var property in properties) + return properties.Select(property => new AttributeItem { - var item = new AttributeItem - { - Name = property.Name, - Type = GetFriendlyTypeName(property.PropertyType), - Description = GetSummary(xmlDoc, property) ?? "", - Version = GetVersion(xmlDoc, property) ?? "10.0.0" - }; - attributes.Add(item); - } - return attributes.OrderBy(i => i.Name).ToList(); + Name = property.Name, + Type = GetFriendlyTypeName(property.PropertyType), + Description = GetSummary(xmlDoc, property) ?? "", + Version = GetVersion(xmlDoc, property) ?? "10.0.0" + }).OrderBy(i => i.Name).ToList(); } /// @@ -68,37 +61,44 @@ private static List GetAttributeCore(Type type) if (xmlDoc == null) return null; var memberName = $"P:{property.DeclaringType?.FullName}.{property.Name}"; + var summaryElement = FindSummaryElement(xmlDoc, memberName); + return summaryElement == null ? null : GetLocalizedSummary(summaryElement); + } + + private static XElement? FindSummaryElement(XDocument xmlDoc, string memberName) + { var memberElement = xmlDoc.Descendants("member") .FirstOrDefault(x => x.Attribute("name")?.Value == memberName); - if (memberElement == null) return null; + var summaryElement = memberElement?.Element("summary"); + if (summaryElement == null) + { + return null; + } - var summaryElement = memberElement.Element("summary"); - if (summaryElement == null) return null; + var inheritDoc = summaryElement.Element("inheritdoc"); + var cref = inheritDoc?.Attribute("cref")?.Value; + return cref != null ? FindSummaryElement(xmlDoc, cref) : summaryElement; + } - // 获取当前语言(zh-CN -> zh, en-US -> en) - var currentLanguage = CultureInfo.CurrentUICulture.TwoLetterISOLanguageName; + private static string? GetLocalizedSummary(XElement? summaryElement) + { + if (summaryElement == null) + { + return null; + } - // 查找匹配当前语言的 para 元素 + var currentLanguage = CultureInfo.CurrentUICulture.TwoLetterISOLanguageName; var langPara = summaryElement.Elements("para") .FirstOrDefault(p => p.Attribute("lang")?.Value == currentLanguage); - if (langPara != null) { return langPara.Value.Trim(); } - // 如果找不到当前语言,回退到第一个有 lang 属性的 para(通常是 zh) var firstLangPara = summaryElement.Elements("para") .FirstOrDefault(p => p.Attribute("lang") != null); - - if (firstLangPara != null) - { - return firstLangPara.Value.Trim(); - } - - // 如果都没有,返回整个 summary 的文本(向后兼容旧格式) - return summaryElement.Value.Trim(); + return firstLangPara != null ? firstLangPara.Value.Trim() : summaryElement.Value.Trim(); } /// @@ -112,16 +112,13 @@ private static List GetAttributeCore(Type type) var memberElement = xmlDoc.Descendants("member") .FirstOrDefault(x => x.Attribute("name")?.Value == memberName); - if (memberElement == null) return null; - // 在 summary 节点下查找包含 version 的 para 节点 // XML 格式: 10.2.2 - var summaryElement = memberElement.Element("summary"); - if (summaryElement == null) return null; + var summaryElement = memberElement?.Element("summary"); // 查找第一个包含 version 元素的 para // 直接在循环中返回,避免创建中间变量 - return summaryElement.Elements("para") + return summaryElement?.Elements("para") .Select(p => p.Element("version")) .FirstOrDefault(v => v != null) ?.Value.Trim(); @@ -140,6 +137,7 @@ private static string GetFriendlyTypeName(Type type) { genericTypeName = genericTypeName.Substring(0, backtickIndex); } + var genericArgs = string.Join(", ", type.GetGenericArguments().Select(GetFriendlyTypeName)); return $"{genericTypeName}<{genericArgs}>"; }