private static void GetEntries(MemberInfoPath.Entry member, Stack <MemberInfoPath.Entry> membersPath, Type type, List <TypeEntry> result, List <object> values, Stack <object> refStack, Type memberType, object memberValue) { membersPath.Push(member); var path = new MemberInfoPath(membersPath); var beforeCount = result.Count; // Check if record object sub members (skip flax objects) // It's used for ref types bu not null types and with checking cyclic references if ((memberType.IsClass || memberType.IsArray || typeof(IList).IsAssignableFrom(memberType)) && memberValue != null && !refStack.Contains(memberValue)) { if (memberType.IsArray && !typeof(FlaxEngine.Object).IsAssignableFrom(memberType.GetElementType())) { var array = (Array)memberValue; var elementType = memberType.GetElementType(); var length = array.Length; refStack.Push(memberValue); for (int i = 0; i < length; i++) { var elementValue = array.GetValue(i); GetEntries(new MemberInfoPath.Entry(member.Member, i), membersPath, type, result, values, refStack, elementType, elementValue); } refStack.Pop(); } else if (typeof(IList).IsAssignableFrom(memberType) && !typeof(FlaxEngine.Object).IsAssignableFrom(memberType.GetElementType())) { var list = (IList)memberValue; var elementType = memberType.GetGenericArguments()[0]; var count = list.Count; refStack.Push(memberValue); for (int i = 0; i < count; i++) { var elementValue = list[i]; GetEntries(new MemberInfoPath.Entry(member.Member, i), membersPath, type, result, values, refStack, elementType, elementValue); } refStack.Pop(); } else if (memberType.IsClass && !typeof(FlaxEngine.Object).IsAssignableFrom(memberType)) { refStack.Push(memberValue); GetEntries(memberValue, membersPath, memberType, result, values, refStack); refStack.Pop(); } } var afterCount = result.Count; result.Add(new TypeEntry(path, afterCount - beforeCount)); values.Add(memberValue); membersPath.Pop(); }
/// <summary> /// Initializes a new instance of the <see cref="MemberComparison"/> struct. /// </summary> /// <param name="memberPath">The member path.</param> /// <param name="value1">The first value.</param> /// <param name="value2">The second value.</param> public MemberComparison(MemberInfoPath memberPath, object value1, object value2) { MemberPath = memberPath; Value1 = value1; Value2 = value2; }
/// <summary> /// Initializes a new instance of the <see cref="MemberComparison"/> struct. /// </summary> /// <param name="member">The member.</param> /// <param name="value1">The first value.</param> /// <param name="value2">The second value.</param> public MemberComparison(MemberInfo member, object value1, object value2) { MemberPath = new MemberInfoPath(member); Value1 = value1; Value2 = value2; }
public TypeEntry(MemberInfoPath membersPath, int subEntriesCount) { Path = membersPath; SubEntriesCount = subEntriesCount; }
private static void GetEntries(MemberInfoPath.Entry member, Stack <MemberInfoPath.Entry> membersPath, List <TypeEntry> result, List <object> values, Stack <object> refStack, ScriptType memberType, object memberValue) { membersPath.Push(member); var path = new MemberInfoPath(membersPath); var beforeCount = result.Count; // Check if record object sub members (skip Flax objects) // It's used for ref types but not null types and with checking cyclic references if ((memberType.IsClass || memberType.IsArray || typeof(IList).IsAssignableFrom(memberType.Type) || typeof(IDictionary).IsAssignableFrom(memberType.Type)) && memberValue != null && !refStack.Contains(memberValue)) { if (memberType.IsArray && !typeof(FlaxEngine.Object).IsAssignableFrom(memberType.GetElementType())) { // Array var array = (Array)memberValue; var elementType = new ScriptType(memberType.GetElementType()); var length = array.Length; refStack.Push(memberValue); for (int i = 0; i < length; i++) { var value = array.GetValue(i); GetEntries(new MemberInfoPath.Entry(member.Member, i), membersPath, result, values, refStack, elementType, value); } refStack.Pop(); } else if (typeof(IList).IsAssignableFrom(memberType.Type) && !typeof(FlaxEngine.Object).IsAssignableFrom(memberType.GetElementType())) { // List var list = (IList)memberValue; var genericArguments = memberType.GetGenericArguments(); var elementType = new ScriptType(genericArguments[0]); var count = list.Count; refStack.Push(memberValue); for (int i = 0; i < count; i++) { var value = list[i]; GetEntries(new MemberInfoPath.Entry(member.Member, i), membersPath, result, values, refStack, elementType, value); } refStack.Pop(); } else if (typeof(IDictionary).IsAssignableFrom(memberType.Type)) { // Dictionary var dictionary = (IDictionary)memberValue; var genericArguments = memberType.GetGenericArguments(); var valueType = new ScriptType(genericArguments[1]); foreach (var key in dictionary.Keys) { var value = dictionary[key]; GetEntries(new MemberInfoPath.Entry(member.Member, key), membersPath, result, values, refStack, valueType, value); } } else if (memberType.IsClass && !new ScriptType(typeof(FlaxEngine.Object)).IsAssignableFrom(memberType)) { // Object refStack.Push(memberValue); GetEntries(memberValue, membersPath, memberType, result, values, refStack); refStack.Pop(); } } var afterCount = result.Count; result.Add(new TypeEntry(path, afterCount - beforeCount)); var memberValueType = TypeUtils.GetObjectType(memberValue); if (memberValue != null && memberValueType.IsStructure) { var json = JsonSerializer.Serialize(memberValue); var clone = JsonSerializer.Deserialize(json, memberValueType.Type); values.Add(clone); } else { values.Add(memberValue); } membersPath.Pop(); }