From 8dd50c0421c011170c0132eec6361d5e3d5ecfee Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Mon, 24 Apr 2017 22:26:47 +0000 Subject: [PATCH 1/2] Keep ObjectCreator ResolveAssembly override bound until disposal. --- OpenRA.Game/ModData.cs | 3 +++ OpenRA.Game/ObjectCreator.cs | 23 +++++++++++++++++++++-- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/OpenRA.Game/ModData.cs b/OpenRA.Game/ModData.cs index d24dba8fda..98a19f3f88 100644 --- a/OpenRA.Game/ModData.cs +++ b/OpenRA.Game/ModData.cs @@ -217,6 +217,9 @@ namespace OpenRA MapCache.Dispose(); if (VoxelLoader != null) VoxelLoader.Dispose(); + + if (ObjectCreator != null) + ObjectCreator.Dispose(); } } diff --git a/OpenRA.Game/ObjectCreator.cs b/OpenRA.Game/ObjectCreator.cs index c9c3c0aa03..3d8f85e58c 100644 --- a/OpenRA.Game/ObjectCreator.cs +++ b/OpenRA.Game/ObjectCreator.cs @@ -18,7 +18,7 @@ using OpenRA.Primitives; namespace OpenRA { - public class ObjectCreator + public sealed class ObjectCreator : IDisposable { // .NET does not support unloading assemblies, so mod libraries will leak across mod changes. // This tracks the assemblies that have been loaded since game start so that we don't load multiple copies @@ -76,7 +76,6 @@ namespace OpenRA AppDomain.CurrentDomain.AssemblyResolve += ResolveAssembly; assemblies = assemblyList.SelectMany(asm => asm.GetNamespaces().Select(ns => Pair.New(asm, ns))).ToArray(); - AppDomain.CurrentDomain.AssemblyResolve -= ResolveAssembly; } Assembly ResolveAssembly(object sender, ResolveEventArgs e) @@ -85,6 +84,9 @@ namespace OpenRA if (a.FullName == e.Name) return a; + if (assemblies == null) + return null; + return assemblies.Select(a => a.First).FirstOrDefault(a => a.FullName == e.Name); } @@ -159,6 +161,23 @@ namespace OpenRA .SelectMany(ma => ma.GetTypes()); } + ~ObjectCreator() + { + Dispose(false); + } + + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + void Dispose(bool disposing) + { + if (disposing) + AppDomain.CurrentDomain.AssemblyResolve -= ResolveAssembly; + } + [AttributeUsage(AttributeTargets.Constructor)] public sealed class UseCtorAttribute : Attribute { } } From a01b3f88fcf8de01e3278e9b794768fd72b075d3 Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Mon, 24 Apr 2017 23:29:08 +0100 Subject: [PATCH 2/2] Remove unused ObjectCreator constructor. --- OpenRA.Game/ObjectCreator.cs | 7 ------- 1 file changed, 7 deletions(-) diff --git a/OpenRA.Game/ObjectCreator.cs b/OpenRA.Game/ObjectCreator.cs index 3d8f85e58c..afb8f32f17 100644 --- a/OpenRA.Game/ObjectCreator.cs +++ b/OpenRA.Game/ObjectCreator.cs @@ -29,13 +29,6 @@ namespace OpenRA readonly Pair[] assemblies; readonly bool isMonoRuntime = Type.GetType("Mono.Runtime") != null; - public ObjectCreator(Assembly a) - { - typeCache = new Cache(FindType); - ctorCache = new Cache(GetCtor); - assemblies = a.GetNamespaces().Select(ns => Pair.New(a, ns)).ToArray(); - } - public ObjectCreator(Manifest manifest, FileSystem.FileSystem modFiles) { typeCache = new Cache(FindType);