Skip to content
This repository was archived by the owner on May 9, 2023. It is now read-only.

Commit d1eb567

Browse files
committed
Move GetCacheMembers into separate class
1 parent f1ca484 commit d1eb567

File tree

2 files changed

+195
-181
lines changed

2 files changed

+195
-181
lines changed

src/CacheObject/CacheMember.cs

Lines changed: 0 additions & 181 deletions
Original file line numberDiff line numberDiff line change
@@ -169,186 +169,5 @@ public void OnEvaluateClicked()
169169
}
170170
}
171171
}
172-
173-
#region Cache Member Util
174-
175-
public static List<CacheMember> GetCacheMembers(object inspectorTarget, Type type, ReflectionInspector inspector)
176-
{
177-
//var list = new List<CacheMember>();
178-
HashSet<string> cachedSigs = new();
179-
List<CacheMember> props = new();
180-
List<CacheMember> fields = new();
181-
List<CacheMember> ctors = new();
182-
List<CacheMember> methods = new();
183-
184-
var types = ReflectionUtility.GetAllBaseTypes(type);
185-
186-
var flags = BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static;
187-
if (!inspector.StaticOnly)
188-
flags |= BindingFlags.Instance;
189-
190-
if (!type.IsAbstract)
191-
{
192-
// Get non-static constructors of the main type.
193-
// There's no reason to get the static cctor, it will be invoked when we inspect the class.
194-
// Also no point getting ctors on inherited types.
195-
foreach (var ctor in type.GetConstructors(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance))
196-
TryCacheMember(ctor, ctors, cachedSigs, type, inspector);
197-
198-
// structs always have a parameterless constructor
199-
if (type.IsValueType)
200-
{
201-
CacheConstructor cached = new(type);
202-
cached.SetFallbackType(type);
203-
cached.SetInspectorOwner(inspector, null);
204-
ctors.Add(cached);
205-
}
206-
}
207-
208-
foreach (var declaringType in types)
209-
{
210-
var target = inspectorTarget;
211-
if (!inspector.StaticOnly)
212-
target = target.TryCast(declaringType);
213-
214-
foreach (var prop in declaringType.GetProperties(flags))
215-
if (prop.DeclaringType == declaringType)
216-
TryCacheMember(prop, props, cachedSigs, declaringType, inspector);
217-
218-
foreach (var field in declaringType.GetFields(flags))
219-
if (field.DeclaringType == declaringType)
220-
TryCacheMember(field, fields, cachedSigs, declaringType, inspector);
221-
222-
foreach (var method in declaringType.GetMethods(flags))
223-
if (method.DeclaringType == declaringType)
224-
TryCacheMember(method, methods, cachedSigs, declaringType, inspector);
225-
226-
}
227-
228-
var sorted = new List<CacheMember>();
229-
sorted.AddRange(props.OrderBy(it => Array.IndexOf(types, it.DeclaringType))
230-
.ThenBy(it => it.NameForFiltering));
231-
sorted.AddRange(fields.OrderBy(it => Array.IndexOf(types, it.DeclaringType))
232-
.ThenBy(it => it.NameForFiltering));
233-
sorted.AddRange(ctors.OrderBy(it => Array.IndexOf(types, it.DeclaringType))
234-
.ThenBy(it => it.NameForFiltering));
235-
sorted.AddRange(methods.OrderBy(it => Array.IndexOf(types, it.DeclaringType))
236-
.ThenBy(it => it.NameForFiltering));
237-
return sorted;
238-
}
239-
240-
private static void TryCacheMember(MemberInfo member, IList list, HashSet<string> cachedSigs,
241-
Type declaringType, ReflectionInspector inspector, bool ignorePropertyMethodInfos = true)
242-
{
243-
try
244-
{
245-
if (UERuntimeHelper.IsBlacklisted(member))
246-
return;
247-
248-
var sig = GetSig(member);
249-
250-
// ExplorerCore.Log($"Trying to cache member {sig}... ({member.MemberType})");
251-
252-
CacheMember cached;
253-
Type returnType;
254-
switch (member.MemberType)
255-
{
256-
case MemberTypes.Constructor:
257-
{
258-
var ci = member as ConstructorInfo;
259-
sig += GetArgumentString(ci.GetParameters());
260-
if (cachedSigs.Contains(sig))
261-
return;
262-
cached = new CacheConstructor(ci);
263-
returnType = ci.DeclaringType;
264-
}
265-
break;
266-
267-
case MemberTypes.Method:
268-
{
269-
var mi = member as MethodInfo;
270-
if (ignorePropertyMethodInfos
271-
&& (mi.Name.StartsWith("get_") || mi.Name.StartsWith("set_")))
272-
return;
273-
274-
sig += GetArgumentString(mi.GetParameters());
275-
if (cachedSigs.Contains(sig))
276-
return;
277-
278-
cached = new CacheMethod(mi);
279-
returnType = mi.ReturnType;
280-
break;
281-
}
282-
283-
case MemberTypes.Property:
284-
{
285-
var pi = member as PropertyInfo;
286-
287-
if (!pi.CanRead && pi.CanWrite)
288-
{
289-
// write-only property, cache the set method instead.
290-
var setMethod = pi.GetSetMethod(true);
291-
if (setMethod != null)
292-
TryCacheMember(setMethod, list, cachedSigs, declaringType, inspector, false);
293-
return;
294-
}
295-
296-
sig += GetArgumentString(pi.GetIndexParameters());
297-
if (cachedSigs.Contains(sig))
298-
return;
299-
300-
cached = new CacheProperty(pi);
301-
returnType = pi.PropertyType;
302-
break;
303-
}
304-
305-
case MemberTypes.Field:
306-
{
307-
var fi = member as FieldInfo;
308-
cached = new CacheField(fi);
309-
returnType = fi.FieldType;
310-
break;
311-
}
312-
313-
default: return;
314-
}
315-
316-
cachedSigs.Add(sig);
317-
318-
cached.SetFallbackType(returnType);
319-
cached.SetInspectorOwner(inspector, member);
320-
321-
list.Add(cached);
322-
}
323-
catch (Exception e)
324-
{
325-
ExplorerCore.LogWarning($"Exception caching member {member.DeclaringType.FullName}.{member.Name}!");
326-
ExplorerCore.Log(e.ToString());
327-
}
328-
}
329-
330-
internal static string GetSig(MemberInfo member)
331-
=> $"{member.DeclaringType.Name}.{member.Name}";
332-
333-
internal static string GetArgumentString(ParameterInfo[] args)
334-
{
335-
var sb = new StringBuilder();
336-
sb.Append(' ');
337-
sb.Append('(');
338-
foreach (var param in args)
339-
{
340-
sb.Append(param.ParameterType.Name);
341-
sb.Append(' ');
342-
sb.Append(param.Name);
343-
sb.Append(',');
344-
sb.Append(' ');
345-
}
346-
sb.Append(')');
347-
return sb.ToString();
348-
}
349-
350-
#endregion
351-
352-
353172
}
354173
}
Lines changed: 195 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,195 @@
1+
using System;
2+
using System.Collections;
3+
using System.Collections.Generic;
4+
using System.Linq;
5+
using System.Reflection;
6+
using System.Text;
7+
using UnityExplorer.Inspectors;
8+
using UnityExplorer.Runtime;
9+
using UniverseLib;
10+
using HarmonyLib;
11+
using HarmonyLib.Tools;
12+
13+
namespace UnityExplorer.CacheObject
14+
{
15+
public static class CacheMemberFactory
16+
{
17+
public static List<CacheMember> GetCacheMembers(object inspectorTarget, Type type, ReflectionInspector inspector)
18+
{
19+
//var list = new List<CacheMember>();
20+
HashSet<string> cachedSigs = new();
21+
List<CacheMember> props = new();
22+
List<CacheMember> fields = new();
23+
List<CacheMember> ctors = new();
24+
List<CacheMember> methods = new();
25+
26+
var types = ReflectionUtility.GetAllBaseTypes(type);
27+
28+
var flags = BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static;
29+
if (!inspector.StaticOnly)
30+
flags |= BindingFlags.Instance;
31+
32+
if (!type.IsAbstract)
33+
{
34+
// Get non-static constructors of the main type.
35+
// There's no reason to get the static cctor, it will be invoked when we inspect the class.
36+
// Also no point getting ctors on inherited types.
37+
foreach (var ctor in type.GetConstructors(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance))
38+
TryCacheMember(ctor, ctors, cachedSigs, type, inspector);
39+
40+
// structs always have a parameterless constructor
41+
if (type.IsValueType)
42+
{
43+
CacheConstructor cached = new(type);
44+
cached.SetFallbackType(type);
45+
cached.SetInspectorOwner(inspector, null);
46+
ctors.Add(cached);
47+
}
48+
}
49+
50+
foreach (var declaringType in types)
51+
{
52+
var target = inspectorTarget;
53+
if (!inspector.StaticOnly)
54+
target = target.TryCast(declaringType);
55+
56+
foreach (var prop in declaringType.GetProperties(flags))
57+
if (prop.DeclaringType == declaringType)
58+
TryCacheMember(prop, props, cachedSigs, declaringType, inspector);
59+
60+
foreach (var field in declaringType.GetFields(flags))
61+
if (field.DeclaringType == declaringType)
62+
TryCacheMember(field, fields, cachedSigs, declaringType, inspector);
63+
64+
foreach (var method in declaringType.GetMethods(flags))
65+
if (method.DeclaringType == declaringType)
66+
TryCacheMember(method, methods, cachedSigs, declaringType, inspector);
67+
68+
}
69+
70+
var sorted = new List<CacheMember>();
71+
sorted.AddRange(props.OrderBy(it => Array.IndexOf(types, it.DeclaringType))
72+
.ThenBy(it => it.NameForFiltering));
73+
sorted.AddRange(fields.OrderBy(it => Array.IndexOf(types, it.DeclaringType))
74+
.ThenBy(it => it.NameForFiltering));
75+
sorted.AddRange(ctors.OrderBy(it => Array.IndexOf(types, it.DeclaringType))
76+
.ThenBy(it => it.NameForFiltering));
77+
sorted.AddRange(methods.OrderBy(it => Array.IndexOf(types, it.DeclaringType))
78+
.ThenBy(it => it.NameForFiltering));
79+
return sorted;
80+
}
81+
82+
static void TryCacheMember(
83+
MemberInfo member,
84+
IList list,
85+
HashSet<string> cachedSigs,
86+
Type declaringType,
87+
ReflectionInspector inspector,
88+
bool ignorePropertyMethodInfos = true)
89+
{
90+
try
91+
{
92+
if (UERuntimeHelper.IsBlacklisted(member))
93+
return;
94+
95+
string sig = member switch
96+
{
97+
MethodBase mb => mb.FullDescription(),
98+
PropertyInfo or FieldInfo => $"{member.DeclaringType.FullDescription()}.{member.Name}",
99+
_ => throw new NotImplementedException(),
100+
};
101+
102+
if (cachedSigs.Contains(sig))
103+
return;
104+
105+
// ExplorerCore.Log($"Trying to cache member {sig}... ({member.MemberType})");
106+
107+
CacheMember cached;
108+
Type returnType;
109+
110+
switch (member.MemberType)
111+
{
112+
case MemberTypes.Constructor:
113+
{
114+
var ci = member as ConstructorInfo;
115+
cached = new CacheConstructor(ci);
116+
returnType = ci.DeclaringType;
117+
}
118+
break;
119+
120+
case MemberTypes.Method:
121+
{
122+
var mi = member as MethodInfo;
123+
if (ignorePropertyMethodInfos
124+
&& (mi.Name.StartsWith("get_") || mi.Name.StartsWith("set_")))
125+
return;
126+
127+
cached = new CacheMethod(mi);
128+
returnType = mi.ReturnType;
129+
break;
130+
}
131+
132+
case MemberTypes.Property:
133+
{
134+
var pi = member as PropertyInfo;
135+
136+
if (!pi.CanRead && pi.CanWrite)
137+
{
138+
// write-only property, cache the set method instead.
139+
var setMethod = pi.GetSetMethod(true);
140+
if (setMethod != null)
141+
TryCacheMember(setMethod, list, cachedSigs, declaringType, inspector, false);
142+
return;
143+
}
144+
145+
cached = new CacheProperty(pi);
146+
returnType = pi.PropertyType;
147+
break;
148+
}
149+
150+
case MemberTypes.Field:
151+
{
152+
var fi = member as FieldInfo;
153+
cached = new CacheField(fi);
154+
returnType = fi.FieldType;
155+
break;
156+
}
157+
158+
default:
159+
throw new NotImplementedException();
160+
}
161+
162+
cachedSigs.Add(sig);
163+
164+
cached.SetFallbackType(returnType);
165+
cached.SetInspectorOwner(inspector, member);
166+
167+
list.Add(cached);
168+
}
169+
catch (Exception e)
170+
{
171+
ExplorerCore.LogWarning($"Exception caching member {member.DeclaringType.FullName}.{member.Name}!");
172+
ExplorerCore.Log(e.ToString());
173+
}
174+
}
175+
176+
//internal static string GetSig(MemberInfo member) => $"{member.DeclaringType.Name}.{member.Name}";
177+
//
178+
//internal static string GetArgumentString(ParameterInfo[] args)
179+
//{
180+
// var sb = new StringBuilder();
181+
// sb.Append(' ');
182+
// sb.Append('(');
183+
// foreach (var param in args)
184+
// {
185+
// sb.Append(param.ParameterType.Name);
186+
// sb.Append(' ');
187+
// sb.Append(param.Name);
188+
// sb.Append(',');
189+
// sb.Append(' ');
190+
// }
191+
// sb.Append(')');
192+
// return sb.ToString();
193+
//}
194+
}
195+
}

0 commit comments

Comments
 (0)