using NCC.ClayObject.Extensions;
using NCC.Dependency;
using NCC.JsonSerialization;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Dynamic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.Serialization.Json;
using System.Text;
using System.Text.Json;
using System.Xml;
using System.Xml.Linq;
namespace NCC.ClayObject
{
///
/// 粘土对象
///
[SuppressSniffer]
public class Clay : DynamicObject
{
///
/// 构造函数
///
public Clay()
{
XmlElement = new XElement("root", CreateTypeAttr(JsonType.@object));
jsonType = JsonType.@object;
}
///
/// 构造函数
///
///
///
private Clay(XElement element, JsonType type)
{
Debug.Assert(type == JsonType.array || type == JsonType.@object);
XmlElement = element;
jsonType = type;
}
///
/// 是否是 Object 类型
///
public bool IsObject => jsonType == JsonType.@object;
///
/// 是否是 Array 类型
///
public bool IsArray => jsonType == JsonType.array;
///
/// XML 元素
///
public XElement XmlElement { get; private set; }
///
/// 创建一个超级类型
///
///
public static dynamic Object()
{
return new Clay();
}
///
/// 基于现有类型创建一个超级类型
///
///
///
public static dynamic Object(object obj)
{
return Parse(Serialize(obj));
}
///
/// 将 Json 转换成动态类型
///
///
///
public static dynamic Parse(string json)
{
return Parse(json, Encoding.Unicode);
}
///
/// 将 Json 转换成动态类型
///
///
///
///
public static dynamic Parse(string json, Encoding encoding)
{
using var reader = JsonReaderWriterFactory.CreateJsonReader(encoding.GetBytes(json), XmlDictionaryReaderQuotas.Max);
return ToValue(XElement.Load(reader));
}
///
/// 将 Steam 转换成动态类型
///
///
///
public static dynamic Parse(Stream stream)
{
using var reader = JsonReaderWriterFactory.CreateJsonReader(stream, XmlDictionaryReaderQuotas.Max);
return ToValue(XElement.Load(reader));
}
///
/// 将 Steam 转换成动态类型
///
///
///
///
public static dynamic Parse(Stream stream, Encoding encoding)
{
using var reader = JsonReaderWriterFactory.CreateJsonReader(stream, encoding, XmlDictionaryReaderQuotas.Max, _ => { });
return ToValue(XElement.Load(reader));
}
///
/// 序列化对象
///
///
///
public static string Serialize(object obj)
{
return CreateJsonString(new XStreamingElement("root", CreateTypeAttr(GetJsonType(obj)), CreateJsonNode(obj)));
}
///
/// 是否定义某个键
///
///
///
public bool IsDefined(string name)
{
return IsObject && (XmlElement.Element(name) != null);
}
///
/// 判断数组索引是否存在
///
///
///
public bool IsDefined(int index)
{
return IsArray && (XmlElement.Elements().ElementAtOrDefault(index) != null);
}
///
/// 删除键
///
///
///
public bool Delete(string name)
{
var elem = XmlElement.Element(name);
if (elem != null)
{
elem.Remove();
return true;
}
else return false;
}
///
/// 根据索引删除元素
///
///
///
public bool Delete(int index)
{
var elem = XmlElement.Elements().ElementAtOrDefault(index);
if (elem != null)
{
elem.Remove();
return true;
}
else return false;
}
///
/// 反序列化
///
///
///
public T Deserialize()
{
return (T)Deserialize(typeof(T));
}
///
/// 删除
///
///
///
///
///
public override bool TryInvoke(InvokeBinder binder, object[] args, out object result)
{
result = (IsArray)
? Delete((int)args[0])
: Delete((string)args[0]);
return true;
}
///
/// 判断是否定义
///
///
///
///
///
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;
}
///
/// 支持 Foreach 遍历
///
///
///
///
public override bool TryConvert(ConvertBinder binder, out object result)
{
if (binder.Type == typeof(IEnumerable) || binder.Type == typeof(object[]))
{
var ie = (IsArray)
? XmlElement.Elements().Select(x => ToValue(x))
: XmlElement.Elements().Select(x => (dynamic)new KeyValuePair(x.Name.LocalName, ToValue(x)));
result = (binder.Type == typeof(object[])) ? ie.ToArray() : ie;
}
else
{
result = Deserialize(binder.Type);
}
return true;
}
///
/// 获取索引值
///
///
///
///
///
public override bool TryGetIndex(GetIndexBinder binder, object[] indexes, out object result)
{
return (IsArray)
? TryGet(XmlElement.Elements().ElementAtOrDefault((int)indexes[0]), out result)
: TryGet(XmlElement.Element((string)indexes[0]), out result);
}
///
/// 获取成员值
///
///
///
///
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
return (IsArray)
? TryGet(XmlElement.Elements().ElementAtOrDefault(int.Parse(binder.Name)), out result)
: TryGet(XmlElement.Element(binder.Name), out result);
}
///
/// 设置索引
///
///
///
///
///
public override bool TrySetIndex(SetIndexBinder binder, object[] indexes, object value)
{
return (IsArray)
? TrySet((int)indexes[0], value)
: TrySet((string)indexes[0], value);
}
///
/// 设置成员
///
///
///
///
public override bool TrySetMember(SetMemberBinder binder, object value)
{
return (IsArray)
? TrySet(int.Parse(binder.Name), value)
: TrySet(binder.Name, value);
}
///
/// 获取动态成员名称
///
///
public override IEnumerable GetDynamicMemberNames()
{
return (IsArray)
? XmlElement.Elements().Select((x, i) => i.ToString())
: XmlElement.Elements().Select(x => x.Name.LocalName);
}
///
/// 重写 .ToString()
///
///
public override string ToString()
{
// is can't serialize. replace to
foreach (var elem in XmlElement.Descendants().Where(x => x.Attribute("type").Value == "null"))
{
elem.RemoveNodes();
}
return CreateJsonString(new XStreamingElement("root", CreateTypeAttr(jsonType), XmlElement.Elements()));
}
///
/// 固化粘土,也就是直接输出对象
///
///
public object Solidify()
{
return Solidify