using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Reflection;
namespace RTDevSoftFucFrame
{
public interface RTAutoSaveInterface
{
string GetRTSaveObjID();
}
static public class RTAutoSaveHelp
{
public static string MakeRTSaveObjID()
{
Guid NewGuid = Guid.NewGuid();
return NewGuid.ToString();
}
}
[AttributeUsage(AttributeTargets.Field, AllowMultiple = true, Inherited = false)]
public class RTAutoSaveFieldAttribute : Attribute
{
public RTAutoSaveFieldAttribute(bool RefOtherObj, bool SaveField = true)
{
_RefOther = RefOtherObj;
_SaveThisField = SaveField;
}
private bool _RefOther = false;
public bool RefOther
{
get { return (_RefOther); }
set { _RefOther = value; }
}
private bool _SaveThisField = true;
public bool SaveThisField
{
get { return (_SaveThisField); }
set { _SaveThisField = value; }
}
}
internal class RTAnyObjectLoadInf
{
public List<Object> m_AllObj = new List<Object>();
public Dictionary<String, Object> m_AllIdAndObj = new Dictionary<String, Object>();
public RTAutoSaveInterface GetRTAutoSaveInterfaceObjFromID(string RTSaveObjID)
{
RTAutoSaveInterface RefObj = null;
for (int j = 0; j < m_AllObj.Count; j++)
{
RTAutoSaveInterface RTAutoSaveInterfaceObj = m_AllObj[j] as RTAutoSaveInterface;
if (RTAutoSaveInterfaceObj != null)
{
if (RTAutoSaveInterfaceObj.GetRTSaveObjID() == RTSaveObjID)
{
RefObj = RTAutoSaveInterfaceObj;
break;
}
}
}
return RefObj;
}
public Object GetRTObjFromID(string RTSaveObjID)
{
try
{
return m_AllIdAndObj[RTSaveObjID];
}
catch (Exception e)
{
var ex1 = new System.Exception(e.Message);
throw ex1;
}
}
public List<Object> m_ObjParentList = new List<Object>();
public List<String> m_ParNameList = new List<String>();
public List<XmlElement> m_XMLNodeList = new List<XmlElement>();
public List<bool> m_IsList = new List<bool>();
}
internal class RTSaveProperty
{
public XmlElement ParentXMLNode = null;
public XmlDocument Xmldoc = null;
}
public class RefObjIsNotRTAutoSaveInterfaceException : ApplicationException
{
public RefObjIsNotRTAutoSaveInterfaceException() { }
public RefObjIsNotRTAutoSaveInterfaceException(string message)
: base(message)
{ }
public RefObjIsNotRTAutoSaveInterfaceException(string message, Exception inner)
: base(message, inner)
{ }
}
public class RTObjectAutoSave
{
private const string RefObjAttStrFlag = "RefObjID_17CB4EAD";
private const string TrueTypeAttStrFlag = "TrueType_17CB4EAD";
private const string ValueAttStrFlag = "Value_17CB4EAD";
private const string TypeAssambleAttStrFlag = "TypeAssamble_17CB4EAD";
private const string IsClassNullAttStrFlag = "IsClassNull_17CB4EAD";
private static Boolean m_IsMakeID = false;
private static Dictionary<Object, string> m_ObjIdDict = new Dictionary<object, string>();
private static Dictionary<Object, XmlElement> m_RefObjDict = new Dictionary<object, XmlElement>();
private static RTObjectTreeNode m_ObjRootNode = new RTObjectTreeNode();
public static Boolean IsMakeID
{
get { return RTObjectAutoSave.m_IsMakeID; }
set { RTObjectAutoSave.m_IsMakeID = value; }
}
public static bool SaveRTObjectToXML(Object SaveRTAnyObject, XmlElement SaveParentXMLNode)
{
if (SaveRTAnyObject is RTAutoSaveInterface) m_IsMakeID = false;
else m_IsMakeID = true;
try
{
RTSaveProperty parentSave = new RTSaveProperty();
parentSave.ParentXMLNode = SaveParentXMLNode;
parentSave.Xmldoc = SaveParentXMLNode.OwnerDocument;
Boolean Result = SaveOneRTObject(parentSave, SaveRTAnyObject);
if (m_IsMakeID)
foreach (Object Obj in m_RefObjDict.Keys)
{
if (m_ObjIdDict.Keys.Contains(Obj))
m_RefObjDict[Obj].Attributes[RefObjAttStrFlag].Value = m_ObjIdDict[Obj];
}
return Result;
}
catch (RefObjIsNotRTAutoSaveInterfaceException ex)
{
var ex1 = new System.Exception(ex.Message);
throw ex1;
}
finally { }
}
public static bool LoadRTObjectFromXML(Object SaveRTAnyObject, XmlElement LoadParentXMLNode)
{
if (SaveRTAnyObject is RTAutoSaveInterface) m_IsMakeID = false;
else m_IsMakeID = true;
RTSaveProperty parentSave = new RTSaveProperty();
parentSave.ParentXMLNode = LoadParentXMLNode;
parentSave.Xmldoc = LoadParentXMLNode.OwnerDocument;
return LoadRTObject(parentSave, SaveRTAnyObject);
}
private static bool SaveOneRTObject(RTSaveProperty parentSave, Object SaveRTAnyObject)
{
Type ClassType = SaveRTAnyObject.GetType();
return SaveRTParWithType(parentSave, SaveRTAnyObject, ClassType);
}
delegate bool SaveParDelagate(XmlElement ParXMLNode, Object SavePar, Type SaveParType);
private static bool SaveRTParWithType(RTSaveProperty parentSave, Object SaveRTAnyObject, Type ClassType)
{
Type BaseClassType = ClassType.BaseType;
RTSaveProperty BaseSaveProperty = Copy(parentSave);
if (BaseClassType != null && BaseClassType.FullName != "System.Object" && !BaseClassType.Name.Contains("`"))
{
XmlElement NewNode = parentSave.Xmldoc.CreateElement("BaseClass_" + BaseClassType.Name);
XmlAttribute RTObjID = parentSave.Xmldoc.CreateAttribute("m_RTObjID_17CB4EAD");
RTObjID.Value = "";
if (m_IsMakeID && !m_ObjIdDict.Keys.Contains(SaveRTAnyObject))
{
RTObjID.Value = RTAutoSaveHelp.MakeRTSaveObjID();
NewNode.Attributes.Append(RTObjID);
m_ObjIdDict.Add(SaveRTAnyObject, RTObjID.Value);
}
BaseSaveProperty.ParentXMLNode = NewNode;
parentSave.ParentXMLNode.AppendChild(NewNode);
SaveRTParWithType(BaseSaveProperty, SaveRTAnyObject, BaseClassType);
}
FieldInfo[] myFields = ClassType.GetFields(BindingFlags.Public | BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.DeclaredOnly);
for (int i = 0; i < myFields.Length; i++)
{
string ParName = myFields[i].Name;
object ParVal = myFields[i].GetValue(SaveRTAnyObject);
if (ParVal == null)
{
parentSave.ParentXMLNode.SetAttribute(ParName, "null");
continue;
}
Type ParType = null;
try
{
ParType = ParVal.GetType();
}
catch (Exception ex)
{
ex = new RefObjIsNotRTAutoSaveInterfaceException(ClassType.FullName + "中的变量:" +
ParName + "以RTAutoSaveField特征标记引用方式引用了非RTAutoSaveInterface变量");
throw ex;
}
bool IsRefOther = false;
bool SaveThisField = true;
object[] attrs111 = myFields[i].GetCustomAttributes(true);
foreach (object obj in attrs111)
{
RTAutoSaveFieldAttribute att = obj as RTAutoSaveFieldAttribute;
if (att != null)
{
IsRefOther = att.RefOther;
SaveThisField = att.SaveThisField;
}
}
if (!SaveThisField)
{
continue;
}
SaveParDelagate SaveParDelagateObj = delegate(XmlElement ParXMLNode, Object SaveParVal, Type SaveParType)
{
if (IsRefOther)
{
if (!m_IsMakeID)
{
RTAutoSaveInterface ItemFDD = SaveParVal as RTAutoSaveInterface;
if (ItemFDD == null)
{
var ex = new RefObjIsNotRTAutoSaveInterfaceException(ClassType.FullName + "中的变量:" +
ParName + "以RTAutoSaveField特征标记引用方式引用了非RTAutoSaveInterface变量");
throw ex;
}
ParXMLNode.SetAttribute(RefObjAttStrFlag, (SaveParVal as RTAutoSaveInterface).GetRTSaveObjID());
}
else
{
if (!m_ObjIdDict.Keys.Contains(SaveParVal))
{
if (!m_RefObjDict.ContainsKey(SaveParVal))
m_RefObjDict.Add(SaveParVal, ParXMLNode);
ParXMLNode.SetAttribute(RefObjAttStrFlag, null);
}
else
{
ParXMLNode.SetAttribute(RefObjAttStrFlag, m_ObjIdDict[SaveParVal]);
}
}
}
else
{
ParXMLNode.SetAttribute(TrueTypeAttStrFlag, SaveParType.FullName);
ParXMLNode.SetAttribute(TypeAssambleAttStrFlag, SaveParType.Assembly.ManifestModule.Name);
RTSaveProperty NewFIDSaveProperty = Copy(parentSave);
NewFIDSaveProperty.ParentXMLNode = ParXMLNode;
SaveOneRTObject(NewFIDSaveProperty, SaveParVal);
}
return true;
};
if (!ParType.IsClass || ParType.FullName == "System.String")
{
if (!ParName.Contains("17CB4EAD"))
parentSave.ParentXMLNode.SetAttribute(ParName, ParVal.ToString());
}
else if (ParType.FullName.Contains(@"System.Collections.Generic"))
{
Type[] ListGenTypes = ParType.GetGenericArguments();
Type GenType = ListGenTypes[0];
XmlElement NewNode = parentSave.Xmldoc.CreateElement(ParName);
dynamic ListObj = ParVal;
for (int j = 0; j < ListObj.Count; j++)
{
XmlElement NewNode2 = parentSave.Xmldoc.CreateElement(ParName + "_One");
Object ItemObj = ListObj[j] as Object;
if(ItemObj != null)
{
Type ItemObjType = ItemObj.GetType();
if (!ItemObjType.IsClass || ParType.FullName == "System.String")
{
Type ListParType = ListObj[j].GetType();
if (!ListParType.IsClass || ListParType.FullName == "System.String")
{
NewNode2.SetAttribute(TrueTypeAttStrFlag, ListParType.FullName);
NewNode2.SetAttribute(ValueAttStrFlag, ListObj[j].ToString());
}
else
{
continue;
}
}
else
{
SaveParDelagateObj(NewNode2, ItemObj, ItemObjType);
}
}
else
{
NewNode2.SetAttribute(IsClassNullAttStrFlag, "true");
}
NewNode.AppendChild(NewNode2);
}
parentSave.ParentXMLNode.AppendChild(NewNode);
}
else if (ParType.IsClass)
{
XmlElement NewNode = parentSave.Xmldoc.CreateElement(ParName);
if (ParVal == null)
{
continue;
}
SaveParDelagateObj(NewNode, ParVal, ParType);
parentSave.ParentXMLNode.AppendChild(NewNode);
}
}
return true;
}
private static bool LoadRTObject(RTSaveProperty parentSave, Object SaveRTAnyObject)
{
Type ClassType = SaveRTAnyObject.GetType();
RTAnyObjectLoadInf AllLoadInf = new RTAnyObjectLoadInf();
bool IsLoadOK = LoadRTParWithType(parentSave, SaveRTAnyObject, ClassType, AllLoadInf);
bool IsTwoOK = TwoStepDo(AllLoadInf);
return IsLoadOK && IsTwoOK;
}
private static Object ParseStringToValueObj(string ValueStr, Type ValueType)
{
Object ValueObj = null;
if (ValueStr.Equals("")) return null;
if (ValueType.IsEnum)
{
ValueObj = Enum.Parse(ValueType, ValueStr);
}
else if (ValueType.IsValueType)
{
Type[] FunParTypes = new Type[1];
FunParTypes[0] = typeof(string);
var ValMethod = ValueType.GetMethod("Parse", FunParTypes);
object TemSimpleObj = ValueType.Assembly.CreateInstance(ValueType.FullName);
object ReVal = ValMethod.Invoke(TemSimpleObj, new object[] { ValueStr });
ValueObj = ReVal;
}
else
{
ValueObj = ValueStr;
}
return ValueObj;
}
private static Object CreateClassObjFromSaveXMLNode(XmlElement ThisFieldNode)
{
Object ParVal = null;
if (ThisFieldNode != null)
{
string TrueTypeFullName = ThisFieldNode.GetAttribute(TrueTypeAttStrFlag);
string AssambleModuleName = ThisFieldNode.GetAttribute(TypeAssambleAttStrFlag);
if (!string.IsNullOrEmpty(TrueTypeFullName) && !string.IsNullOrEmpty(TrueTypeFullName))
{
Assembly ParDefAsmb = Assembly.LoadFrom(AssambleModuleName);
dynamic ParTrueobj = null;
if (TrueTypeFullName.Equals("System.Double[]"))
{
ParTrueobj = Array.CreateInstance(typeof(Double), 100);
}
else if (TrueTypeFullName.Equals("System.String"))
{
ParTrueobj = Activator.CreateInstance(typeof(String), new char[]{' '});
}
else
{
ParTrueobj = ParDefAsmb.CreateInstance(TrueTypeFullName, true);
}
if (ParTrueobj != null)
{
ParVal = ParTrueobj;
}
}
else
{
string RefObjId = ThisFieldNode.GetAttribute(RefObjAttStrFlag);
XmlDocument XmlDoc = ThisFieldNode.OwnerDocument;
XmlNode FindNode = null;
FindNode = SearchNode(XmlDoc.FirstChild, RefObjId, FindNode);
if (FindNode != null)
{
return CreateClassObjFromSaveXMLNode(FindNode as XmlElement);
}
}
}
return ParVal;
}
private static bool LoadRTParWithType(RTSaveProperty parentSave, Object SaveRTAnyObject, Type ClassType, RTAnyObjectLoadInf AllLoadInf, bool BaseCal = false)
{
Type BaseClassType = ClassType.BaseType;
if (!BaseCal)
{
AllLoadInf.m_AllObj.Add(SaveRTAnyObject);
}
RTSaveProperty BaseSaveProperty = Copy(parentSave);
if (BaseClassType.FullName != "System.Object")
{
if (parentSave.ParentXMLNode == null) return false;
XmlElement SelNode = (XmlElement)parentSave.ParentXMLNode.SelectSingleNode("BaseClass_" + BaseClassType.Name);
BaseSaveProperty.ParentXMLNode = SelNode;
LoadRTParWithType(BaseSaveProperty, SaveRTAnyObject, BaseClassType, AllLoadInf, true);
}
FieldInfo[] AllFields = ClassType.GetFields(BindingFlags.Public | BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.DeclaredOnly);
for (int i = 0; i < AllFields.Length; i++)
{
bool IsRefOtherObj = false;
bool SaveThisField = true;
{
object[] FieldAttrs = AllFields[i].GetCustomAttributes(true);
foreach (object obj in FieldAttrs)
{
RTAutoSaveFieldAttribute att = obj as RTAutoSaveFieldAttribute;
if (att != null)
{
IsRefOtherObj = att.RefOther;
SaveThisField = att.SaveThisField;
}
}
}
if (!SaveThisField)
{
continue;
}
string ParName = AllFields[i].Name;
string ParAttributeVal = parentSave.ParentXMLNode.GetAttribute(ParName);
if (ParAttributeVal == "null")
{
AllFields[i].SetValue(SaveRTAnyObject, null);
continue;
}
Object ParVal = null;
{
{
XmlElement ThisFieldNode = (XmlElement)parentSave.ParentXMLNode.SelectSingleNode(ParName);
if (ThisFieldNode != null)
{
ParVal = CreateClassObjFromSaveXMLNode(ThisFieldNode);
}
}
if (ParVal == null)
{
ParVal = AllFields[i].GetValue(SaveRTAnyObject);
}
else
{
AllFields[i].SetValue(SaveRTAnyObject, ParVal);
}
}
Type ParType = null;
try
{
if (ParVal == null) continue;
ParType = ParVal.GetType();
}
catch (Exception e)
{
var ex = new RefObjIsNotRTAutoSaveInterfaceException(ClassType.FullName + "中的变量:" +
ParName + "以RTAutoSaveField特征标记引用方式引用了非RTAutoSaveInterface变量");
throw ex;
}
if (!ParType.IsClass || ParType.FullName == "System.String")
{
string SaveVal = parentSave.ParentXMLNode.GetAttribute(ParName);
Object ValueObj = ParseStringToValueObj(SaveVal, ParType);
AllFields[i].SetValue(SaveRTAnyObject, ValueObj);
}
else if (ParType.FullName.StartsWith(@"System.Collections.Generic.List`1"))
{
Type[] ListGenTypes = ParType.GetGenericArguments();
Type GenType = ListGenTypes[0];
XmlElement SelNode = (XmlElement)parentSave.ParentXMLNode.SelectSingleNode(ParName);
if (!IsRefOtherObj)
{
for (int j = 0; j < SelNode.ChildNodes.Count; j++)
{
XmlElement SelNode2 = SelNode.ChildNodes[j] as XmlElement;
string ListValueStr = SelNode2.GetAttribute(ValueAttStrFlag);
string IsNullStr = SelNode2.GetAttribute(IsClassNullAttStrFlag);
object NewListObj = null;
if (IsNullStr == "true")
{
NewListObj = null;
}
else
{
if (!string.IsNullOrEmpty(ListValueStr))
{
string TrueTypeFullName = SelNode2.GetAttribute(TrueTypeAttStrFlag);
Type ListItemTrueType = Type.GetType(TrueTypeFullName);
NewListObj = ParseStringToValueObj(ListValueStr, ListItemTrueType);
}
else
{
Object NewListMemberObj = null;
{
NewListMemberObj = CreateClassObjFromSaveXMLNode(SelNode2);
if (NewListMemberObj == null)
{
Type[] tps = new Type[0];
object[] obj = new object[0];
NewListMemberObj = GenType.GetConstructor(tps).Invoke(obj) as Object;
}
}
{
RTSaveProperty NewFIDSaveProperty = Copy(parentSave);
NewFIDSaveProperty.ParentXMLNode = SelNode2;
LoadRTParWithType(NewFIDSaveProperty, NewListMemberObj, GenType, AllLoadInf);
}
NewListObj = NewListMemberObj;
}
}
var addMethod = ParType.GetMethod("Add");
addMethod.Invoke((object)ParVal, new object[] { NewListObj });
}
}
else
{
AllLoadInf.m_ObjParentList.Add(SaveRTAnyObject);
AllLoadInf.m_ParNameList.Add(ParName);
AllLoadInf.m_XMLNodeList.Add(SelNode);
AllLoadInf.m_IsList.Add(true);
}
}
else if (ParType.IsClass)
{
if (ParVal == null)
{
AllFields[i].SetValue(SaveRTAnyObject, ParVal);
continue;
}
else
{
XmlElement NewNode = (XmlElement)parentSave.ParentXMLNode.SelectSingleNode(ParName);
if (IsRefOtherObj)
{
AllLoadInf.m_ObjParentList.Add(SaveRTAnyObject);
AllLoadInf.m_ParNameList.Add(ParName);
AllLoadInf.m_XMLNodeList.Add(NewNode);
AllLoadInf.m_IsList.Add(false);
}
else
{
{
AllFields[i].SetValue(SaveRTAnyObject, ParVal);
if (m_IsMakeID)
{
String RefObjID = (from Par in m_ObjIdDict.Keys
where ParType == Par.GetType()
select m_ObjIdDict[Par]).FirstOrDefault();
if (RefObjID != null && !AllLoadInf.m_AllIdAndObj.Keys.Contains(RefObjID))
AllLoadInf.m_AllIdAndObj.Add(RefObjID, ParVal);
}
RTSaveProperty NewFIDSaveProperty = Copy(parentSave);
NewFIDSaveProperty.ParentXMLNode = NewNode;
LoadRTParWithType(NewFIDSaveProperty, ParVal, ParType, AllLoadInf);
}
}
}
}
}
return true;
}
private static bool TwoStepDo(RTAnyObjectLoadInf AllLoadInf)
{
for (int i = 0; i < AllLoadInf.m_ObjParentList.Count && i < AllLoadInf.m_ParNameList.Count && i < AllLoadInf.m_XMLNodeList.Count && i < AllLoadInf.m_IsList.Count; i++)
{
Type ParentType = AllLoadInf.m_ObjParentList[i].GetType();
FieldInfo ParFieldInfo = ParentType.GetField(AllLoadInf.m_ParNameList[i], BindingFlags.Public | BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.DeclaredOnly);
Type ParType = ParFieldInfo.FieldType;
if (!AllLoadInf.m_IsList[i])
{
string RefObjID = AllLoadInf.m_XMLNodeList[i].GetAttribute(RefObjAttStrFlag);
Object RefObj = null;
if (!m_IsMakeID)
{
RefObj = AllLoadInf.GetRTAutoSaveInterfaceObjFromID(RefObjID) as RTAutoSaveInterface;
}
else
{
RefObj = AllLoadInf.GetRTObjFromID(RefObjID);
}
if (RefObj != null)
{
ParFieldInfo.SetValue(AllLoadInf.m_ObjParentList[i], RefObj);
}
}
else
{
XmlElement SelNode = AllLoadInf.m_XMLNodeList[i];
object ParVal = ParFieldInfo.GetValue(AllLoadInf.m_ObjParentList[i]);
dynamic FDD = ParVal;
for (int j = 0; j < SelNode.ChildNodes.Count; j++)
{
XmlElement SelNode2 = SelNode.ChildNodes[j] as XmlElement;
string RefObjID = SelNode2.GetAttribute(RefObjAttStrFlag);
Object RefObj = null;
if (!m_IsMakeID)
{
RefObj = AllLoadInf.GetRTAutoSaveInterfaceObjFromID(RefObjID) as RTAutoSaveInterface;
}
else
{
RefObj = AllLoadInf.GetRTObjFromID(RefObjID);
}
if (RefObj != null)
{
var addMethod = ParType.GetMethod("Add");
addMethod.Invoke((object)ParVal, new object[] { RefObj });
}
}
}
}
return true;
}
private static XmlNode SearchNode(XmlNode Node, string RefObjId, XmlNode FindNode)
{
if (RefObjId == "") return null;
for (int i = 0; i < Node.Attributes.Count; i++)
{
if (Node.Name.StartsWith("BaseClass") && Node.Attributes[i].Value.Equals(RefObjId))
{
FindNode = Node.ParentNode;
break;
}
}
if (Node.ChildNodes.Count > 0)
{
foreach (XmlNode Child in Node.ChildNodes)
{
XmlNode Temp = SearchNode(Child, RefObjId, FindNode);
if (Temp != null) FindNode = Temp;
}
}
return FindNode;
}
private static RTSaveProperty Copy(RTSaveProperty rth)
{
RTSaveProperty NewFIDSaveProperty = new RTSaveProperty();
NewFIDSaveProperty.Xmldoc = rth.Xmldoc;
NewFIDSaveProperty.ParentXMLNode = rth.ParentXMLNode;
return NewFIDSaveProperty;
}
}
public class RTCloneHelp
{
public static Boolean IsMakeID
{
get { return RTObjectAutoSave.IsMakeID; }
set { RTObjectAutoSave.IsMakeID = value; }
}
public static Object DeepClone(Object rthAnyObject)
{
XmlDocument Tem1 = new XmlDocument();
XmlElement Ele1 = Tem1.CreateElement("Root");
Tem1.AppendChild(Ele1);
RTObjectAutoSave.SaveRTObjectToXML(rthAnyObject, Ele1);
Type ThisType = rthAnyObject.GetType();
Object ParTrueobj = Activator.CreateInstance(ThisType, true);
RTObjectAutoSave.LoadRTObjectFromXML(ParTrueobj, Ele1);
return ParTrueobj;
}
}
public class RTAnyObject : RTAutoSaveInterface
{
public RTAnyObject()
{
m_RTObjID = RTAutoSaveHelp.MakeRTSaveObjID();
}
private string m_RTObjID = "";
public string GetRTSaveObjID()
{
return m_RTObjID;
}
}
public class RTObjectTreeNode
{
public String NodeID = "";
public Object NodeObj = null;
public XmlElement NodeXmlEle = null;
public RTObjectTreeNode Parent = null;
public List<RTObjectTreeNode> Children = new List<RTObjectTreeNode>();
}
}