Fix shallow copy to deep copy
This commit is contained in:
parent
ca8f8ddb1a
commit
c066719ccd
@ -298,7 +298,7 @@ namespace TJAPlayer3
|
||||
string key = bestPlay.ChartUniqueId + bestPlay.ChartDifficulty.ToString();
|
||||
if (!bestPlaysDistinctCharts.ContainsKey(key))
|
||||
{
|
||||
bestPlaysDistinctCharts[key] = bestPlay;
|
||||
bestPlaysDistinctCharts[key] = bestPlay.Copy();
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -326,7 +326,7 @@ namespace TJAPlayer3
|
||||
string key = bestPlay.ChartUniqueId;
|
||||
if (!bestPlaysDistinctSongs.ContainsKey(key))
|
||||
{
|
||||
bestPlaysDistinctSongs[key] = bestPlay;
|
||||
bestPlaysDistinctSongs[key] = bestPlay.Copy();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
133
OpenTaiko/src/Helpers/ObjectExtensions.cs
Normal file
133
OpenTaiko/src/Helpers/ObjectExtensions.cs
Normal file
@ -0,0 +1,133 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using System.ArrayExtensions;
|
||||
|
||||
// https://github.com/Burtsev-Alexey/net-object-deep-copy/blob/master/ObjectExtensions.cs
|
||||
|
||||
namespace System
|
||||
{
|
||||
public static class ObjectExtensions
|
||||
{
|
||||
private static readonly MethodInfo CloneMethod = typeof(Object).GetMethod("MemberwiseClone", BindingFlags.NonPublic | BindingFlags.Instance);
|
||||
|
||||
public static bool IsPrimitive(this Type type)
|
||||
{
|
||||
if (type == typeof(String)) return true;
|
||||
return (type.IsValueType & type.IsPrimitive);
|
||||
}
|
||||
|
||||
public static Object Copy(this Object originalObject)
|
||||
{
|
||||
return InternalCopy(originalObject, new Dictionary<Object, Object>(new ReferenceEqualityComparer()));
|
||||
}
|
||||
private static Object InternalCopy(Object originalObject, IDictionary<Object, Object> visited)
|
||||
{
|
||||
if (originalObject == null) return null;
|
||||
var typeToReflect = originalObject.GetType();
|
||||
if (IsPrimitive(typeToReflect)) return originalObject;
|
||||
if (visited.ContainsKey(originalObject)) return visited[originalObject];
|
||||
if (typeof(Delegate).IsAssignableFrom(typeToReflect)) return null;
|
||||
var cloneObject = CloneMethod.Invoke(originalObject, null);
|
||||
if (typeToReflect.IsArray)
|
||||
{
|
||||
var arrayType = typeToReflect.GetElementType();
|
||||
if (IsPrimitive(arrayType) == false)
|
||||
{
|
||||
Array clonedArray = (Array)cloneObject;
|
||||
clonedArray.ForEach((array, indices) => array.SetValue(InternalCopy(clonedArray.GetValue(indices), visited), indices));
|
||||
}
|
||||
|
||||
}
|
||||
visited.Add(originalObject, cloneObject);
|
||||
CopyFields(originalObject, visited, cloneObject, typeToReflect);
|
||||
RecursiveCopyBaseTypePrivateFields(originalObject, visited, cloneObject, typeToReflect);
|
||||
return cloneObject;
|
||||
}
|
||||
|
||||
private static void RecursiveCopyBaseTypePrivateFields(object originalObject, IDictionary<object, object> visited, object cloneObject, Type typeToReflect)
|
||||
{
|
||||
if (typeToReflect.BaseType != null)
|
||||
{
|
||||
RecursiveCopyBaseTypePrivateFields(originalObject, visited, cloneObject, typeToReflect.BaseType);
|
||||
CopyFields(originalObject, visited, cloneObject, typeToReflect.BaseType, BindingFlags.Instance | BindingFlags.NonPublic, info => info.IsPrivate);
|
||||
}
|
||||
}
|
||||
|
||||
private static void CopyFields(object originalObject, IDictionary<object, object> visited, object cloneObject, Type typeToReflect, BindingFlags bindingFlags = BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.FlattenHierarchy, Func<FieldInfo, bool> filter = null)
|
||||
{
|
||||
foreach (FieldInfo fieldInfo in typeToReflect.GetFields(bindingFlags))
|
||||
{
|
||||
if (filter != null && filter(fieldInfo) == false) continue;
|
||||
if (IsPrimitive(fieldInfo.FieldType)) continue;
|
||||
var originalFieldValue = fieldInfo.GetValue(originalObject);
|
||||
var clonedFieldValue = InternalCopy(originalFieldValue, visited);
|
||||
fieldInfo.SetValue(cloneObject, clonedFieldValue);
|
||||
}
|
||||
}
|
||||
public static T Copy<T>(this T original)
|
||||
{
|
||||
return (T)Copy((Object)original);
|
||||
}
|
||||
}
|
||||
|
||||
public class ReferenceEqualityComparer : EqualityComparer<Object>
|
||||
{
|
||||
public override bool Equals(object x, object y)
|
||||
{
|
||||
return ReferenceEquals(x, y);
|
||||
}
|
||||
public override int GetHashCode(object obj)
|
||||
{
|
||||
if (obj == null) return 0;
|
||||
return obj.GetHashCode();
|
||||
}
|
||||
}
|
||||
|
||||
namespace ArrayExtensions
|
||||
{
|
||||
public static class ArrayExtensions
|
||||
{
|
||||
public static void ForEach(this Array array, Action<Array, int[]> action)
|
||||
{
|
||||
if (array.LongLength == 0) return;
|
||||
ArrayTraverse walker = new ArrayTraverse(array);
|
||||
do action(array, walker.Position);
|
||||
while (walker.Step());
|
||||
}
|
||||
}
|
||||
|
||||
internal class ArrayTraverse
|
||||
{
|
||||
public int[] Position;
|
||||
private int[] maxLengths;
|
||||
|
||||
public ArrayTraverse(Array array)
|
||||
{
|
||||
maxLengths = new int[array.Rank];
|
||||
for (int i = 0; i < array.Rank; ++i)
|
||||
{
|
||||
maxLengths[i] = array.GetLength(i) - 1;
|
||||
}
|
||||
Position = new int[array.Rank];
|
||||
}
|
||||
|
||||
public bool Step()
|
||||
{
|
||||
for (int i = 0; i < Position.Length; ++i)
|
||||
{
|
||||
if (Position[i] < maxLengths[i])
|
||||
{
|
||||
Position[i]++;
|
||||
for (int j = 0; j < i; j++)
|
||||
{
|
||||
Position[j] = 0;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user