csharp/AlenToma/EntityWorker.Core/Source/EntityWorker.Core/Object.Library/XML/XmlUtility.cs

XmlUtility.cs
using EnsatyWorker.Core.Attributes;
using FastDeepCloner;
using EnsatyWorker.Core.Helper;
using EnsatyWorker.Core.InterFace;
using EnsatyWorker.Core.SqlQuerys;
using System;
using System.Collections;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using System.Xml;

namespace EnsatyWorker.Core.Object.Library.XML
{
    internal static clast XmlUtility
    {
        /// 
        /// serialize object to xml
        /// 
        /// 
        /// 
        public static string ToXml(this object o)
        {
            string xmlResult = "";
            ToXml(o, ref xmlResult);
            var xmlDoc = new System.Xml.XmlDocameent();
            StringWriter sw = new StringWriter();
            xmlDoc.LoadXml(xmlResult);
            xmlDoc.Save(sw);
            return sw.ToString();
        }

        /// 
        /// DeSerilize Xml to object, this is supposed to handle all unknow object types but there has not been to many tests.
        /// 
        /// 
        /// 
        /// 
        public static object FromXml(this string xml, IRepository transaction = null)  
        {
            if (string.IsNullOrEmpty(xml))
                return null;
            var doc = new System.Xml.XmlDocameent();
            doc.LoadXml(xml);
            var o = FromXml(doc.DocameentElement);
            void LoadXmlIgnoreProperties(object item)
            {
                if (item is IList)
                {
                    foreach (var t in (IList)item)
                        LoadXmlIgnoreProperties(t);
                    return;
                }

                var type = item?.GetType().GetActualType();
                if (type == null)
                    return;
                if (!(item?.GetPrimaryKeyValue().ObjectIsNew() ?? true))
                {
                    var primaryId = item.GetPrimaryKeyValue();
                    foreach (var prop in DeepCloner.GetFastDeepClonerProperties(item.GetType()).Where(x => (x.ContainAttribute() || !x.IsInternalType) && !x.ContainAttribute() && x.CanRead))
                    {
                        var value = prop.GetValue(item);
                        if (prop.PropertyType == typeof(string) && string.IsNullOrEmpty(value?.ToString()))
                            value = string.Empty;
                        if (prop.IsInternalType && value == LightDataTableShared.ValueByType(prop.PropertyType)) // Value is default
                        {
                            var cmd = transaction.GetSqlCommand($"SELECT [{prop.GetPropertyName()}] FROM {type.TableName().GetName(transaction.DataBaseTypes)} WHERE [{item.GetPrimaryKey().GetPropertyName()}] = {Querys.GetValueByType(item.GetPrimaryKeyValue(), transaction.DataBaseTypes)}");
                            var data = transaction.ExecuteScalar(cmd);
                            if (data == null)
                                continue;
                            if (prop.ContainAttribute())
                                data = new DataCipher(prop.GetCustomAttribute().Key, prop.GetCustomAttribute().KeySize).Decrypt(data.ToString());
                            else if (prop.ContainAttribute() && data.ToString().IsBase64String())
                                data = MethodHelper.DecodeStringFromBase64(data.ToString());

                            prop.SetValue(item, data.ConvertValue(prop.PropertyType));
                        }
                        else if (value != null) LoadXmlIgnoreProperties(value);
                    }

                }
            }
            if (transaction != null)
                LoadXmlIgnoreProperties(o);
            return o;

        }

        /// 
        /// DeSerilize Xml to object, this is supposed to handle all unknow object types but there has not been to many tests.
        /// 
        /// 
        /// 
        /// 
        public static T FromXml(this string xml, IRepository transaction) where T : clast
        {
            if (string.IsNullOrEmpty(xml))
                return (T)(new object());
            var doc = new System.Xml.XmlDocameent();
            doc.LoadXml(xml);
            var o = (T)FromXml(doc.DocameentElement);
            void LoadXmlIgnoreProperties(object item)
            {
                if (item is IList)
                {
                    foreach (var t in (IList)item)
                        LoadXmlIgnoreProperties(t);
                    return;
                }

                var type = item?.GetType().GetActualType();
                if (type == null)
                    return;
                if (!(item?.GetPrimaryKeyValue().ObjectIsNew() ?? true))
                {
                    var primaryId = item.GetPrimaryKeyValue();
                    foreach (var prop in DeepCloner.GetFastDeepClonerProperties(item.GetType()).Where(x => (x.ContainAttribute() || !x.IsInternalType) && !x.ContainAttribute() && x.CanRead))
                    {
                        var value = prop.GetValue(item);
                        if (prop.PropertyType == typeof(string) && string.IsNullOrEmpty(value?.ToString()))
                            value = string.Empty;
                        if (prop.IsInternalType && value == LightDataTableShared.ValueByType(prop.PropertyType)) // Value is default
                        {
                            var cmd = transaction.GetSqlCommand($"SELECT [{prop.GetPropertyName()}] FROM {type.TableName().GetName(transaction.DataBaseTypes)} WHERE [{item.GetPrimaryKey().GetPropertyName()}] = {Querys.GetValueByType(item.GetPrimaryKeyValue(), transaction.DataBaseTypes)}");
                            var data = transaction.ExecuteScalar(cmd);
                            if (data == null)
                                continue;
                            if (prop.ContainAttribute())
                                data = new DataCipher(prop.GetCustomAttribute().Key, prop.GetCustomAttribute().KeySize).Decrypt(data.ToString());
                            else if (prop.ContainAttribute() && data.ToString().IsBase64String())
                                data = MethodHelper.DecodeStringFromBase64(data.ToString());

                            prop.SetValue(item, data.ConvertValue(prop.PropertyType));
                        }
                        else if (value != null) LoadXmlIgnoreProperties(value);
                    }

                }
            }
            if (transaction != null)
                LoadXmlIgnoreProperties(o);
            return o;

        }


        private static object FromXml(XmlNode doc)
        {
            var fullType = Type.GetType(doc.Attributes["FullName"].Value);
            object item = fullType.CreateInstance();
            var subtype = fullType.GetActualType();
            foreach (XmlNode chil in doc.ChildNodes)
            {
                var prop = DeepCloner.GetProperty(subtype, chil.Name);
                if (chil.Attributes["FullName"] != null && prop == null)
                {
                    if (chil.Name != "List")
                        ((IList)item).Add(FromXml(chil));

                    else foreach (var t in FromXml(chil) as IList)
                            ((IList)item).Add(t);
                    continue;
                }
                if (prop != null && prop.IsInternalType)
                    prop.SetValue(item, chil.InnerText.ConvertValue(prop.PropertyType));
                else if (chil.Attributes["FullName"] != null)
                    prop.SetValue(item, FromXml(chil));
                else ((IList)item).Add(chil.InnerText.ConvertValue(item.GetType().GetActualType()));

            }
            return item;
        }


        private static string ToXml(object o, ref string xml, bool addStart = true, string propName = "")
        {
            if (addStart)
                xml += "";
            var name = string.IsNullOrWhiteSpace(propName) ? new Regex("[^a-zA-Z]").Replace(o.GetType().Name, "") : propName;
            var quName = o.GetType().astemblyQualifiedName;

            if (o.GetType().IsInternalType())
            {
                if (o is byte[])
                    o = Convert.ToBase64String(o as byte[]);
                xml += $"{o}";
                return xml;
            }

            xml += $"";

            if (o is IList)
            {
                foreach (var item in (IList)o)
                    ToXml(item, ref xml, false);
            }
            else
            {
                foreach (var prop in DeepCloner.GetFastDeepClonerProperties(o.GetType()).Where(x => !x.ContainAttribute()))
                {
                    var value = prop.GetValue(o);
                    if (value == null)
                        continue;
                    var zName = prop.Name;

                    if (value is byte[])
                        value = Convert.ToBase64String(value as byte[]);
                    if (value.GetType().IsInternalType())
                        xml += $"{value}";
                    else ToXml(value, ref xml, false, zName);
                }
            }

            xml += $"";
            return xml;

        }
    }
}