You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

124 lines
3.8 KiB

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq.Expressions;
  4. using System.Reflection;
  5. using System.Text;
  6. namespace UnityEditor.PostProcessing
  7. {
  8. public static class ReflectionUtils
  9. {
  10. static Dictionary<KeyValuePair<object, string>, FieldInfo> s_FieldInfoFromPaths = new Dictionary<KeyValuePair<object, string>, FieldInfo>();
  11. public static FieldInfo GetFieldInfoFromPath(object source, string path)
  12. {
  13. FieldInfo field = null;
  14. var kvp = new KeyValuePair<object, string>(source, path);
  15. if (!s_FieldInfoFromPaths.TryGetValue(kvp, out field))
  16. {
  17. var splittedPath = path.Split('.');
  18. var type = source.GetType();
  19. foreach (var t in splittedPath)
  20. {
  21. field = type.GetField(t, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
  22. if (field == null)
  23. break;
  24. type = field.FieldType;
  25. }
  26. s_FieldInfoFromPaths.Add(kvp, field);
  27. }
  28. return field;
  29. }
  30. public static string GetFieldPath<T, TValue>(Expression<Func<T, TValue>> expr)
  31. {
  32. MemberExpression me;
  33. switch (expr.Body.NodeType)
  34. {
  35. case ExpressionType.Convert:
  36. case ExpressionType.ConvertChecked:
  37. var ue = expr.Body as UnaryExpression;
  38. me = (ue != null ? ue.Operand : null) as MemberExpression;
  39. break;
  40. default:
  41. me = expr.Body as MemberExpression;
  42. break;
  43. }
  44. var members = new List<string>();
  45. while (me != null)
  46. {
  47. members.Add(me.Member.Name);
  48. me = me.Expression as MemberExpression;
  49. }
  50. var sb = new StringBuilder();
  51. for (int i = members.Count - 1; i >= 0; i--)
  52. {
  53. sb.Append(members[i]);
  54. if (i > 0) sb.Append('.');
  55. }
  56. return sb.ToString();
  57. }
  58. public static object GetFieldValue(object source, string name)
  59. {
  60. var type = source.GetType();
  61. while (type != null)
  62. {
  63. var f = type.GetField(name, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
  64. if (f != null)
  65. return f.GetValue(source);
  66. type = type.BaseType;
  67. }
  68. return null;
  69. }
  70. public static object GetFieldValueFromPath(object source, ref Type baseType, string path)
  71. {
  72. var splittedPath = path.Split('.');
  73. object srcObject = source;
  74. foreach (var t in splittedPath)
  75. {
  76. var fieldInfo = baseType.GetField(t, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
  77. if (fieldInfo == null)
  78. {
  79. baseType = null;
  80. break;
  81. }
  82. baseType = fieldInfo.FieldType;
  83. srcObject = GetFieldValue(srcObject, t);
  84. }
  85. return baseType == null
  86. ? null
  87. : srcObject;
  88. }
  89. public static object GetParentObject(string path, object obj)
  90. {
  91. var fields = path.Split('.');
  92. if (fields.Length == 1)
  93. return obj;
  94. var info = obj.GetType().GetField(fields[0], BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
  95. obj = info.GetValue(obj);
  96. return GetParentObject(string.Join(".", fields, 1, fields.Length - 1), obj);
  97. }
  98. }
  99. }