Enhance MultipliedObjectManager with robust error handling and reference management
This commit is contained in:
		@@ -328,14 +328,39 @@ namespace TerraTech {
 | 
			
		||||
        private readonly Action<MultipliedObject<T>> _configureObject;
 | 
			
		||||
 | 
			
		||||
        public MultipliedObjectManager(Action<MultipliedObject<T>> configureObject) {
 | 
			
		||||
            if (configureObject == null)
 | 
			
		||||
                throw new ArgumentNullException("configureObject");
 | 
			
		||||
 | 
			
		||||
            _configureObject = configureObject;
 | 
			
		||||
            _managedObjects = new Dictionary<T, MultipliedObject<T>>();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void SafeRemove(T instance) {
 | 
			
		||||
            if (instance == null)
 | 
			
		||||
                return;
 | 
			
		||||
 | 
			
		||||
            try {
 | 
			
		||||
                _managedObjects.Remove(instance);
 | 
			
		||||
            } catch (Exception e) {
 | 
			
		||||
                Console.WriteLine(String.Format("Error removing instance from _managedObjects: {0}", e));
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void OnObjectAttached(T instance) {
 | 
			
		||||
            if (!_managedObjects.ContainsKey(instance)) {
 | 
			
		||||
                if (Main.debug.Value)
 | 
			
		||||
                    Console.WriteLine("{0}.OnAttached", typeof(T).Name);
 | 
			
		||||
            if (Main.debug.Value)
 | 
			
		||||
                Console.WriteLine("{0}.OnAttached", typeof(T).Name);
 | 
			
		||||
 | 
			
		||||
            if (instance == null) {
 | 
			
		||||
                Console.WriteLine("Attempted to attach null instance");
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            try {
 | 
			
		||||
                if (_managedObjects.ContainsKey(instance)) {
 | 
			
		||||
                    if (Main.debug.Value)
 | 
			
		||||
                        Console.WriteLine("{0} already managed, skipping", typeof(T).Name);
 | 
			
		||||
                    return;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                var multipliedObject = new MultipliedObject<T>(instance);
 | 
			
		||||
                _configureObject(multipliedObject);
 | 
			
		||||
@@ -345,43 +370,84 @@ namespace TerraTech {
 | 
			
		||||
 | 
			
		||||
                ApplyTo(instance);
 | 
			
		||||
                multipliedObject.LogValues("Patched");
 | 
			
		||||
            } catch (Exception e) {
 | 
			
		||||
                Console.WriteLine(String.Format("Error in OnObjectAttached: {0}", e));
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void OnObjectDetached(T instance) {
 | 
			
		||||
            MultipliedObject<T> multipliedObject;
 | 
			
		||||
            if (_managedObjects.TryGetValue(instance, out multipliedObject)) {
 | 
			
		||||
                if (Main.debug.Value) {
 | 
			
		||||
                    Console.WriteLine("{0}.OnDetaching", typeof(T).Name);
 | 
			
		||||
                    multipliedObject.LogValues("Restoring");
 | 
			
		||||
                }
 | 
			
		||||
            if (Main.debug.Value)
 | 
			
		||||
                Console.WriteLine("{0}.OnDetaching", typeof(T).Name);
 | 
			
		||||
            if (instance == null) {
 | 
			
		||||
                Console.WriteLine("Attempted to detach null instance");
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
                RestoreTo(instance);
 | 
			
		||||
                multipliedObject.LogValues("Restored");
 | 
			
		||||
                _managedObjects.Remove(instance);
 | 
			
		||||
            try {
 | 
			
		||||
                MultipliedObject<T> multipliedObject;
 | 
			
		||||
                if (_managedObjects.TryGetValue(instance, out multipliedObject)) {
 | 
			
		||||
                    if (Main.debug.Value)
 | 
			
		||||
                        multipliedObject.LogValues("Restoring");
 | 
			
		||||
 | 
			
		||||
                    try {
 | 
			
		||||
                        RestoreTo(instance);
 | 
			
		||||
                        multipliedObject.LogValues("Restored");
 | 
			
		||||
                    } catch (Exception e) {
 | 
			
		||||
                        Console.WriteLine(String.Format("Error restoring values: {0}", e));
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    SafeRemove(instance);
 | 
			
		||||
                }
 | 
			
		||||
            } catch (Exception e) {
 | 
			
		||||
                Console.WriteLine(String.Format("Error in OnObjectDetached: {0}", e));
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void ApplyAll(IEnumerable<string> fieldNames = null) {
 | 
			
		||||
            if (Main.debug.Value)
 | 
			
		||||
                Console.WriteLine("Modifying {0} {1}", _managedObjects.Count, typeof(T).Name);
 | 
			
		||||
            foreach (var instance in _managedObjects.Keys
 | 
			
		||||
                         .ToList()) {  // ToList to avoid modification during enumeration
 | 
			
		||||
                RestoreTo(instance, fieldNames);
 | 
			
		||||
                ApplyTo(instance, fieldNames);
 | 
			
		||||
 | 
			
		||||
            // Make a copy of the keys to avoid modification during enumeration
 | 
			
		||||
            var instances = _managedObjects.Keys.ToList();
 | 
			
		||||
 | 
			
		||||
            foreach (var instance in instances) {
 | 
			
		||||
                try {
 | 
			
		||||
                    RestoreTo(instance, fieldNames);
 | 
			
		||||
                    ApplyTo(instance, fieldNames);
 | 
			
		||||
                } catch (Exception e) {
 | 
			
		||||
                    Console.WriteLine(String.Format("Error applying to instance: {0}", e));
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void ApplyTo(T instance, IEnumerable<string> fieldNames = null) {
 | 
			
		||||
            MultipliedObject<T> obj;
 | 
			
		||||
            if (_managedObjects.TryGetValue(instance, out obj))
 | 
			
		||||
                obj.ApplyTo(fieldNames);
 | 
			
		||||
            if (Main.debug.Value)
 | 
			
		||||
                Console.WriteLine("Applying {0}", typeof(T).Name);
 | 
			
		||||
            if (instance == null)
 | 
			
		||||
                return;
 | 
			
		||||
 | 
			
		||||
            try {
 | 
			
		||||
                MultipliedObject<T> obj;
 | 
			
		||||
                if (_managedObjects.TryGetValue(instance, out obj))
 | 
			
		||||
                    obj.ApplyTo(fieldNames);
 | 
			
		||||
            } catch (Exception e) {
 | 
			
		||||
                Console.WriteLine(String.Format("Error in ApplyTo: {0}", e));
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void RestoreTo(T instance, IEnumerable<string> fieldNames = null) {
 | 
			
		||||
            MultipliedObject<T> obj;
 | 
			
		||||
            if (_managedObjects.TryGetValue(instance, out obj))
 | 
			
		||||
                obj.RestoreTo(fieldNames);
 | 
			
		||||
            if (Main.debug.Value)
 | 
			
		||||
                Console.WriteLine("Restoring {0}", typeof(T).Name);
 | 
			
		||||
            if (instance == null)
 | 
			
		||||
                return;
 | 
			
		||||
 | 
			
		||||
            try {
 | 
			
		||||
                MultipliedObject<T> obj;
 | 
			
		||||
                if (_managedObjects.TryGetValue(instance, out obj))
 | 
			
		||||
                    obj.RestoreTo(fieldNames);
 | 
			
		||||
            } catch (Exception e) {
 | 
			
		||||
                Console.WriteLine(String.Format("Error in RestoreTo: {0}", e));
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user