diff --git a/Harmony/Tools/AccessTools.cs b/Harmony/Tools/AccessTools.cs index 4f4fed3d..713334e0 100644 --- a/Harmony/Tools/AccessTools.cs +++ b/Harmony/Tools/AccessTools.cs @@ -1608,8 +1608,6 @@ public static object CreateInstance(Type type) /// static readonly Dictionary addHandlerCache = new Dictionary(); - static readonly ReaderWriterLockSlim addHandlerCacheLock = new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion); - /// Makes a deep copy of any object /// The type of the instance that should be created /// The original object @@ -1641,6 +1639,18 @@ public static void MakeDeepCopy(object source, out T result, Func processor = null, string pathRoot = "") { + static bool TryGetHandler(Type resultType, out FastInvokeHandler handler) + { + lock (addHandlerCache) + return addHandlerCache.TryGetValue(resultType, out handler); + } + + static void SetHandler(Type resultType, FastInvokeHandler handler) + { + lock (addHandlerCache) + addHandlerCache[resultType] = handler; + } + if (source is null || resultType is null) return null; @@ -1655,44 +1665,30 @@ public static object MakeDeepCopy(object source, Type resultType, Func m.Name == "Add" && m.GetParameters().Length == 1); - if (addOperation is object) - { - addInvoker = MethodInvoker.GetHandler(addOperation); - } - addHandlerCacheLock.EnterWriteLock(); - try - { - addHandlerCache[resultType] = addInvoker; - } - finally - { - addHandlerCacheLock.ExitWriteLock(); - } - } - if (addInvoker != null) + var addOperation = FirstMethod(resultType, m => m.Name == "Add" && m.GetParameters().Length == 1); + if (addOperation is object) { - var addableResult = Activator.CreateInstance(resultType); - var newElementType = resultType.GetGenericArguments()[0]; - var i = 0; - foreach (var element in source as IEnumerable) - { - var iStr = (i++).ToString(); - var path = pathRoot.Length > 0 ? pathRoot + "." + iStr : iStr; - var newElement = MakeDeepCopy(element, newElementType, processor, path); - _ = addInvoker(addableResult, new object[] { newElement }); - } - return addableResult; + addInvoker = MethodInvoker.GetHandler(addOperation); } + + SetHandler(resultType, addInvoker); } - finally + + if (addInvoker != null) { - addHandlerCacheLock.ExitUpgradeableReadLock(); + var addableResult = Activator.CreateInstance(resultType); + var newElementType = resultType.GetGenericArguments()[0]; + var i = 0; + foreach (var element in source as IEnumerable) + { + var iStr = (i++).ToString(); + var path = pathRoot.Length > 0 ? pathRoot + "." + iStr : iStr; + var newElement = MakeDeepCopy(element, newElementType, processor, path); + _ = addInvoker(addableResult, new object[] {newElement}); + } + return addableResult; } }