From e235fd977d803225818dd5920c91c0605dfdf9d9 Mon Sep 17 00:00:00 2001 From: "J. Ritchie Carroll" Date: Mon, 18 May 2026 19:06:45 -0500 Subject: [PATCH] Added attribute query safety wrappers to accommodate custom attribute constructor signature changes when older encountered adapter references an older signature Old adapter will not be added to cache, but type load error will be safely logged. --- .../Adapters/AdapterCache.cs | 37 ++++++++++++++++--- 1 file changed, 32 insertions(+), 5 deletions(-) diff --git a/src/Gemstone.Timeseries/Adapters/AdapterCache.cs b/src/Gemstone.Timeseries/Adapters/AdapterCache.cs index b4c05011d..878e16e0a 100644 --- a/src/Gemstone.Timeseries/Adapters/AdapterCache.cs +++ b/src/Gemstone.Timeseries/Adapters/AdapterCache.cs @@ -33,6 +33,7 @@ using System.Text.Json.Serialization; using System.Threading; using Gemstone.ComponentModel.DataAnnotations; +using Gemstone.Diagnostics; using Gemstone.EventHandlerExtensions; using Gemstone.StringExtensions; using Gemstone.TypeExtensions; @@ -446,10 +447,10 @@ public static IEnumerable GetConnectionParameters(string as } /// - /// Gets the AdapterProtocol attribute for the protocol acronym. + /// Gets the for the protocol acronym. /// /// - /// Adapter Protocl for the protocol acronym. + /// Adapter protocol attribute for the protocol acronym. public static AdapterProtocolAttribute? GetProtocolAttribute(string acronym) { return AdapterProtocols.Values @@ -568,8 +569,21 @@ public static void ReloadAdapterTypes() internal static IEnumerable<(AdapterInfo info, TAttr[] attributes)> GetAdapterAttributes(this IEnumerable adapters) where TAttr : Attribute { return adapters - .Select(info => (info, attributes: info.Type.GetCustomAttributes().ToArray())) + .Select(info => (info, attributes: safeGetCustomAttributes(info.Type))) .Where(item => item.attributes.Length > 0); + + static TAttr[] safeGetCustomAttributes(Type type) + { + try + { + return type.GetCustomAttributes().ToArray(); + } + catch (Exception ex) + { + Logger.SwallowException(ex, $"Failed to get custom attributes for type '{typeof(TAttr).FullName}'", $"{nameof(AdapterCache)}.{nameof(GetAdapterAttributes)}"); + return []; + } + } } // Gets all adapters grouped with each of its specified attributes for all adapters with methods that are marked with the attribute. @@ -577,14 +591,27 @@ public static void ReloadAdapterTypes() { return adapters.Select(info => (info, methodAttributes: getMethodAttributes(info))); - (MethodInfo, TAttr)[] getMethodAttributes(AdapterInfo info) + static (MethodInfo, TAttr)[] getMethodAttributes(AdapterInfo info) { return info.Type .GetMethods(BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance | BindingFlags.IgnoreCase) - .Select(method => (method, attribute: method.GetCustomAttribute())) + .Select(method => (method, attribute: safeGetCustomMethodAttr(method))) .Where(item => item.attribute is not null) .ToArray()!; } + + static TAttr? safeGetCustomMethodAttr(MethodInfo method) + { + try + { + return method.GetCustomAttribute(); + } + catch (Exception ex) + { + Logger.SwallowException(ex, $"Failed to get custom attribute for method '{method.Name}' of type '{method.DeclaringType?.FullName}'", $"{nameof(AdapterCache)}.{nameof(GetAdapterMethodAttributes)}"); + return null; + } + } } // Gets all adapters filtered by editor browsable state.