发布1203
大石头 编写于 2019-12-03 22:57:54
X
using System;
using System.Globalization;
using System.Xml;

namespace NewLife.Serialization
{
    /// <summary>Xml基础类型处理器</summary>
    public class XmlGeneral : XmlHandlerBase
    {
        /// <summary>实例化</summary>
        public XmlGeneral()
        {
            Priority = 10;
        }

        /// <summary>写入一个对象</summary>
        /// <param name="value">目标对象</param>
        /// <param name="type">类型</param>
        /// <returns>是否处理成功</returns>
        public override Boolean Write(Object value, Type type)
        {
            if (value == null && type != typeof(String)) return false;

            var writer = Host.GetWriter();

            // 枚举 写入字符串
            if (type.IsEnum)
            {
                writer.WriteValue(value + "");
                return true;
            }

            switch (Type.GetTypeCode(type))
            {
                case TypeCode.Boolean:
                    writer.WriteValue((Boolean)value);
                    return true;
                case TypeCode.Byte:
                case TypeCode.SByte:
                case TypeCode.Char:
                    writer.WriteValue((Char)value);
                    return true;
                case TypeCode.DBNull:
                case TypeCode.Empty:
                    writer.WriteValue(0);
                    return true;
                case TypeCode.DateTime:
                    writer.WriteValue(((DateTime)value).ToFullString());
                    return true;
                case TypeCode.Decimal:
                    writer.WriteValue((Decimal)value);
                    return true;
                case TypeCode.Double:
                    writer.WriteValue((Double)value);
                    return true;
                case TypeCode.Single:
                    writer.WriteValue((Single)value);
                    return true;
                case TypeCode.Int16:
                case TypeCode.UInt16:
                case TypeCode.Int32:
                case TypeCode.UInt32:
                    writer.WriteValue((Int32)value);
                    return true;
                case TypeCode.Int64:
                case TypeCode.UInt64:
                    writer.WriteValue((Int64)value);
                    return true;
                case TypeCode.String:
                    writer.WriteValue(value + "");
                    return true;
                case TypeCode.Object:
                    break;
                default:
                    break;
            }

            if (type == typeof(Guid))
            {
                writer.WriteValue(((Guid)value).ToString());
                return true;
            }

            if (type == typeof(DateTimeOffset))
            {
                //writer.WriteValue((DateTimeOffset)value);
                writer.WriteValue(((DateTimeOffset)value) + "");
                return true;
            }

            if (type == typeof(TimeSpan))
            {
                writer.WriteValue(((TimeSpan)value) + "");
                return true;
            }

            if (type == typeof(Byte[]))
            {
                var buf = value as Byte[];
                writer.WriteBase64(buf, 0, buf.Length);
                return true;
            }

            if (type == typeof(Char[]))
            {
                writer.WriteValue(new String((Char[])value));
                return true;
            }

            return false;
        }

        /// <summary>尝试读取</summary>
        /// <param name="type"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public override Boolean TryRead(Type type, ref Object value)
        {
            if (type == null)
            {
                if (value == null) return false;
                type = value.GetType();
            }

            var reader = Host.GetReader();

            if (type == typeof(Guid))
            {
                value = new Guid(reader.ReadContentAsString());
                return true;
            }
            else if (type == typeof(Byte[]))
            {
                // 用字符串长度作为预设缓冲区的长度
                var buf = new Byte[reader.Value.Length];
                var count = reader.ReadContentAsBase64(buf, 0, buf.Length);
                value = buf.ReadBytes(0, count);
                return true;
            }
            else if (type == typeof(Char[]))
            {
                value = reader.ReadContentAsString().ToCharArray();
                return true;
            }
            else if (type == typeof(DateTimeOffset))
            {
                //value = reader.ReadContentAs(type, null);
                value = DateTimeOffset.Parse(reader.ReadContentAsString());
                return true;
            }
            else if (type == typeof(TimeSpan))
            {
                value = TimeSpan.Parse(reader.ReadContentAsString());
                return true;
            }

            var code = Type.GetTypeCode(type);
            if (code == TypeCode.Object) return false;

            // 读取异构Xml时可能报错
            var v = (reader.NodeType == XmlNodeType.Element ? reader.ReadElementContentAsString() : reader.ReadContentAsString()) + "";

            // 枚举
            if (type.IsEnum)
            {
                value = Enum.Parse(type, v);
                return true;
            }

            switch (code)
            {
                case TypeCode.Boolean:
                    value = v.ToBoolean();
                    return true;
                case TypeCode.Byte:
                    value = Byte.Parse(v, NumberStyles.HexNumber);
                    return true;
                case TypeCode.Char:
                    if (v.Length > 0) value = v[0];
                    return true;
                case TypeCode.DBNull:
                    value = DBNull.Value;
                    return true;
                case TypeCode.DateTime:
                    value = v.ToDateTime();
                    return true;
                case TypeCode.Decimal:
                    value = (Decimal)v.ToDouble();
                    return true;
                case TypeCode.Double:
                    value = v.ToDouble();
                    return true;
                case TypeCode.Empty:
                    value = null;
                    return true;
                case TypeCode.Int16:
                    value = (Int16)v.ToInt();
                    return true;
                case TypeCode.Int32:
                    value = v.ToInt();
                    return true;
                case TypeCode.Int64:
                    value = Int64.Parse(v);
                    return true;
                case TypeCode.Object:
                    break;
                case TypeCode.SByte:
                    value = SByte.Parse(v, NumberStyles.HexNumber);
                    return true;
                case TypeCode.Single:
                    value = (Single)v.ToDouble();
                    return true;
                case TypeCode.String:
                    value = v;
                    return true;
                case TypeCode.UInt16:
                    value = (UInt16)v.ToInt();
                    return true;
                case TypeCode.UInt32:
                    value = (UInt32)v.ToInt();
                    return true;
                case TypeCode.UInt64:
                    value = UInt64.Parse(v);
                    return true;
                default:
                    break;
            }

            return false;
        }
    }
}