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="encgiztomjdfgacne" map="noteId"/>
<prop name="encge1tcnrcn1dkittnfzauozxmucne" map="noteCreatedByUserId"/>
<prop name="encgiydimrcn3h0mtznjzaun15ovhdelbdgj4c2ctofvrqcne" map="noteCreatedByFullName" dateType="string"/>
<prop name="encgq2dsmrcnrdmmtdnjzawnj2micne" map="noteDateCreated"/>
<prop name="encgizdqmzcntxkj1qmfvacne" map="noteContent"/>
<prop name="encgi1dinrcnusintkmnscmcne" map="noteCategory"/>
</model>
<model type="NUnitTestInfra.NoteList">
<prop name="encg21tenrcqzciiqcne" map="data"/>
</model>
<model type="NUnitTestInfra.CardDetail">
<prop name="encgezdcnrcnswsn0jpf3t0lllcne" map="data.cardNumber" dataType="cardnumber"/>
<prop name="encgmydmmrdvuxkmlmpvmcullymj4acne" map="data.cardholderMemberNumber" dataType="merchantnumber"/>
<prop name="encg22tgmramtten1wpqcne" map="data.cardStatus"/>
<prop name="enche0tqnrc3vt0j1qpzmdcjjwcne" map="data.cardholderFullName"/>
<prop name="encgy2donbbjysgedenbrqcne" 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="encgeydcmbgrswymqcne">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="encgeydcmbgrswymqcne">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
}
}