WXMC/.svn/pristine/a8/a8399f41a7d0afa41163cfbce8c4a87eeda30e8e.svn-base

287 lines
9.9 KiB
Plaintext
Raw Normal View History

2024-12-04 16:18:46 +08:00
using CommonSerializeDefine;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Text;
using UnityEngine;
namespace CommonSerializing
{
public class Deserializer : SerializerBase, IDeserializer
{
public object DeserializeData(Type targetType, string data)
{
ITypeSerializer serializer = EnsureSerializer(targetType);
return serializer.Deserialize(data, targetType, this);
}
public object Deserialize(Type targetType, IEnumerable<KeyValuePair<string, string>> datas)
{
object rootObj = Activator.CreateInstance(targetType);
Dictionary<string, object> objects = new Dictionary<string, object>()
{
{ "", rootObj },
};
List<string> currentStack = new List<string>();
foreach (var data in datas)
{
string dataPath = data.Key;
string dataValue = data.Value;
string[] newStack = SplitPath(dataPath);
string fieldName = newStack[newStack.Length - 1];
object parentObj = EnsureParentObject(objects, newStack, newStack.Length - 1);
FieldInfo field = EnsureField(parentObj.GetType(), fieldName);
field.SetValue(parentObj, DeserializeData(field.FieldType, dataValue));
UpdateStack(currentStack, newStack, objects);
}
UpdateStack(currentStack, null, objects);
return rootObj;
}
public IEnumerable<T> Deserialize<T>(IListDataProvider datas)
{
foreach (var row in datas.Provide())
{
yield return (T)Deserialize(typeof(T), row);
}
}
public Dictionary<string, T> Deserialize<T>(IMapDataProvider datas)
{
Dictionary<string, T> result = new Dictionary<string, T>();
foreach (var row in datas.Provide())
{
result.Add(row.Key, (T)Deserialize(typeof(T), row.Value));
}
return result;
}
private object EnsureParentObject(Dictionary<string, object> objects, string[] objectPath, int objectPathCount)
{
string objectID = JoinString(".", objectPath, objectPathCount);
object parentObj;
if (objects.TryGetValue(objectID, out parentObj))
{
return parentObj;
}
string fieldName = objectPath[objectPathCount - 1];
object grantParentObj = EnsureParentObject(objects, objectPath, objectPathCount - 1);
FieldInfo field = EnsureField(grantParentObj.GetType(), fieldName);
parentObj = field.GetValue(grantParentObj);
if (parentObj == null)
{
parentObj = Activator.CreateInstance(field.FieldType);
}
if (!field.FieldType.IsValueType)
{
field.SetValue(grantParentObj, parentObj);
}
objects.Add(objectID, parentObj);
return parentObj;
}
private void UpdateStack(List<string> currentStack, string[] newStack, Dictionary<string, object> objects)
{
int lastCommonIndex = -1;
int newStackLength = newStack?.Length ?? 0;
int min = currentStack.Count < newStackLength ? currentStack.Count : newStackLength;
for (int i = 0; i < min; i++)
{
if (currentStack[i] != newStack[i])
{
break;
}
else
{
lastCommonIndex = i;
}
}
// Return to last common
for (int i = currentStack.Count - 1; i > lastCommonIndex; i--)
{
string parentObjectID = JoinString(".", currentStack, i);
string objectID = JoinString(".", currentStack, i + 1);
string fieldName = currentStack[i];
object obj;
if (!objects.TryGetValue(objectID, out obj))
{
continue;
}
object parentObj = objects[parentObjectID];
FieldInfo field = EnsureField(parentObj.GetType(), fieldName);
if (field.FieldType.IsValueType)
{
field.SetValue(parentObj, obj);
}
objects.Remove(objectID);
}
currentStack.RemoveRange(lastCommonIndex + 1, currentStack.Count - lastCommonIndex - 1);
if (newStack != null)
{
for (int i = lastCommonIndex + 1; i < newStackLength; i++)
{
currentStack.Add(newStack[i]);
}
}
}
public Dictionary<string, T> DeserializeMap<T>(IDataMatrix matrix)
{
Dictionary<string, T> result = new Dictionary<string, T>();
foreach (var item in SplitToMap(matrix))
{
result.Add(item.Key, (T)DeserializeObject(typeof(T), item.Value));
}
return result;
}
private object DeserializeObject(Type targetType, IDataMatrix matrix, object rootObj = null)
{
rootObj = rootObj ?? Activator.CreateInstance(targetType);
foreach (var subMatrix in SplitByColName(matrix))
{
string dataPath = subMatrix.GetColName(1);
string fieldName = dataPath;
FieldInfo field = EnsureField(targetType, fieldName);
Type fieldType = field.FieldType;
object fieldObj;
if (subMatrix.GetIsFinalColLayer(1))
{
fieldObj = DeserializeData(field.FieldType, subMatrix[1, 1]);
}
else if (IsOrSubclassOf(fieldType, typeof(Dictionary<,>)))
{
IDictionary fieldDict = Activator.CreateInstance(fieldType) as IDictionary;
foreach (var subItem in SplitToMap(subMatrix))
{
string key = subItem.Key;
object keyObject = DeserializeData(fieldType.GenericTypeArguments[0], key);
fieldDict.Add(keyObject, DeserializeObject(fieldType.GenericTypeArguments[1], subItem.Value));
}
fieldObj = fieldDict;
}
else if (IsOrSubclassOf(fieldType, typeof(List<>)))
{
fieldObj = null;
}
else
{
SubDataMatrix objMatrix = subMatrix;
objMatrix.OffsetLayer++;
fieldObj = DeserializeObject(field.FieldType, objMatrix, field.GetValue(rootObj));
}
field.SetValue(rootObj, fieldObj);
}
return rootObj;
}
private IEnumerable<SubDataMatrix> SplitByColName(IDataMatrix matrix)
{
int lastSameCol = 1;
string lastSameColName = matrix.GetColName(1);
for (int col = 2; col <= matrix.Columns + 1; col++)
{
if (col == matrix.Columns + 1 || matrix.GetColName(col) != lastSameColName)
{
var subMatrix = new SubDataMatrix()
{
FromDataMatrix = matrix,
OffsetRow = 0,
OffsetCol = lastSameCol - 1,
SizeRows = null,
SizeColumns = col - lastSameCol,
OffsetLayer = 0,
};
yield return subMatrix;
if (col != matrix.Columns + 1)
{
lastSameCol = col;
lastSameColName = matrix.GetColName(col);
}
}
}
}
private IEnumerable<KeyValuePair<string, IDataMatrix>> SplitToMap(IDataMatrix matrix)
{
int lastNotEmptyRow = 1;
bool waitingForYield = true;
for (int row = 2; row <= matrix.Rows + 1; row++)
{
if (row == matrix.Rows + 1 || !string.IsNullOrEmpty(matrix[row, 1]) || matrix.IsRowEmpty(row))
{
if (waitingForYield)
{
var subMatrix = new SubDataMatrix()
{
FromDataMatrix = matrix,
OffsetRow = lastNotEmptyRow - 1,
OffsetCol = 1,
SizeRows = row - lastNotEmptyRow,
SizeColumns = matrix.Columns - 1,
OffsetLayer = 1,
};
waitingForYield = false;
yield return new KeyValuePair<string, IDataMatrix>(matrix[lastNotEmptyRow, 1], subMatrix);
}
if (row == matrix.Rows + 1)
{
break;
}
if (!string.IsNullOrEmpty(matrix[row, 1]))
{
waitingForYield = true;
lastNotEmptyRow = row;
}
}
}
}
private static bool IsOrSubclassOf(Type test, Type parent)
{
if (test == parent || test.IsSubclassOf(parent))
{
return true;
}
if (test.IsGenericType)
{
Type gen = test.GetGenericTypeDefinition();
if (gen == parent || gen.IsSubclassOf(parent))
{
return true;
}
}
return false;
}
}
}