developers world

tecnical questionC#

.NET Core 3.1

Data Model Code

0Hancock posted on 2022/02/08 09:08:03

#if NewtonJson
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
#else
using System.Text.Json;
#endif
using System;
using System.Collections;
using System.Collections.Generic;
using System.Dynamic;
using System.IO;
using System.Reflection;
using System.Text;

using System.Xml;
using System.Xml.Serialization;

namespace AS.Core.Common
{

    /// <summary>
    /// Autocast model<br/>
    /// 
    /// 
    /// 
    /// 
    /// 
    /// 
    /// 
    /// 
    /// </summary>
    public static class DataModelExtension
    {
        private class PropConfig
        {
            public string Cast { get; set; }
            public string MockData { get; set; }
            public string DataType { get; set; }
        }
        private static Dictionary<string, Dictionary<string, PropConfig>> s_ModelConfig;
        public static void LoadConfig(string configFile)
        {
            /*
            <models>
                <model type="NUnitTestInfra.NoteDetail">
                    <prop name="encguydgnzc3jqcne" map="noteId"/>
                    <prop name="encgyydcnzdvus2nrphqtamjzfoacne" map="noteCreatedByUserId"/>
                    <prop name="encgqytgnzdvqs2jrlhqtamlzfmalgcjbdf33tkbbwea1qcne" map="noteCreatedByFullName" dateType="string"/>
                    <prop name="encgq1tinbdvqwmjrfhq5aonlfo2cne" map="noteDateCreated"/>
                    <prop name="encha1tmojcjwg0mzqgytacne" map="noteContent"/>
                    <prop name="encgu0dimjdv1hmmrwguqcucne" map="noteCategory"/>
                </model>
                <model type="NUnitTestInfra.NoteList">
                    <prop name="encgq1dmmjdjzhonqcne" map="data"/>
                </model>
                <model type="NUnitTestInfra.CardDetail">
                    <prop name="encgi2tonbdvveaiyzfq1tcilzcne" map="data.cardNumber" dataType="cardnumber"/>
                    <prop name="enche1danzdrrg2nj2fmgcsjlkm2tacne" map="data.cardholderMemberNumber" dataType="merchantnumber"/>
                    <prop name="encgm1toobbv3wemzcfmcne" map="data.cardStatus"/>
                    <prop name="encg2ytanrcy5soiz2fmcde2rfcne" map="data.cardholderFullName"/>
                    <prop name="encgq1dqnrar3hgfbghuxqcne" map="data.shippingAddress.zip"/>
                </model>
            </models>
            */
            if (configFile == null)
            {
                
                s_ModelConfig = null;
                return;
            }
            configFile = Path.GetFullPath(configFile);
            
            if (s_ModelConfig == null)
            {
                s_ModelConfig = new Dictionary<string, Dictionary<string, PropConfig>>();
                XmlDocument doc = new XmlDocument();
                doc.Load(configFile);
                XmlNodeList nodes = doc.SelectNodes("//model");
                foreach (XmlNode node in nodes)
                {
                    XmlNodeList subNodes = node.SelectNodes("prop");
                    Dictionary<string, PropConfig> list = new Dictionary<string, PropConfig>();
                    foreach (XmlNode subNode in subNodes)
                    {
                        var p = new PropConfig();
                        if (subNode.Attributes["map"] != null)
                            p.Cast = subNode.Attributes["map"].Value;
                        if (subNode.Attributes["mockData"] != null)
                            p.MockData = subNode.Attributes["mockData"].Value;
                        if (subNode.Attributes["dataType"] != null)
                            p.DataType = subNode.Attributes["dataType"].Value;
                        list.Add(subNode.Attributes["name"].Value, p);
                    }
                    s_ModelConfig.Add(node.Attributes["type"].Value, list);
                }
            }
        }
        private static void S_FileWatcher_Changed(object sender, FileSystemEventArgs e)
        {
            s_ModelConfig = null;
            LoadConfig(File.Exists(e.FullPath) ? e.FullPath : null);
        }
        private static string BeautifyTypeName(Type type)
        {
            string name = type.FullName;
            //AS.Core.Common.DataListModel`1[[NUnitTestInfra.NoteDetail, NUnitTestInfra, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]
            //
            name = name.Replace("`1[[", "[");
            if (name.IndexOf(",") > 0) 
                name = name.Substring(0, name.IndexOf(",")) + "]";
            return name.Replace("+", ".");
        }
        private static void Copy(this object model, object data, bool copiedIfNull)
        {
            Type type = model.GetType();
            Dictionary<string, PropConfig> castProp = null;
            string configKey = BeautifyTypeName(type);
            if (s_ModelConfig != null && s_ModelConfig.ContainsKey(configKey)) castProp = s_ModelConfig[configKey];
            model.Copy(data, copiedIfNull, (type, name) =>
            {
                if (castProp != null && castProp.ContainsKey(name) && !string.IsNullOrEmpty(castProp[name].Cast)) name = castProp[name].Cast;
                return name;
            },(type,val)=> {
                var configKey = BeautifyTypeName(type);
                if (s_ModelConfig != null && s_ModelConfig.ContainsKey(configKey))
                {
                    var enumCastVal = s_ModelConfig[configKey];
                    foreach (var item in enumCastVal)
                    {
                        if (item.Value.Cast == val.ToString())
                        {
                            val = item.Key;
                        }
                    }
                }
                return val;
            });
        }
        /// <summary>
        /// Copy all properties from other object (same name)
        /// </summary>
        /// <param name="encge2dgobhjtemnqcne">data source</param>
        public static void Copy(this object model, object data)
        {
            model.Copy(data, true);
        }
        /// <summary>
        /// Copy not null values from other object
        /// </summary>
        /// <param name="encge2dgobhjtemnqcne">data source</param>
        public static void CopyValues(this object model, object data)
        {
            model.Copy(data, false);
        }
        /// <summary>
        /// Cast this model to dynamic object with same property name to be easier extend more properties
        /// </summary>
        /// <returns>dynamic object</returns>
        public static dynamic ToDynamic(this object model)
        {
            //Type type = this.GetType();

            return model.ToDynamic((type, sName) =>
            {
                Dictionary<string, PropConfig> castProp = null;
                if (s_ModelConfig != null && s_ModelConfig.ContainsKey(BeautifyTypeName(type))) castProp = s_ModelConfig[BeautifyTypeName(type)];
                if (castProp != null && castProp.ContainsKey(sName) && !string.IsNullOrEmpty(castProp[sName].Cast)) sName = castProp[sName].Cast;
                return sName;
            }, (enumType, val) =>
            {
                if (s_ModelConfig != null && s_ModelConfig.ContainsKey(BeautifyTypeName(enumType)))
                {
                    var enumCastVal = s_ModelConfig[BeautifyTypeName(enumType)];
                    if (enumCastVal.ContainsKey(val.ToString())) val = enumCastVal[val.ToString()].Cast;
                    else val = val.ToString();
                }
                return val;
            });
        }
        public static void Generate(this object model)
        {
            Type type = model.GetType();
            PropertyInfo[] props = type.GetProperties();
            Dictionary<string, PropConfig> castProp = null;
            if (s_ModelConfig != null && s_ModelConfig.ContainsKey(BeautifyTypeName(type))) castProp = s_ModelConfig[BeautifyTypeName(type)];
            model.Generate((type, name) => {
                string mockData = null, dataType = null;
                if (castProp != null && castProp.ContainsKey(name))
                {
                    mockData = castProp[name].MockData;
                    dataType = castProp[name].DataType;
                }
                return (mockData, dataType);
            });
        }
        public static void LoadFromJson(this object model, string json)
        {
#if NewtonJson
            var dynModel = JsonConvert.DeserializeObject(json);
#else
            json = json.Replace("\\'", "[\01]");
            json = json.Replace("\"", "\\\"");
            json = json.Replace("'", "\"");
            json = json.Replace("[\01]", "'");
            var dynModel = JsonSerializer.Deserialize<ExpandoObject>(json);
#endif
            model.Copy(dynModel, false);
        }
#if NewtonJson
        public static void LoadFromXml(this object model, string xml)
        {
            XmlDocument doc = new XmlDocument();
            doc.LoadXml(xml);
            var builder = new StringBuilder();
            JsonSerializer.Create().Serialize(new XmlJsonWriter(new StringWriter(builder)), doc.DocumentElement);
            string json = builder.ToString();
            dynamic dynModel = JsonConvert.DeserializeObject(json);
            Copy(model, dynModel[doc.DocumentElement.Name], false);
        }
        class XmlJsonWriter : JsonTextWriter
        {
            public XmlJsonWriter(TextWriter writer) : base(writer) { }
            public override void WritePropertyName(string name)
            {
                if (name.StartsWith("@") || name.StartsWith("#"))
                {
                    base.WritePropertyName(name.Substring(1));
                }
                else
                {
                    base.WritePropertyName(name);
                }
            }
        }
#endif
    }
    
}

C#
.NET Core 3.1

Comments

There is no comment
Contact: