diff --git a/Torch/Managers/ReflectionManager.cs b/Torch/Managers/ReflectionManager.cs index 9c2701d..1886fb6 100644 --- a/Torch/Managers/ReflectionManager.cs +++ b/Torch/Managers/ReflectionManager.cs @@ -15,44 +15,144 @@ namespace Torch.Managers string Name { get; set; } Type Type { get; set; } } + + /// + /// Indicates that this field should contain a delegate capable of retrieving the value of a field. + /// + /// + /// + /// _instanceGetter; + /// + /// [ReflectedGetterAttribute(Name="_staticField", Type=typeof(Example))] + /// private static Func _staticGetter; + /// + /// private class Example { + /// private int _instanceField; + /// private static int _staticField; + /// } + /// ]]> + /// + /// [AttributeUsage(AttributeTargets.Field)] public class ReflectedGetterAttribute : Attribute, IReflectedFieldAttribute { + /// + /// Name of the field to get. If null, the tagged field's name. + /// public string Name { get; set; } = null; + /// + /// Declaring type of the field to get. If null, inferred from the instance argument type. + /// public Type Type { get; set; } = null; } + /// + /// Indicates that this field should contain a delegate capable of setting the value of a field. + /// + /// + /// + /// _instanceSetter; + /// + /// [ReflectedSetterAttribute(Name="_staticField", Type=typeof(Example))] + /// private static Action _staticSetter; + /// + /// private class Example { + /// private int _instanceField; + /// private static int _staticField; + /// } + /// ]]> + /// + /// [AttributeUsage(AttributeTargets.Field)] public class ReflectedSetterAttribute : Attribute, IReflectedFieldAttribute { + /// + /// Name of the field to get. If null, the tagged field's name. + /// public string Name { get; set; } = null; + /// + /// Declaring type of the field to get. If null, inferred from the instance argument type. + /// public Type Type { get; set; } = null; } + /// + /// Indicates that this field should contain a delegate capable of invoking an instance method. + /// + /// + /// + /// ExampleInstance; + /// + /// private class Example { + /// private int ExampleInstance(int a, float b) { + /// return a + ", " + b; + /// } + /// } + /// ]]> + /// + /// [AttributeUsage(AttributeTargets.Field)] public class ReflectedMethodAttribute : Attribute { + /// + /// Name of the method to invoke. If null, the tagged field's name. + /// public string Name { get; set; } = null; + /// + /// Declaring type of the method to invoke. If null, inferred from the instance argument type. + /// + public Type Type { get; set; } = null; } + /// + /// Indicates that this field should contain a delegate capable of invoking a static method. + /// + /// + /// + /// ExampleStatic; + /// + /// private class Example { + /// private static int ExampleStatic(int a, float b) { + /// return a + ", " + b; + /// } + /// } + /// ]]> + /// + /// [AttributeUsage(AttributeTargets.Field)] public class ReflectedStaticMethodAttribute : ReflectedMethodAttribute { - public Type Type { get; set; } } + /// + /// Automatically calls for every assembly already loaded, and every assembly that is loaded in the future. + /// public class ReflectionManager : Manager { + private static readonly string[] _namespaceBlacklist = new[] { + "System", "VRage", "Sandbox", "SpaceEngineers" + }; + /// public ReflectionManager(ITorchBase torchInstance) : base(torchInstance) { } + /// public override void Attach() { - foreach (var asm in AppDomain.CurrentDomain.GetAssemblies()) + foreach (Assembly asm in AppDomain.CurrentDomain.GetAssemblies()) Process(asm); AppDomain.CurrentDomain.AssemblyLoad += CurrentDomain_AssemblyLoad; } + /// public override void Detach() { AppDomain.CurrentDomain.AssemblyLoad -= CurrentDomain_AssemblyLoad; @@ -72,7 +172,13 @@ namespace Torch.Managers public static void Process(Type t) { if (_processedTypes.Add(t)) - ProcessInternal(t); + { + foreach (string ns in _namespaceBlacklist) + if (t.FullName.StartsWith(ns)) + return; + foreach (FieldInfo field in t.GetFields(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)) + Process(field); + } } /// @@ -85,20 +191,49 @@ namespace Torch.Managers Process(type); } + /// + /// Processes the given field, determines if it's reflected, and initializes it if it is. + /// + /// Field to process + /// true if it was reflected, false if it wasn't reflectable + /// If the field failed to process + public static bool Process(FieldInfo field) + { + var attr = field.GetCustomAttribute(); + if (attr != null) + { + ProcessReflectedMethod(field, attr); + return true; + } + var attr2 = field.GetCustomAttribute(); + if (attr2 != null) + { + ProcessReflectedField(field, attr2); + return true; + } + var attr3 = field.GetCustomAttribute(); + if (attr3 != null) + { + ProcessReflectedField(field, attr3); + return true; + } + + return false; + } + private static void ProcessReflectedMethod(FieldInfo field, ReflectedMethodAttribute attr) { MethodInfo delegateMethod = field.FieldType.GetMethod("Invoke"); ParameterInfo[] parameters = delegateMethod.GetParameters(); - Type trueType; + Type trueType = attr.Type; Type[] trueParameterTypes; - if (attr is ReflectedStaticMethodAttribute staticMethod) + if (attr is ReflectedStaticMethodAttribute) { - trueType = staticMethod.Type; trueParameterTypes = parameters.Select(x => x.ParameterType).ToArray(); } else { - trueType = parameters[0].ParameterType; + trueType = trueType ?? parameters[0].ParameterType; trueParameterTypes = parameters.Skip(1).Select(x => x.ParameterType).ToArray(); } @@ -196,23 +331,5 @@ namespace Torch.Managers field.SetValue(null, Expression.Lambda(impl, paramExp).Compile()); } - - private static void ProcessInternal(Type t) - { - foreach (FieldInfo field in t.GetFields(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)) - { - var attr = field.GetCustomAttribute(); - if (attr != null) - ProcessReflectedMethod(field, attr); - var attr2 = field.GetCustomAttribute(); - if (attr2 != null) - ProcessReflectedField(field, attr2); - var attr3 = field.GetCustomAttribute(); - if (attr3 != null) - ProcessReflectedField(field, attr3); - - } - } - } }