| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314 |
- using System.Collections;
- using System.Dynamic;
- using System.Reflection;
- using System.Runtime.Serialization.Json;
- using System.Text;
- using Masuit.Tools;
- using System.Xml.Linq;
- using System.Xml;
- using System.Text.Json;
- namespace EasyTemplate.Tool;
- public sealed class Clay : DynamicObject, IEnumerable
- {
- //
- // 摘要:
- // JSON 类型
- private enum JsonType
- {
- @string,
- number,
- boolean,
- @object,
- array,
- @null
- }
- //
- // 摘要:
- // JSON 类型
- private readonly JsonType jsonType;
- //
- // 摘要:
- // 校验 Xml 标签格式
- private static readonly Func<string, Exception> TryVerifyNCName = (Func<string, Exception>)Delegate.CreateDelegate(typeof(Func<string, Exception>), typeof(XmlConvert).GetMethod("TryVerifyNCName", BindingFlags.Static | BindingFlags.NonPublic));
- //
- // 摘要:
- // 将被转换成字符串的类型
- private static readonly Type[] ToBeConvertStringTypes = new Type[1] { typeof(DateTimeOffset) };
- //
- // 摘要:
- // 是否是 Object 类型
- public bool IsObject => jsonType == JsonType.@object;
- //
- // 摘要:
- // 是否是 Array 类型
- public bool IsArray => jsonType == JsonType.array;
- //
- // 摘要:
- // 粘土对象 Xml 元数据
- public XElement XmlElement { get; private set; }
- //
- // 摘要:
- // 当 Clay 时 数组类型时的长度
- public int Length => XmlElement.Elements().Count();
- //
- // 摘要:
- // 配置读取不存在 Key 时行为
- //
- // 言论:
- // 如果设置 false,那么返回 null
- public bool ThrowOnUndefined { get; set; } = true;
- //
- // 摘要:
- // 构造函数
- //
- // 参数:
- // throwOnUndefined:
- // 如果设置 false,则读取不存在的值返回 null,默认 true
- public Clay(bool throwOnUndefined = true)
- {
- XmlElement = new XElement("root", CreateTypeAttr(JsonType.@object));
- jsonType = JsonType.@object;
- ThrowOnUndefined = throwOnUndefined;
- }
- //
- // 摘要:
- // 构造函数
- //
- // 参数:
- // element:
- // System.Xml.Linq.XElement
- //
- // type:
- // JSON 类型
- //
- // throwOnUndefined:
- // 如果设置 false,则读取不存在的值返回 null,默认 true
- private Clay(XElement element, JsonType type, bool throwOnUndefined = true)
- {
- XmlElement = element;
- jsonType = type;
- ThrowOnUndefined = throwOnUndefined;
- }
- //
- // 摘要:
- // 创建空的粘土对象
- //
- // 参数:
- // throwOnUndefined:
- // 如果设置 false,则读取不存在的值返回 null,默认 true
- //
- // 返回结果:
- // Furion.ClayObject.Clay
- public static dynamic Object(bool throwOnUndefined = true)
- {
- return new Clay(throwOnUndefined);
- }
- //
- // 摘要:
- // 基于现有对象创建粘土对象
- //
- // 参数:
- // obj:
- // 对象
- //
- // throwOnUndefined:
- // 如果设置 false,则读取不存在的值返回 null,默认 true
- //
- // 返回结果:
- // Furion.ClayObject.Clay
- public static dynamic Object(object obj, bool throwOnUndefined = true)
- {
- if (obj == null)
- {
- throw new ArgumentNullException("obj");
- }
- return Parse(CreateJsonString(new XStreamingElement("root", CreateTypeAttr(GetJsonType(obj)), CreateJsonNode(obj))), throwOnUndefined);
- }
- //
- // 摘要:
- // 基于现有对象创建粘土对象
- //
- // 参数:
- // json:
- // JSON 字符串
- //
- // throwOnUndefined:
- // 如果设置 false,则读取不存在的值返回 null,默认 true
- //
- // 返回结果:
- // Furion.ClayObject.Clay
- public static dynamic Parse(string json, bool throwOnUndefined = true)
- {
- return Parse(json, Encoding.UTF8, throwOnUndefined);
- }
- //
- // 摘要:
- // 基于现有对象创建粘土对象
- //
- // 参数:
- // json:
- // JSON 字符串
- //
- // encoding:
- // 编码类型
- //
- // throwOnUndefined:
- // 如果设置 false,则读取不存在的值返回 null,默认 true
- //
- // 返回结果:
- // Furion.ClayObject.Clay
- public static dynamic Parse(string json, Encoding encoding, bool throwOnUndefined = true)
- {
- using XmlDictionaryReader reader = JsonReaderWriterFactory.CreateJsonReader(encoding.GetBytes(json), XmlDictionaryReaderQuotas.Max);
- return ToValue(XElement.Load(reader), throwOnUndefined);
- }
- //
- // 摘要:
- // 基于 Stream 对象创建粘土对象
- //
- // 参数:
- // stream:
- // System.IO.Stream
- //
- // throwOnUndefined:
- // 如果设置 false,则读取不存在的值返回 null,默认 true
- //
- // 返回结果:
- // Furion.ClayObject.Clay
- public static dynamic Parse(Stream stream, bool throwOnUndefined = true)
- {
- using XmlDictionaryReader reader = JsonReaderWriterFactory.CreateJsonReader(stream, XmlDictionaryReaderQuotas.Max);
- return ToValue(XElement.Load(reader), throwOnUndefined);
- }
- //
- // 摘要:
- // 基于 Stream 对象创建粘土对象
- //
- // 参数:
- // stream:
- // System.IO.Stream
- //
- // encoding:
- // 编码类型
- //
- // throwOnUndefined:
- // 如果设置 false,则读取不存在的值返回 null,默认 true
- //
- // 返回结果:
- // Furion.ClayObject.Clay
- public static dynamic Parse(Stream stream, Encoding encoding, bool throwOnUndefined = true)
- {
- using XmlDictionaryReader reader = JsonReaderWriterFactory.CreateJsonReader(stream, encoding, XmlDictionaryReaderQuotas.Max, delegate
- {
- });
- return ToValue(XElement.Load(reader), throwOnUndefined);
- }
- //
- // 摘要:
- // 重写动态调用方法实现删除行为
- //
- // 参数:
- // binder:
- //
- // args:
- //
- // result:
- public override bool TryInvoke(InvokeBinder binder, object[] args, out object result)
- {
- result = (IsArray ? Delete((int)args[0]) : Delete((string)args[0]));
- return true;
- }
- //
- // 摘要:
- // 重写动态调用成员名称方法实现键是否存在行为
- //
- // 参数:
- // binder:
- //
- // args:
- //
- // result:
- public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result)
- {
- if (args.Length != 0)
- {
- result = null;
- return false;
- }
- result = IsDefined(binder.Name);
- return true;
- }
- //
- // 摘要:
- // 重写类型转换方法实现粘土对象动态转换
- //
- // 参数:
- // binder:
- //
- // result:
- public override bool TryConvert(ConvertBinder binder, out object result)
- {
- if (binder.Type == typeof(IEnumerable) || binder.Type == typeof(object[]))
- {
- IEnumerable<object> enumerable = (IEnumerable<object>)(IsArray ? ((IEnumerable)(from x in XmlElement.Elements()
- select ToValue(x, ThrowOnUndefined))) : ((IEnumerable)XmlElement.Elements().Select((Func<XElement, object>)((XElement x) => new KeyValuePair<string, object>((x.Name == "{item}item") ? x.Attribute("item").Value : x.Name.LocalName, ToValue(x, ThrowOnUndefined))))));
- IEnumerable<object> enumerable2;
- if (!(binder.Type == typeof(object[])))
- {
- enumerable2 = enumerable;
- }
- else
- {
- IEnumerable<object> enumerable3 = enumerable.ToArray();
- enumerable2 = enumerable3;
- }
- result = enumerable2;
- }
- else
- {
- result = Deserialize(binder.Type);
- }
- return true;
- }
- //
- // 摘要:
- // 重写根据索引获取值的行为
- //
- // 参数:
- // binder:
- //
- // indexes:
- //
- // result:
- public override bool TryGetIndex(GetIndexBinder binder, object[] indexes, out object result)
- {
- bool isValid;
- if (!IsArray)
- {
- return TryGet(FindXElement((string)indexes[0], out isValid), out result, ThrowOnUndefined);
- }
- return TryGet(XmlElement.Elements().ElementAtOrDefault((int)indexes[0]), out result, ThrowOnUndefined);
- }
- //
- // 摘要:
- // 重写根据成员名称获取值的行为
- //
- // 参数:
- // binder:
- //
- // result:
- public override bool TryGetMember(GetMemberBinder binder, out object result)
- {
- bool isValid;
- if (!IsArray)
- {
- return TryGet(FindXElement(binder.Name, out isValid), out result, ThrowOnUndefined);
- }
- return TryGet(XmlElement.Elements().ElementAtOrDefault(int.Parse(binder.Name)), out result, ThrowOnUndefined);
- }
- //
- // 摘要:
- // 重写根据索引设置值的行为
- //
- // 参数:
- // binder:
- //
- // indexes:
- //
- // value:
- public override bool TrySetIndex(SetIndexBinder binder, object[] indexes, object value)
- {
- if (!IsArray)
- {
- return TrySet((string)indexes[0], value);
- }
- return TrySet((int)indexes[0], value);
- }
- //
- // 摘要:
- // 重写根据成员名称设置值的行为
- //
- // 参数:
- // binder:
- //
- // value:
- public override bool TrySetMember(SetMemberBinder binder, object value)
- {
- if (!IsArray)
- {
- return TrySet(binder.Name, value);
- }
- return TrySet(int.Parse(binder.Name), value);
- }
- //
- // 摘要:
- // 重写获取所有动态成员名称行为
- public override IEnumerable<string> GetDynamicMemberNames()
- {
- if (!IsArray)
- {
- return from x in XmlElement.Elements()
- select (!(x.Name == "{item}item")) ? x.Name.LocalName : x.Attribute("item").Value;
- }
- return XmlElement.Elements().Select((XElement x, int i) => i.ToString());
- }
- //
- // 摘要:
- // 重写转换成字符串方法
- public override string ToString()
- {
- foreach (XElement item in from x in XmlElement.Descendants()
- where x.Attribute("type").Value == "null"
- select x)
- {
- item.RemoveNodes();
- }
- return CreateJsonString(new XStreamingElement("root", CreateTypeAttr(jsonType), XmlElement.Elements()));
- }
- //
- // 摘要:
- // 判断对象键是否存在
- //
- // 参数:
- // name:
- public bool IsDefined(string name)
- {
- bool isValid;
- if (IsObject)
- {
- return FindXElement(name, out isValid) != null;
- }
- return false;
- }
- //
- // 摘要:
- // 判断数组索引是否存在
- //
- // 参数:
- // index:
- public bool IsDefined(int index)
- {
- if (IsArray)
- {
- return XmlElement.Elements().ElementAtOrDefault(index) != null;
- }
- return false;
- }
- //
- // 摘要:
- // 根据键删除对象属性
- //
- // 参数:
- // name:
- public bool Delete(string name)
- {
- bool isValid;
- XElement xElement = FindXElement(name, out isValid);
- if (xElement != null)
- {
- xElement.Remove();
- return true;
- }
- return false;
- }
- //
- // 摘要:
- // 根据索引删除数组元素
- //
- // 参数:
- // index:
- public bool Delete(int index)
- {
- XElement xElement = XmlElement.Elements().ElementAtOrDefault(index);
- if (xElement != null)
- {
- xElement.Remove();
- return true;
- }
- return false;
- }
- //
- // 摘要:
- // 将粘土对象反序列化为特定类型
- //
- // 类型参数:
- // T:
- public T Deserialize<T>()
- {
- return (T)Deserialize(typeof(T));
- }
- //
- // 摘要:
- // 将粘土对象转换为 object 类型
- public object Solidify()
- {
- return Solidify<object>();
- }
- //
- // 摘要:
- // 将粘土对象转换为特定类型
- //
- // 类型参数:
- // T:
- public T Solidify<T>()
- {
- //return JSON.Deserialize<T>(ToString());
- return ToString().ToEntity<T>();
- }
- //
- // 摘要:
- // 将粘土对象转换为字典类型
- public IDictionary<string, object> ToDictionary()
- {
- if (IsArray)
- {
- throw new InvalidOperationException("Cannot convert a clay object with JsonType as an array to a dictionary object.");
- }
- Dictionary<string, object> dictionary = new Dictionary<string, object>();
- IEnumerator enumerator = GetEnumerator();
- try
- {
- while (enumerator.MoveNext())
- {
- KeyValuePair<string, object> keyValuePair = (KeyValuePair<string, object>)enumerator.Current;
- dictionary[keyValuePair.Key] = keyValuePair.Value;
- }
- return dictionary;
- }
- finally
- {
- IDisposable disposable = enumerator as IDisposable;
- if (disposable != null)
- {
- disposable.Dispose();
- }
- }
- }
- //
- // 摘要:
- // 转换成特定对象
- //
- // 参数:
- // valueProvider:
- // 值提供器
- //
- // 类型参数:
- // T:
- public IEnumerable<T> ConvertTo<T>(Func<PropertyInfo, object, object> valueProvider = null) where T : class, new()
- {
- IEnumerable<PropertyInfo> enumerable = from p in typeof(T).GetProperties(BindingFlags.Instance | BindingFlags.Public)
- where p.CanWrite
- select p;
- List<T> list = new List<T>();
- if (IsObject)
- {
- list.Add(ConvertTo<T>(enumerable, (dynamic)this, valueProvider));
- return list;
- }
- if (IsArray)
- {
- foreach (dynamic item in AsEnumerator<object>())
- {
- list.Add(ConvertTo<T>(enumerable, item, valueProvider));
- }
- }
- return list;
- }
- //
- // 摘要:
- // 将粘土对象转换为特定类型
- //
- // 参数:
- // properties:
- //
- // clay:
- //
- // valueProvider:
- // 值提供器
- //
- // 类型参数:
- // T:
- private static T ConvertTo<T>(IEnumerable<PropertyInfo> properties, dynamic clay, Func<PropertyInfo, object, object> valueProvider = null) where T : class, new()
- {
- T val = new T();
- foreach (PropertyInfo property in properties)
- {
- object obj = ((clay.IsDefined(property.Name)) ? clay[property.Name] : null);
- if (valueProvider != null)
- {
- obj = valueProvider(property, obj);
- }
- property.SetValue(val, obj.ChangeType(property.PropertyType));
- }
- return val;
- }
- //
- // 摘要:
- // XElement 对象转换成 C# 对象
- //
- // 参数:
- // element:
- //
- // throwOnUndefined:
- // 如果设置 false,则读取不存在的值返回 null,默认 true
- private static dynamic ToValue(XElement element, bool throwOnUndefined = true)
- {
- JsonType jsonType = (JsonType)Enum.Parse(typeof(JsonType), element.Attribute("type").Value);
- switch (jsonType)
- {
- case JsonType.boolean:
- return (bool)element;
- case JsonType.number:
- if (element.Value.Contains('.'))
- {
- return (double)element;
- }
- return (long)element;
- case JsonType.@string:
- return (string?)element;
- case JsonType.@object:
- case JsonType.array:
- return new Clay(element, jsonType, throwOnUndefined);
- default:
- return null;
- }
- }
- //
- // 摘要:
- // 获取 JSON 类型
- //
- // 参数:
- // obj:
- private static JsonType GetJsonType(object obj)
- {
- if (obj == null)
- {
- return JsonType.@null;
- }
- Type type = obj.GetType();
- if (ToBeConvertStringTypes.Contains(type))
- {
- return JsonType.@string;
- }
- if (obj is ExpandoObject)
- {
- return JsonType.@object;
- }
- switch (Type.GetTypeCode(type))
- {
- case TypeCode.Boolean:
- return JsonType.boolean;
- case TypeCode.Char:
- case TypeCode.DateTime:
- case TypeCode.String:
- return JsonType.@string;
- case TypeCode.SByte:
- case TypeCode.Byte:
- case TypeCode.Int16:
- case TypeCode.UInt16:
- case TypeCode.Int32:
- case TypeCode.UInt32:
- case TypeCode.Int64:
- case TypeCode.UInt64:
- case TypeCode.Single:
- case TypeCode.Double:
- case TypeCode.Decimal:
- return JsonType.number;
- case TypeCode.Object:
- return (obj is IEnumerable) ? JsonType.array : JsonType.@object;
- default:
- return JsonType.@null;
- }
- }
- //
- // 摘要:
- // 创建 XElement type 属性
- //
- // 参数:
- // type:
- private static XAttribute CreateTypeAttr(JsonType type)
- {
- return new XAttribute("type", type.ToString());
- }
- //
- // 摘要:
- // 创建 XElement 节点值
- //
- // 参数:
- // obj:
- private static object CreateJsonNode(object obj)
- {
- bool flag = obj?.GetType().IsEnum ?? false;
- switch (GetJsonType(obj))
- {
- case JsonType.@string:
- case JsonType.number:
- return flag ? ((object)(int)obj) : obj;
- case JsonType.boolean:
- return obj.ToString().ToLower();
- case JsonType.@object:
- return CreateXObject(obj);
- case JsonType.array:
- return CreateXArray(obj as IEnumerable);
- default:
- return null;
- }
- }
- //
- // 摘要:
- // 创建 XStreamingElement 对象
- //
- // 参数:
- // obj:
- //
- // 类型参数:
- // T:
- private static IEnumerable<XStreamingElement> CreateXArray<T>(T obj) where T : IEnumerable
- {
- return from object o in obj
- select new XStreamingElement("item", CreateTypeAttr(GetJsonType(o)), CreateJsonNode(o));
- }
- //
- // 摘要:
- // 创建 XStreamingElement 对象
- //
- // 参数:
- // obj:
- private static IEnumerable<XStreamingElement> CreateXObject(object obj)
- {
- if (obj is ExpandoObject source)
- {
- return source.Select<KeyValuePair<string, object>, XStreamingElement>((KeyValuePair<string, object> a) => new XStreamingElement(a.Key, CreateTypeAttr(GetJsonType(a.Value)), CreateJsonNode(a.Value)));
- }
- return from pi in obj.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public)
- select new
- {
- Name = pi.Name,
- Value = pi.GetValue(obj, null)
- } into a
- select new XStreamingElement(a.Name, CreateTypeAttr(GetJsonType(a.Value)), CreateJsonNode(a.Value));
- }
- //
- // 摘要:
- // 创建 JSON 字符串
- //
- // 参数:
- // element:
- private static string CreateJsonString(XStreamingElement element)
- {
- using MemoryStream memoryStream = new MemoryStream();
- using XmlDictionaryWriter xmlDictionaryWriter = JsonReaderWriterFactory.CreateJsonWriter(memoryStream, Encoding.UTF8);
- element.WriteTo(xmlDictionaryWriter);
- xmlDictionaryWriter.Flush();
- return Encoding.UTF8.GetString(memoryStream.ToArray());
- }
- //
- // 摘要:
- // 读取值
- //
- // 参数:
- // element:
- //
- // result:
- //
- // throwOnUndefined:
- private static bool TryGet(XElement element, out object result, bool throwOnUndefined = true)
- {
- if (element == null)
- {
- result = null;
- return !throwOnUndefined;
- }
- result = ToValue(element, throwOnUndefined);
- return true;
- }
- //
- // 摘要:
- // 根据键设置对象值
- //
- // 参数:
- // name:
- //
- // value:
- private bool TrySet(string name, object value)
- {
- JsonType jsonType = GetJsonType(value);
- if (value is Clay clay)
- {
- if (clay.IsObject)
- {
- value = value.ToExpandoObject();
- }
- else if (clay.IsArray)
- {
- List<object> list = new List<object>();
- foreach (object item in (dynamic)clay)
- {
- list.Add((dynamic)((item is Clay value2) ? value2.ToExpandoObject() : item));
- }
- value = list;
- }
- }
- bool isValid;
- XElement xElement = FindXElement(name, out isValid);
- if (xElement == null)
- {
- if (isValid)
- {
- XmlElement.Add(new XElement(name, CreateTypeAttr(jsonType), CreateJsonNode(value)));
- }
- else
- {
- XElement xElement2 = XElement.Parse($"<a:item xmlns:a=\"item\" item=\"{name}\" type=\"{jsonType}\"></a:item>");
- xElement2.ReplaceNodes(CreateJsonNode(value));
- XmlElement.Add(xElement2);
- }
- }
- else
- {
- xElement.Attribute("type").Value = jsonType.ToString();
- xElement.ReplaceNodes(CreateJsonNode(value));
- }
- return true;
- }
- //
- // 摘要:
- // 根据索引设置数组值
- //
- // 参数:
- // index:
- //
- // value:
- private bool TrySet(int index, object value)
- {
- JsonType type = GetJsonType(value);
- XElement xElement = XmlElement.Elements().ElementAtOrDefault(index);
- if (xElement == null)
- {
- XmlElement.Add(new XElement("item", CreateTypeAttr(type), CreateJsonNode(value)));
- }
- else
- {
- xElement.Attribute("type").Value = type.ToString();
- xElement.ReplaceNodes(CreateJsonNode(value));
- }
- return true;
- }
- //
- // 摘要:
- // 反序列化
- //
- // 参数:
- // type:
- private object Deserialize(Type type)
- {
- if (!IsArray)
- {
- return DeserializeObject(type);
- }
- return DeserializeArray(type);
- }
- //
- // 摘要:
- // 反序列化对象
- //
- // 参数:
- // targetType:
- private object DeserializeObject(Type targetType)
- {
- object obj = Activator.CreateInstance(targetType);
- Dictionary<string, PropertyInfo> dictionary = (from p in targetType.GetProperties(BindingFlags.Instance | BindingFlags.Public)
- where p.CanWrite
- select p).ToDictionary((PropertyInfo pi) => pi.Name, (PropertyInfo pi) => pi);
- foreach (XElement item in XmlElement.Elements())
- {
- string key = ((item.Name == "{item}item") ? item.Attribute("item").Value : item.Name.LocalName);
- if (dictionary.TryGetValue(key, out var value))
- {
- dynamic val = DeserializeValue(item, value.PropertyType, ThrowOnUndefined);
- value.SetValue(obj, val, null);
- }
- }
- return obj;
- }
- //
- // 摘要:
- // 反序列化值
- //
- // 参数:
- // element:
- //
- // elementType:
- //
- // throwOnUndefined:
- // 如果设置 false,则读取不存在的值返回 null,默认 true
- private static dynamic DeserializeValue(XElement element, Type elementType, bool throwOnUndefined = true)
- {
- dynamic val = ToValue(element, throwOnUndefined);
- if (val is Clay clay)
- {
- val = clay.Deserialize(elementType);
- }
- return Extension.ChangeType(val, elementType);
- }
- //
- // 摘要:
- // 反序列化数组
- //
- // 参数:
- // targetType:
- private object DeserializeArray(Type targetType)
- {
- if (targetType.IsArray)
- {
- Type elementType = targetType.GetElementType();
- dynamic val = Array.CreateInstance(elementType, XmlElement.Elements().Count());
- int num = 0;
- {
- foreach (XElement item in XmlElement.Elements())
- {
- val[num++] = DeserializeValue(item, elementType, ThrowOnUndefined);
- }
- return val;
- }
- }
- Type elementType2 = targetType.GetGenericArguments()[0];
- dynamic val2 = Activator.CreateInstance(targetType);
- foreach (XElement item2 in XmlElement.Elements())
- {
- val2.Add(DeserializeValue(item2, elementType2, ThrowOnUndefined));
- }
- return val2;
- }
- //
- // 摘要:
- // 根据键查找 System.Xml.Linq.XElement 对象
- //
- // 参数:
- // name:
- //
- // isValid:
- private XElement FindXElement(string name, out bool isValid)
- {
- bool flag = (isValid = TryVerifyNCName(name) == null);
- XElement? xElement = (from e in XmlElement.Elements("{item}item")
- where (string?)e.Attribute("item") == name
- select e).FirstOrDefault();
- if (xElement == null)
- {
- if (!flag)
- {
- return null;
- }
- xElement = XmlElement.Element(name);
- }
- return xElement;
- }
- //
- // 摘要:
- // 初始化粘土对象枚举器
- public IEnumerator GetEnumerator()
- {
- if (!IsArray)
- {
- return new ClayObjectEnumerator(this);
- }
- return new ClayArrayEnumerator(this);
- }
- //
- // 摘要:
- // 将粘土对象转换成 IEnumerable{T} 对象
- public IEnumerable<T> AsEnumerator<T>()
- {
- return this.Cast<T>();
- }
- //
- // 摘要:
- // 内部粘土对象枚举器
- IEnumerator IEnumerable.GetEnumerator()
- {
- return GetEnumerator();
- }
- }
- public static class ExpandoObjectExtensions
- {
- //
- // 摘要:
- // 将对象转 ExpandoObject 类型
- //
- // 参数:
- // value:
- public static ExpandoObject ToExpandoObject(this object value)
- {
- if (value == null)
- {
- throw new ArgumentNullException("value");
- }
- if (value is Clay clay && clay.IsObject)
- {
- dynamic val = new ExpandoObject();
- IDictionary<string, object> dictionary = (IDictionary<string, object>)val;
- foreach (object item in (dynamic)clay)
- {
- KeyValuePair<string, object> keyValuePair = (KeyValuePair<string, object>)(dynamic)item;
- dictionary.Add(keyValuePair.Key, (dynamic)((keyValuePair.Value is Clay value2) ? value2.ToExpandoObject() : keyValuePair.Value));
- }
- return val;
- }
- if (value is JsonElement jsonElement && jsonElement.ValueKind == JsonValueKind.Object)
- {
- dynamic val2 = new ExpandoObject();
- IDictionary<string, object> dictionary2 = (IDictionary<string, object>)val2;
- foreach (KeyValuePair<string, object> item2 in jsonElement.ToObject() as IDictionary<string, object>)
- {
- dictionary2.Add(item2);
- }
- return val2;
- }
- ExpandoObject expandoObject = value as ExpandoObject;
- if (expandoObject == null)
- {
- expandoObject = new ExpandoObject();
- IDictionary<string, object> dictionary3 = expandoObject;
- foreach (KeyValuePair<string, object> item3 in value.ToDictionary())
- {
- dictionary3.Add(item3);
- }
- }
- return expandoObject;
- }
- //
- // 摘要:
- // 移除 ExpandoObject 对象属性
- //
- // 参数:
- // expandoObject:
- //
- // propertyName:
- public static void RemoveProperty(this ExpandoObject expandoObject, string propertyName)
- {
- if (expandoObject == null)
- {
- throw new ArgumentNullException("expandoObject");
- }
- if (propertyName == null)
- {
- throw new ArgumentNullException("propertyName");
- }
- ((IDictionary<string, object>)expandoObject).Remove(propertyName);
- }
- //
- // 摘要:
- // 判断 ExpandoObject 是否为空
- //
- // 参数:
- // expandoObject:
- public static bool Empty(this ExpandoObject expandoObject)
- {
- return !expandoObject.Any();
- }
- //
- // 摘要:
- // 判断 ExpandoObject 是否拥有某属性
- //
- // 参数:
- // expandoObject:
- //
- // propertyName:
- public static bool HasProperty(this ExpandoObject expandoObject, string propertyName)
- {
- if (expandoObject == null)
- {
- throw new ArgumentNullException("expandoObject");
- }
- if (propertyName == null)
- {
- throw new ArgumentNullException("propertyName");
- }
- return ((IDictionary<string, object>)expandoObject).ContainsKey(propertyName);
- }
- //
- // 摘要:
- // 实现 ExpandoObject 浅拷贝
- //
- // 参数:
- // expandoObject:
- public static ExpandoObject ShallowCopy(this ExpandoObject expandoObject)
- {
- return Copy(expandoObject, deep: false);
- }
- //
- // 摘要:
- // 实现 ExpandoObject 深度拷贝
- //
- // 参数:
- // expandoObject:
- public static ExpandoObject DeepCopy(this ExpandoObject expandoObject)
- {
- return Copy(expandoObject, deep: true);
- }
- //
- // 摘要:
- // 拷贝 ExpandoObject 对象
- //
- // 参数:
- // original:
- //
- // deep:
- private static ExpandoObject Copy(ExpandoObject original, bool deep)
- {
- ExpandoObject expandoObject = new ExpandoObject();
- IDictionary<string, object> dictionary = expandoObject;
- foreach (KeyValuePair<string, object> item in (IEnumerable<KeyValuePair<string, object>>)original)
- {
- dictionary.Add(item.Key, (deep && item.Value is ExpandoObject expandoObject2) ? expandoObject2.DeepCopy() : item.Value);
- }
- return expandoObject;
- }
- }
- public sealed class ClayArrayEnumerator : IEnumerator
- {
- //
- // 摘要:
- // 粘土对象
- public dynamic _clay;
- //
- // 摘要:
- // 当前索引
- private int position = -1;
- //
- // 摘要:
- // 当前元素
- public dynamic Current
- {
- get
- {
- try
- {
- return _clay[position];
- }
- catch (IndexOutOfRangeException)
- {
- throw new InvalidOperationException();
- }
- }
- }
- //
- // 摘要:
- // 当前元素(内部)
- object IEnumerator.Current => Current;
- //
- // 摘要:
- // 构造函数
- //
- // 参数:
- // clay:
- // 粘土对象
- public ClayArrayEnumerator(dynamic clay)
- {
- _clay = clay;
- }
- //
- // 摘要:
- // 推进(获取)下一个元素
- public bool MoveNext()
- {
- position++;
- return position < _clay.Length;
- }
- //
- // 摘要:
- // 将元素索引恢复初始值
- public void Reset()
- {
- position = -1;
- }
- }
- public sealed class ClayObjectEnumerator : IEnumerator
- {
- //
- // 摘要:
- // 粘土对象
- public dynamic _clay;
- //
- // 摘要:
- // 当前索引
- private int position = -1;
- //
- // 摘要:
- // 当前元素
- public KeyValuePair<string, dynamic> Current
- {
- get
- {
- try
- {
- XElement xElement = ((XElement)_clay.XmlElement).Elements().ElementAtOrDefault(position);
- string text = ((xElement.Name == "{item}item") ? xElement.Attribute("item").Value : xElement.Name.LocalName);
- return new KeyValuePair<string, object>(text, _clay[text]);
- }
- catch (IndexOutOfRangeException)
- {
- throw new InvalidOperationException();
- }
- }
- }
- //
- // 摘要:
- // 当前元素(内部)
- object IEnumerator.Current => (KeyValuePair<string, object>)Current;
- //
- // 摘要:
- // 构造函数
- //
- // 参数:
- // clay:
- // 粘土对象
- public ClayObjectEnumerator(dynamic clay)
- {
- _clay = clay;
- }
- //
- // 摘要:
- // 推进(获取)下一个元素
- public bool MoveNext()
- {
- position++;
- return position < _clay.Length;
- }
- //
- // 摘要:
- // 将元素索引恢复初始值
- public void Reset()
- {
- position = -1;
- }
- }
|