diff --git a/src/WinRT.Runtime/ComWrappersSupport.cs b/src/WinRT.Runtime/ComWrappersSupport.cs index 67c20c0bd..43d61e637 100644 --- a/src/WinRT.Runtime/ComWrappersSupport.cs +++ b/src/WinRT.Runtime/ComWrappersSupport.cs @@ -264,13 +264,8 @@ internal static Func CreateTypedRcwFactory(string runtimeC return (IInspectable obj) => new ABI.System.Nullable(obj.ObjRef); } - Type implementationType = null; - - try - { - (implementationType, _) = TypeNameSupport.FindTypeByName(runtimeClassName.AsSpan()); - } - catch (TypeLoadException) + Type implementationType = TypeNameSupport.FindTypeByNameCached(runtimeClassName); + if(implementationType == null) { // If we reach here, then we couldn't find a type that matches the runtime class name. // Fall back to using IInspectable directly. @@ -318,13 +313,7 @@ internal static string GetRuntimeClassForTypeCreation(IInspectable inspectable, Type implementationType = null; if (!string.IsNullOrEmpty(runtimeClassName)) { - try - { - (implementationType, _) = TypeNameSupport.FindTypeByName(runtimeClassName.AsSpan()); - } - catch (TypeLoadException) - { - } + implementationType = TypeNameSupport.FindTypeByNameCached(runtimeClassName); } if (!(implementationType != null && diff --git a/src/WinRT.Runtime/TypeNameSupport.cs b/src/WinRT.Runtime/TypeNameSupport.cs index 3e1dcac4b..be8e863a3 100644 --- a/src/WinRT.Runtime/TypeNameSupport.cs +++ b/src/WinRT.Runtime/TypeNameSupport.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Concurrent; using System.Collections.Generic; using System.Diagnostics; using System.Linq; @@ -25,12 +26,34 @@ enum TypeNameGenerationFlags static class TypeNameSupport { private static List projectionAssemblies = new List(); + private static ConcurrentDictionary typeNameCache = new ConcurrentDictionary() { ["TrackerCollection"] = null }; public static void RegisterProjectionAssembly(Assembly assembly) { projectionAssemblies.Add(assembly); } + /// + /// Parses and loads the given type name, if not found in the cache. + /// + /// The runtime class name to attempt to parse. + /// The type, if found. Null otherwise + public static Type FindTypeByNameCached(string runtimeClassName) + { + return typeNameCache.GetOrAdd(runtimeClassName, (runtimeClassName) => + { + Type implementationType = null; + try + { + implementationType = FindTypeByName(runtimeClassName.AsSpan()).type; + } + catch (Exception) + { + } + return implementationType; + }); + } + /// /// Parse the first full type name within the provided span. ///