必须填写至少10个字的日志
nnhy 编写于 2012-07-27 18:48:21
X
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Text;
using NewLife.Log;
#if NET4
using System.Linq;
#else
using NewLife.Linq;
#endif

namespace NewLife.Serialization
{
    /// <summary>读写器基类</summary>
    public abstract class ReaderWriterBase<TSettings> : /*NewLife.DisposeBase,*/ IReaderWriter where TSettings : ReaderWriterSetting, new()
    {
        #region 属性
        private String _Name;
        /// <summary>读写器名称</summary>
        public virtual String Name
        {
            get
            {
                if (String.IsNullOrEmpty(_Name))
                {
                    _Name = this.GetType().Name;
                    if (_Name.EndsWith("Reader", StringComparison.OrdinalIgnoreCase))
                        _Name = _Name.Substring(0, _Name.Length - "Reader".Length);
                    if (_Name.EndsWith("Writer", StringComparison.OrdinalIgnoreCase))
                        _Name = _Name.Substring(0, _Name.Length - "Writer".Length);
                }
                return _Name;
            }
        }

        private Stream _Stream;
        /// <summary>数据流。默认实例化一个MemoryStream,设置值时将重置Depth为1</summary>
        public virtual Stream Stream
        {
            get { return _Stream ?? (_Stream = new MemoryStream()); }
            set
            {
                if (_Stream != value)
                {
                    Depth = 1;

                    // 如果原来使用跟踪流,新的也使用跟踪流
                    if (Debug && _Stream is TraceStream && value != null && !(value is TraceStream))
                        _Stream = new TraceStream(value);
                    else
                        _Stream = value;
                }
            }
        }

        private TSettings _Settings;
        /// <summary>序列化设置</summary>
        public virtual TSettings Settings
        {
            get { return _Settings ?? (_Settings = new TSettings()); }
            set { _Settings = value; }
        }

        /// <summary>序列化设置</summary>
        ReaderWriterSetting IReaderWriter.Settings { get { return Settings; } set { Settings = (TSettings)value; } }

        private Int32 _Depth;
        /// <summary>层次深度</summary>
        public Int32 Depth
        {
            get
            {
                if (_Depth < 1) _Depth = 1;
                return _Depth;
            }
            set { _Depth = value; }
        }

        /// <summary>是否使用大小,如果使用,将在写入数组、集合和字符串前预先写入大小</summary>
        protected virtual Boolean UseSize { get { return true; } }

        private Object _CurrentObject;
        /// <summary>当前对象</summary>
        public Object CurrentObject { get { return _CurrentObject; } set { _CurrentObject = value; } }

        private IObjectMemberInfo _CurrentMember;
        /// <summary>当前成员</summary>
        public IObjectMemberInfo CurrentMember { get { return _CurrentMember; } set { _CurrentMember = value; } }

        private IDictionary _Items;
        /// <summary>用于存放使用者的上下文数据</summary>
        public IDictionary Items { get { return _Items ?? (_Items = new Hashtable()); } set { _Items = value; } }
        #endregion

        #region 方法
        /// <summary>重置</summary>
        public virtual void Reset() { Depth = 1; }

        /// <summary>是否精确类型</summary>
        /// <param name="type"></param>
        /// <returns></returns>
        protected static Boolean IsExactType(Type type)
        {
            // 特殊处理Type
            if (type == null || type.IsInterface || type.IsAbstract && type != typeof(Type) || type == typeof(Object) || type == typeof(Exception))
                return false;
            else
                return true;
        }
        #endregion

        #region 备份还原环境
        private Stack<Dictionary<String, Object>> _stack;

        /// <summary>备份当前环境,用于临时切换数据流等</summary>
        /// <returns>本次备份项集合</returns>
        public virtual IDictionary<String, Object> Backup()
        {
            if (_stack == null) _stack = new Stack<Dictionary<String, Object>>();

            var dic = new Dictionary<String, Object>();
            dic["Stream"] = Stream;
            //dic["Depth"] = Depth;
            //dic["CurrentObject"] = CurrentObject;
            //dic["CurrentMember"] = CurrentMember;

            _stack.Push(dic);

            return dic;
        }

        /// <summary>恢复最近一次备份</summary>
        /// <returns>本次还原项集合</returns>
        public virtual IDictionary<String, Object> Restore()
        {
            if (_stack == null || _stack.Count <= 0) throw new Exception("没有任何备份项!");

            var dic = _stack.Pop();

            Object obj = null;
            if (dic.TryGetValue("Stream", out obj)) Stream = obj as Stream;
            //Stream = dic["Stream"] as Stream;
            //Depth = (Int32)dic["Depth"];
            //CurrentObject = dic["CurrentObject"];
            //CurrentMember = dic["CurrentMember"] as IObjectMemberInfo;

            return dic;
        }
        #endregion

