#nullable enable using System; using System.Reflection; using GlitchyEngine.Core; namespace GlitchyEngine.Extensions; public static class ActivatorExtension { /// Creates an instance of the specified type using that type's default constructor. /// The type of object to create. /// A reference to the newly created object; or if no instance could be created. public static object? CreateInstanceSafe(Type type) { try { return Activator.CreateInstance(type, true); } catch (MissingMethodException e) { Log.Error($"Failed to create instance of type \"{type}\": The type doesn't contain a constructor with zero parameters.\nMake sure the type has a constructor that takes no arguments (It can be private!).\n{e}"); } catch (MethodAccessException e) { Log.Error($"Failed to create instance of type \"{type}\": The default constructor is not accessible.\n{e}"); } catch (Exception e) { Log.Error($"Failed to create instance of type \"{type}\": {e}"); } return null; } /// Creates an instance of the specified type using a constructor that matches the given arguments. /// The type of object to create. /// The arguments passed to the constructor /// A reference to the newly created object; or if no instance could be created. public static object? CreateInstanceSafe(Type type, params object[] args) { try { return Activator.CreateInstance(type, BindingFlags.Default | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.CreateInstance | BindingFlags.Instance, null, args, null); } catch (Exception e) { Log.Error($"Failed to create instance of type \"{type}\": {e}"); } return null; } /// /// Creates an instance of the given type inheriting from engine object and sets it's id. /// /// The type of the engine object. /// The objects id. /// An instance of the engine object type; or if the creation failed. internal static EngineObject? CreateEngineObject(Type engineObjectType, UUID objectId) { EngineObject? engineObject = (EngineObject?)CreateInstanceSafe(engineObjectType); if (engineObject != null) engineObject._uuid = objectId; return engineObject; } /// /// Creates an instance of the given type inheriting from engine object and sets it's id. /// /// The type of the engine object. /// The objects id. /// An instance of the engine object type; or if the creation failed. internal static T? CreateEngineObject(Type engineObjectType, UUID objectId) where T : EngineObject { if (!typeof(T).IsAssignableFrom(engineObjectType)) { return null; } EngineObject? engineObject = (EngineObject?)CreateInstanceSafe(engineObjectType); if (engineObject != null) engineObject._uuid = objectId; return (T?)engineObject; } /// /// Creates an instance of the given component type and sets it's entities id. /// /// The type of the component. /// The entities id. /// An instance of the component type; or if the creation failed. internal static Component? CreateComponent(Type componentType, UUID entityId) { Component? component = (Component?)CreateInstanceSafe(componentType); if (component != null) component._uuid = entityId; return component; } /// /// Returns the null for reference types and an initialized value for structs / value types. /// /// The type to create the default value for. public static object? CreateDefaultValue(Type type) { return type.IsClass ? null : CreateInstanceSafe(type); } }