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..afb8f32f17 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 @@ -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); @@ -76,7 +69,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 +77,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 +154,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 { } }