        #region 获取成员
        /// <summary>获取需要序列化的成员</summary>
        /// <param name="type">类型</param>
        /// <param name="value">对象</param>
        /// <returns>需要序列化的成员</returns>
        public IObjectMemberInfo[] GetMembers(Type type, Object value)
        {
            if (type == null)
            {
                if (value == null) throw new ArgumentNullException("type");

                type = value.GetType();
            }

            var mis = OnGetMembers(type, value);

            if (OnGotMembers != null)
            {
                var e = new EventArgs<Type, Object, IObjectMemberInfo[]>(type, value, mis);
                OnGotMembers(this, e);
                mis = e.Arg3;
            }

            // 过滤掉被忽略的成员
            var members = Settings.IgnoreMembers;
            if (members.Count > 0)
            {
                mis = mis.Where(m => !members.Contains(m.Name)).ToArray();
            }

            return mis;
        }

        /// <summary>获取需要序列化的成员(属性或字段)</summary>
        /// <param name="type">指定类型</param>
        /// <param name="value">对象</param>
        /// <returns>需要序列化的成员</returns>
        protected virtual IObjectMemberInfo[] OnGetMembers(Type type, Object value)
        {
            if (type == null) throw new ArgumentNullException("type");

            return ObjectInfo.GetMembers(type, value, Settings.UseField, Settings.IsBaseFirst);
        }

        /// <summary>获取指定类型中需要序列化的成员时触发。使用者可以修改、排序要序列化的成员。</summary>
        public event EventHandler<EventArgs<Type, Object, IObjectMemberInfo[]>> OnGotMembers;
        #endregion

        #region 对象默认值
        /// <summary>判断一个对象的某个成员是否默认值</summary>
        /// <param name="value"></param>
        /// <param name="member"></param>
        /// <returns></returns>
        internal static Boolean IsDefault(Object value, IObjectMemberInfo member)
        {
            if (value == null) return false;

            Object def = ObjectInfo.GetDefaultObject(value.GetType());
            return Object.Equals(member[value], member[def]);
        }
        #endregion

        #region 释放
        ///// <summary>
        ///// 释放资源
        ///// </summary>
        ///// <param name="disposing"></param>
        //protected override void OnDispose(bool disposing)
        //{
        //    base.OnDispose(disposing);
        //}
        #endregion

        #region 跟踪日志
        private Boolean _Debug;
        /// <summary>是否调试</summary>
        public Boolean Debug { get { return _Debug; } set { _Debug = value; } }

        /// <summary>使用跟踪流。实际上是重新包装一次Stream,必须在设置Stream,使用之前</summary>
        public virtual void EnableTraceStream()
        {
            var stream = Stream;
            if (stream == null || stream is TraceStream) return;

            Stream = new TraceStream(stream) { Encoding = Settings.Encoding };
        }

        /// <summary>显示成员列表</summary>
        /// <param name="action"></param>
        /// <param name="members"></param>
        protected void ShowMembers(String action, IObjectMemberInfo[] members)
        {
            if (!Debug || !IsConsole) return;

            var sb = new StringBuilder();
            foreach (var item in members)
            {
                if (sb.Length > 0) sb.Append(",");
                sb.Append(item.Name);
            }
            WriteLog(action, sb.ToString());
        }

        /// <summary>调试输出</summary>
        /// <param name="action">操作</param>
        /// <param name="args">参数</param>
        public void WriteLog(String action, params Object[] args)
        {
            WriteLog(0, action, args);
        }

        static ConsoleColor[][] colors = new ConsoleColor[][] { 
            new ConsoleColor[] { ConsoleColor.Green,ConsoleColor.Magenta, ConsoleColor.White, ConsoleColor.Yellow },
            new ConsoleColor[] { ConsoleColor.Yellow, ConsoleColor.White, ConsoleColor.Magenta,ConsoleColor.Green }
        };

        static Boolean? _IsConsole;
        /// <summary>是否控制台</summary>
        static Boolean IsConsole { get { return (_IsConsole ?? (_IsConsole = Runtime.IsConsole)).Value; } }

        /// <summary>调试输出</summary>
        /// <param name="colorIndex">颜色方案</param>
        /// <param name="action">操作</param>
        /// <param name="args">参数</param>
        public void WriteLog(Int32 colorIndex, String action, params Object[] args)
        {
            if (!Debug || !IsConsole) return;

            ConsoleColor color = Console.ForegroundColor;

            // 缩进
            SetDebugIndent();

            // 红色动作
            Console.ForegroundColor = colors[colorIndex][0];
            Console.Write(action);

            if (args != null && args.Length > 0)
            {
                // 白色参数
                //Console.ForegroundColor = ConsoleColor.White;

                for (int i = 0; i < args.Length; i++)
                {
                    Console.ForegroundColor = colors[colorIndex][i % colors.Length + 1];
                    Console.Write(" ");
                    Console.Write(args[i]);
                }
            }

            Console.ForegroundColor = color;
            Console.WriteLine();
        }

        /// <summary>设置调试缩进</summary>
        /// <param name="indent">缩进</param>
        public void SetDebugIndent(Int32 indent)
        {
            if (!Debug || !IsConsole) return;

            try
            {
                Console.CursorLeft = indent * 4;
            }
            catch { }
        }

        /// <summary>设置调试缩进</summary>
        public void SetDebugIndent()
        {
            if (!Debug || !IsConsole) return;

            SetDebugIndent(Depth - 1);
        }
        #endregion
    }
}