0.2.0: Moved into inspector drawer from module.toolbox to module.inspector
This commit is contained in:
parent
5671c2c754
commit
ffec2abdf4
227 changed files with 5306 additions and 29 deletions
233
Editor/Utilities/EditorMethodUtility.cs
Normal file
233
Editor/Utilities/EditorMethodUtility.cs
Normal file
|
|
@ -0,0 +1,233 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Module.Inspector.Editor.Utilities
|
||||
{
|
||||
internal static class EditorMethodUtility
|
||||
{
|
||||
private static Dictionary<Type, ResultPrimary[]> CACHED_TYPE_TO_PRIMARIES;
|
||||
private static Dictionary<MethodInfo, Result> CACHED_RESULTS;
|
||||
private static Dictionary<Type, Type> CACHED_ATT_TO_DRAWER;
|
||||
|
||||
private static void InitializeCache()
|
||||
{
|
||||
if (CACHED_ATT_TO_DRAWER != null)
|
||||
return;
|
||||
|
||||
CACHED_ATT_TO_DRAWER = new Dictionary<Type, Type>();
|
||||
|
||||
Type baseDrawerType = typeof(AbstractMethodDrawer);
|
||||
var assembly = Assembly.GetAssembly(baseDrawerType);
|
||||
Type[] types = assembly.GetTypes();
|
||||
|
||||
for (var i = 0; i < types.Length; i++)
|
||||
{
|
||||
Type type = types[i];
|
||||
|
||||
if (type.IsAbstract || !baseDrawerType.IsAssignableFrom(type))
|
||||
continue;
|
||||
|
||||
IList<CustomAttributeData> attributes = type.GetCustomAttributesData();
|
||||
|
||||
for (var j = 0; j < attributes.Count; j++)
|
||||
{
|
||||
CustomAttributeData attData = attributes[j];
|
||||
IList<CustomAttributeTypedArgument> arguments = attData.ConstructorArguments;
|
||||
|
||||
for (var k = 0; k < arguments.Count; k++)
|
||||
{
|
||||
if (arguments[k].Value is Type argType)
|
||||
CACHED_ATT_TO_DRAWER.Add(argType, type);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static ResultPrimary[] QueryPrimary(Object target)
|
||||
{
|
||||
InitializeCache();
|
||||
|
||||
if (CACHED_TYPE_TO_PRIMARIES == null)
|
||||
CACHED_TYPE_TO_PRIMARIES = new Dictionary<Type, ResultPrimary[]>();
|
||||
|
||||
Type type = target.GetType();
|
||||
|
||||
if (CACHED_TYPE_TO_PRIMARIES.TryGetValue(type, out ResultPrimary[] primaries))
|
||||
return primaries;
|
||||
|
||||
primaries = InternalFetchPrimary(type);
|
||||
CACHED_TYPE_TO_PRIMARIES.Add(type, primaries);
|
||||
return primaries;
|
||||
}
|
||||
|
||||
public static Result Query(MethodInfo methodInfo)
|
||||
{
|
||||
InitializeCache();
|
||||
|
||||
if (CACHED_RESULTS == null)
|
||||
CACHED_RESULTS = new Dictionary<MethodInfo, Result>();
|
||||
|
||||
if (CACHED_RESULTS.TryGetValue(methodInfo, out Result result))
|
||||
return result;
|
||||
|
||||
result = InternalFetchProperties(methodInfo);
|
||||
|
||||
if (result != null)
|
||||
CACHED_RESULTS.Add(methodInfo, result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static ResultPrimary[] InternalFetchPrimary(Type type)
|
||||
{
|
||||
const BindingFlags FLAGS = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;
|
||||
|
||||
MethodInfo[] methods = type.GetMethods(FLAGS)
|
||||
.Where(m => m.GetParameters().Length == 0)
|
||||
.ToArray();
|
||||
|
||||
var list = new List<ResultPrimary>(methods.Length);
|
||||
|
||||
for (var i = 0; i < methods.Length; i++)
|
||||
{
|
||||
Result result = Query(methods[i]);
|
||||
|
||||
if (result != null)
|
||||
list.Add(new ResultPrimary(methods[i], result));
|
||||
}
|
||||
|
||||
return list.ToArray();
|
||||
}
|
||||
|
||||
private static Result InternalFetchProperties(MethodInfo methodInfo)
|
||||
{
|
||||
ResultValue<DrawerMethodAttribute, DrawerMethodDrawer> drawer = null;
|
||||
ResultValue<DecoratorMethodAttribute, DecoratorMethodDrawer> decorator = null;
|
||||
var accessModifiers = new List<ResultValue<AccessModifierMethodAttribute, AccessModifierMethodDrawer>>(2);
|
||||
object[] attributes = methodInfo.GetCustomAttributes(false);
|
||||
|
||||
for (var i = 0; i < attributes.Length; i++)
|
||||
{
|
||||
object att = attributes[i];
|
||||
|
||||
if (att is DrawerMethodAttribute attDrawer)
|
||||
{
|
||||
if (drawer != null)
|
||||
continue;
|
||||
|
||||
var prop = InternalCreateInstanceOf<DrawerMethodDrawer>(attDrawer);
|
||||
|
||||
if (prop != null)
|
||||
drawer = new ResultValue<DrawerMethodAttribute, DrawerMethodDrawer>(attDrawer, prop);
|
||||
}
|
||||
else if (att is AccessModifierMethodAttribute accessModifier)
|
||||
{
|
||||
var prop = InternalCreateInstanceOf<AccessModifierMethodDrawer>(accessModifier);
|
||||
|
||||
if (prop != null)
|
||||
accessModifiers.Add(new ResultValue<AccessModifierMethodAttribute, AccessModifierMethodDrawer>(accessModifier, prop));
|
||||
}
|
||||
else if (att is DecoratorMethodAttribute attDecorator)
|
||||
{
|
||||
if (decorator != null)
|
||||
continue;
|
||||
|
||||
var prop = InternalCreateInstanceOf<DecoratorMethodDrawer>(attDecorator);
|
||||
|
||||
if (prop != null)
|
||||
decorator = new ResultValue<DecoratorMethodAttribute, DecoratorMethodDrawer>(attDecorator, prop);
|
||||
}
|
||||
}
|
||||
|
||||
if (drawer == null && decorator == null && accessModifiers.Count == 0)
|
||||
return null;
|
||||
|
||||
return new Result(drawer, decorator, accessModifiers);
|
||||
}
|
||||
|
||||
private static T InternalCreateInstanceOf<T>(AbstractMethodAttribute att) where T : AbstractMethodDrawer
|
||||
{
|
||||
if (CACHED_ATT_TO_DRAWER.TryGetValue(att.GetType(), out Type drawerType))
|
||||
return Activator.CreateInstance(drawerType) as T;
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Class: Result from method query
|
||||
/// </summary>
|
||||
public sealed class Result
|
||||
{
|
||||
public readonly ResultValue<DrawerMethodAttribute, DrawerMethodDrawer> draw;
|
||||
public readonly ResultValue<DecoratorMethodAttribute, DecoratorMethodDrawer> decorator;
|
||||
public readonly List<ResultValue<AccessModifierMethodAttribute, AccessModifierMethodDrawer>> accessModifiers;
|
||||
|
||||
public Result(ResultValue<DrawerMethodAttribute, DrawerMethodDrawer> draw,
|
||||
ResultValue<DecoratorMethodAttribute, DecoratorMethodDrawer> decorator,
|
||||
List<ResultValue<AccessModifierMethodAttribute, AccessModifierMethodDrawer>> accessModifiers)
|
||||
{
|
||||
this.draw = draw;
|
||||
this.decorator = decorator;
|
||||
this.accessModifiers = accessModifiers;
|
||||
}
|
||||
|
||||
public T GetAccessModifier<T>() where T : AccessModifierMethodAttribute
|
||||
{
|
||||
for (var i = 0; i < accessModifiers.Count; i++)
|
||||
{
|
||||
if (accessModifiers[i].attribute is T att)
|
||||
return att;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Class: Contains attribute and drawer values
|
||||
/// </summary>
|
||||
/// <typeparam name="T0"></typeparam>
|
||||
/// <typeparam name="T1"></typeparam>
|
||||
public sealed class ResultValue<T0, T1> where T0 : AbstractMethodAttribute
|
||||
where T1 : AbstractMethodDrawer
|
||||
{
|
||||
public readonly T0 attribute;
|
||||
public readonly T1 drawer;
|
||||
|
||||
public ResultValue(T0 attribute, T1 drawer)
|
||||
{
|
||||
this.attribute = attribute;
|
||||
this.drawer = drawer;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Class: Contains primary method info and drawer for a specific method
|
||||
/// </summary>
|
||||
public sealed class ResultPrimary
|
||||
{
|
||||
public readonly MethodInfo methodInfo;
|
||||
public readonly AbstractMethodDrawer drawer;
|
||||
|
||||
public ResultPrimary(MethodInfo methodInfo, AbstractMethodDrawer drawer)
|
||||
{
|
||||
this.methodInfo = methodInfo;
|
||||
this.drawer = drawer;
|
||||
}
|
||||
|
||||
public ResultPrimary(MethodInfo methodInfo, Result result)
|
||||
{
|
||||
this.methodInfo = methodInfo;
|
||||
|
||||
if (result.draw != null)
|
||||
drawer = result.draw.drawer;
|
||||
else if (result.decorator != null)
|
||||
drawer = result.decorator.drawer;
|
||||
else if (result.accessModifiers != null && result.accessModifiers.Count > 0)
|
||||
drawer = result.accessModifiers[0].drawer;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue