using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Reflection;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using NewLife.Exceptions;
using NewLife.Log;
using NewLife.Reflection;
#if NET4
using System.Linq;
#else
using NewLife.Linq;
#endif
namespace NewLife.Serialization
{
/// <summary>读取器基类</summary>
/// <remarks>
/// 序列化框架的核心思想:基本类型直接读取,自定义类型反射得到成员,逐层递归读取!详见<see cref="IReaderWriter"/>
///
/// 序列化框架的处理顺序为:<see cref="IAccessor" />接口 => <see cref="OnObjectReading" />事件 => 扩展类型 => <see cref="ReadValue(Type,ref Object)" />基础类型 => <see cref="ReadDictionary(Type,ref Object)" />字典 => <see cref="ReadEnumerable(Type,ref Object)" />枚举 => <see cref="ReadSerializable" />序列化接口 => <see cref="ReadCustomObject" />自定义对象 => <see cref="ReadUnKnown" />未知类型 => <see cref="OnObjectReaded" />事件
///
/// 反序列化对象时只能调用<see cref="ReadObject(Type)" />方法,其它所有方法(包括所有Read重载)仅用于内部读取或者自定义序列化时使用。
/// </remarks>
/// <typeparam name="TSettings">设置类</typeparam>
public abstract class ReaderBase<TSettings> : ReaderWriterBase<TSettings>, IReader where TSettings : ReaderWriterSetting, new()
{
#region 基元类型
#region 字节
/// <summary>从当前流中读取下一个字节,并使流的当前位置提升 1 个字节。</summary>
/// <returns></returns>
public abstract byte ReadByte();
/// <summary>从当前流中将 count 个字节读入字节数组,如果count小于0,则先读取字节数组长度。</summary>
/// <param name="count">要读取的字节数。</param>
/// <returns></returns>
public virtual byte[] ReadBytes(int count)
{
if (count < 0) count = ReadSize();
if (count <= 0) return null;
Byte[] buffer = new Byte[count];
for (int i = 0; i < count; i++)
{
buffer[i] = ReadByte();
}
return buffer;
}
/// <summary>从此流中读取一个有符号字节,并使流的当前位置提升 1 个字节。</summary>
/// <returns></returns>
//[CLSCompliant(false)]
public virtual sbyte ReadSByte() { return (SByte)ReadByte(); }
#endregion
#region 有符号整数
/// <summary>读取整数的字节数组,某些写入器(如二进制写入器)可能需要改变字节顺序</summary>
/// <param name="count"></param>
/// <returns></returns>
protected virtual Byte[] ReadIntBytes(Int32 count) { return ReadBytes(count); }
/// <summary>从当前流中读取 2 字节有符号整数,并使流的当前位置提升 2 个字节。</summary>
/// <returns></returns>
public virtual short ReadInt16() { return BitConverter.ToInt16(ReadIntBytes(2), 0); }
/// <summary>从当前流中读取 4 字节有符号整数,并使流的当前位置提升 4 个字节。</summary>
/// <returns></returns>
public virtual int ReadInt32() { return BitConverter.ToInt32(ReadIntBytes(4), 0); }
/// <summary>从当前流中读取 8 字节有符号整数,并使流的当前位置向前移动 8 个字节。</summary>
/// <returns></returns>
public virtual long ReadInt64() { return BitConverter.ToInt64(ReadIntBytes(8), 0); }
#endregion
#region 无符号整数
/// <summary>使用 Little-Endian 编码从当前流中读取 2 字节无符号整数,并将流的位置提升 2 个字节。</summary>
/// <returns></returns>
//[CLSCompliant(false)]
public virtual ushort ReadUInt16() { return (UInt16)ReadInt16(); }
/// <summary>从当前流中读取 4 字节无符号整数并使流的当前位置提升 4 个字节。</summary>
/// <returns></returns>
//[CLSCompliant(false)]
public virtual uint ReadUInt32() { return (UInt32)ReadInt32(); }
/// <summary>从当前流中读取 8 字节无符号整数并使流的当前位置提升 8 个字节。</summary>
/// <returns></returns>
//[CLSCompliant(false)]
public virtual ulong ReadUInt64() { return (UInt64)ReadInt64(); }
#endregion
#region 浮点数
/// <summary>从当前流中读取 4 字节浮点值,并使流的当前位置提升 4 个字节。</summary>
/// <returns></returns>
public virtual float ReadSingle() { return BitConverter.ToSingle(ReadBytes(4), 0); }
/// <summary>从当前流中读取 8 字节浮点值,并使流的当前位置提升 8 个字节。</summary>
/// <returns></returns>
public virtual double ReadDouble() { return BitConverter.ToDouble(ReadBytes(8), 0); }
#endregion
#region 字符串
/// <summary>从当前流中读取下一个字符,并根据所使用的 Encoding 和从流中读取的特定字符,提升流的当前位置。</summary>
/// <returns></returns>
public virtual char ReadChar() { return Convert.ToChar(ReadByte()); }
/// <summary>从当前流中读取 count 个字符,以字符数组的形式返回数据,并根据所使用的 Encoding 和从流中读取的特定字符,提升当前位置。</summary>
/// <param name="count">要读取的字符数。</param>
/// <returns></returns>
public virtual char[] ReadChars(int count)
{
if (count < 0) count = ReadSize();
// count个字符可能的最大字节数
Int32 max = Settings.Encoding.GetMaxByteCount(count);
// 首先按最小值读取
Byte[] data = ReadBytes(count);
// 相同,最简单的一种
if (max == count) return Settings.Encoding.GetChars(data);
// 按最大值准备一个字节数组
Byte[] buffer = new Byte[max];
// 复制过去
Buffer.BlockCopy(data, 0, buffer, 0, data.Length);
// 遍历,以下算法性能较差,将来可以考虑优化
Int32 i = 0;
for (i = count; i < max; i++)
{
Int32 n = Settings.Encoding.GetCharCount(buffer, 0, i);
if (n >= count) break;
buffer[i] = ReadByte();
}
return Settings.Encoding.GetChars(buffer, 0, i);
}
/// <summary>从当前流中读取一个字符串。字符串有长度前缀,一次 7 位地被编码为整数。</summary>
/// <returns></returns>
public virtual string ReadString()
{
// 先读长度
Int32 n = ReadSize();
if (n < 0) return null;
if (n == 0) return String.Empty;
Byte[] buffer = ReadBytes(n);
return Settings.Encoding.GetString(buffer);
}
#endregion
#region 其它
/// <summary>从当前流中读取 Boolean 值,并使该流的当前位置提升 1 个字节。</summary>
/// <returns></returns>
public virtual bool ReadBoolean() { return ReadByte() != 0; }
/// <summary>从当前流中读取十进制数值,并将该流的当前位置提升十六个字节。</summary>
/// <returns></returns>
public virtual decimal ReadDecimal()
{
Int32[] data = new Int32[4];
for (int i = 0; i < data.Length; i++)
{
data[i] = ReadInt32();
}
return new Decimal(data);
}
/// <summary>读取一个时间日期</summary>
/// <returns></returns>
public virtual DateTime ReadDateTime() { return Settings.ConvertInt64ToDateTime(ReadInt64()); }
#endregion
#endregion
#region 值类型
/// <summary>读取值类型数据</summary>
/// <param name="type"></param>
/// <returns></returns>
public Object ReadValue(Type type)
{
Object value = null;
return ReadValue(type, ref value) ? value : null;
}
/// <summary>尝试读取值类型数据,返回是否读取成功</summary>
/// <param name="type">要读取的对象类型</param>
/// <param name="value">要读取的对象</param>
/// <returns></returns>
public virtual Boolean ReadValue(Type type, ref Object value)
{
if (type == null)
{
if (value == null) return false;
type = value.GetType();
}
TypeCode code = Type.GetTypeCode(type);
switch (code)
{
case TypeCode.Boolean:
value = ReadBoolean();
return true;
case TypeCode.Byte:
value = ReadByte();
return true;
case TypeCode.Char:
value = ReadChar();
return true;
case TypeCode.DBNull:
value = ReadByte();
return true;
case TypeCode.DateTime:
value = ReadDateTime();
return true;
case TypeCode.Decimal:
value = ReadDecimal();
return true;
case TypeCode.Double:
value = ReadDouble();
return true;
case TypeCode.Empty:
value = ReadByte();
return true;
case TypeCode.Int16:
value = ReadInt16();
return true;
case TypeCode.Int32:
value = ReadInt32();
return true;
case TypeCode.Int64:
value = ReadInt64();
return true;
case TypeCode.Object:
break;
case TypeCode.SByte:
value = ReadSByte();
return true;
case TypeCode.Single:
value = ReadSingle();
return true;
case TypeCode.String:
value = ReadString();
return true;
case TypeCode.UInt16:
value = ReadUInt16();
return true;
case TypeCode.UInt32:
value = ReadUInt32();
return true;
case TypeCode.UInt64:
value = ReadUInt64();
return true;
default:
break;
}
return false;
}
#endregion
#region 字典
/// <summary>尝试读取字典类型对象</summary>
/// <param name="type">类型</param>
/// <param name="value">对象</param>
/// <returns>是否读取成功</returns>
public virtual Boolean ReadDictionary(Type type, ref Object value)
{
return ReadDictionary(type, ref value, ReadMember);
}
/// <summary>尝试读取字典类型对象</summary>
/// <param name="type">类型</param>
/// <param name="value">对象</param>
/// <param name="callback">处理成员的方法</param>
/// <returns>是否读取成功</returns>
public virtual Boolean ReadDictionary(Type type, ref Object value, ReadObjectCallback callback)
{
//if (type == null)
//{
// if (value == null) throw new ArgumentNullException("type");
// type = value.GetType();
//}
//type = CheckAndReadType("ReadDictionaryType", type, value);
if (!typeof(IDictionary).IsAssignableFrom(type)) return false;
// 计算元素类型
Type keyType = null;
Type valueType = null;
// 无法取得键值类型
//if (!GetDictionaryEntryType(type, ref keyType, ref valueType)) return false;
GetDictionaryEntryType(type, ref keyType, ref valueType);
// 提前创建对象,因为对象引用可能用到
Int32 index = objRefIndex;
if (index > 0 && Settings.UseObjRef && value == null)
{
value = TypeX.CreateInstance(type);
if (value != null) AddObjRef(index, value);
}
// 读取键值对集合
IEnumerable<DictionaryEntry> list = ReadDictionary(keyType, valueType, ReadSize(), callback);
if (list == null)
{
value = null;
// 结果为空,重新把对象引用设为空。不用担心里面里面已经引用了有对象的对象引用,因为既然列表返回空,表明里面没有元素
if (index > 0 && Settings.UseObjRef) AddObjRef(index, value);
return true;
}
if (value == null) value = TypeX.CreateInstance(type);
IDictionary dic = value as IDictionary;
foreach (DictionaryEntry item in list)
{
dic.Add(item.Key, item.Value);
}
return true;
}
/// <summary>读取字典项集合,以读取键值失败作为读完字典项的标识,子类可以重载实现以字典项数量来读取</summary>
/// <param name="keyType">键类型</param>
/// <param name="valueType">值类型</param>
/// <param name="count">元素个数</param>
/// <param name="callback">处理元素的方法</param>
/// <returns>字典项集合</returns>
protected virtual IEnumerable<DictionaryEntry> ReadDictionary(Type keyType, Type valueType, Int32 count, ReadObjectCallback callback)
{
List<DictionaryEntry> list = new List<DictionaryEntry>();
// 元素个数小于0,可能是因为不支持元素个数,直接设为最大值
if (count < 0) count = Int32.MaxValue;
for (int i = 0; i < count; i++)
{
// 一旦有一个元素读不到,就中断
DictionaryEntry obj;
Depth++;
if (!ReadDictionaryEntry(keyType, valueType, ref obj, i, callback))
{
Depth--;
break;
}
Depth--;
list.Add(obj);
}
return list;
}
/// <summary>读取字典项</summary>
/// <param name="keyType">键类型</param>
/// <param name="valueType">值类型</param>
/// <param name="value">字典项</param>
/// <param name="index">元素序号</param>
/// <param name="callback">处理元素的方法</param>
/// <returns>是否读取成功</returns>
protected Boolean ReadDictionaryEntry(Type keyType, Type valueType, ref DictionaryEntry value, Int32 index, ReadObjectCallback callback)
{
// 读取成员前
ReadDictionaryEventArgs e = null;
if (OnDictionaryReading != null)
{
e = new ReadDictionaryEventArgs(value, keyType, valueType, index, callback);
OnDictionaryReading(this, e);
// 事件里面有可能改变了参数
value = e.Value;
keyType = e.KeyType;
valueType = e.ValueType;
index = e.Index;
callback = e.Callback;
// 事件处理器可能已经成功读取对象
if (e.Success) return true;
}
Boolean rs = OnReadDictionaryEntry(keyType, valueType, ref value, index, callback);
// 读取成员后
if (OnDictionaryReaded != null)
{
if (e == null) e = new ReadDictionaryEventArgs(value, keyType, valueType, index, callback);
e.Value = value;
e.Success = rs;
OnDictionaryReaded(this, e);
// 事件处理器可以影响结果
value = e.Value;
rs = e.Success;
}
return rs;
}
/// <summary>读取字典项</summary>
/// <param name="keyType">键类型</param>
/// <param name="valueType">值类型</param>
/// <param name="value">字典项</param>
/// <param name="index">元素序号</param>
/// <param name="callback">处理元素的方法</param>
/// <returns>是否读取成功</returns>
protected virtual Boolean OnReadDictionaryEntry(Type keyType, Type valueType, ref DictionaryEntry value, Int32 index, ReadObjectCallback callback)
{
Object key = null;
Object val = null;
// 如果无法取得字典项类型,则每个键值都单独写入类型
//if (keyType == null)
//{
// WriteLog("ReadKeyType");
// keyType = ReadType();
// WriteLog("ReadKeyType", keyType.Name);
//}
// keyType = CheckAndReadType("ReadKeyType", keyType, value.Key);
if (!ReadObject(keyType, ref key)) return false;
//if (valueType == null)
//{
// WriteLog("ReadValueType");
// valueType = ReadType();
// WriteLog("ReadValueType", valueType.Name);
//}
// valueType = CheckAndReadType("ReadValueType", valueType, value.Value);
if (!ReadObject(valueType, ref val)) return false;
value.Key = key;
value.Value = val;
return true;
}
/// <summary>取得字典的键值类型,默认只支持获取两个泛型参数的字典的键值类型</summary>
/// <param name="type">字典类型</param>
/// <param name="keyType">键类型</param>
/// <param name="valueType">值类型</param>
/// <returns>是否获取成功,如果失败,则字典读取失败</returns>
protected virtual Boolean GetDictionaryEntryType(Type type, ref Type keyType, ref Type valueType)
{
// 两个泛型参数的泛型
if (type.IsGenericType)
{
Type[] ts = type.GetGenericArguments();
if (ts != null && ts.Length == 2)
{
keyType = ts[0];
valueType = ts[1];
return true;
}
}
return false;
}
#endregion
#region 枚举
/// <summary>尝试读取枚举</summary>
/// <param name="type">要读取的对象类型</param>
/// <param name="value">要读取的对象</param>
/// <returns>是否读取成功</returns>
public virtual Boolean ReadEnumerable(Type type, ref Object value)
{
return ReadEnumerable(type, ref value, ReadMember);
}
/// <summary>尝试读取枚举</summary>
/// <remarks>重点和难点在于如果得知枚举元素类型,这里假设所有元素类型一致,否则实在无法处理</remarks>
/// <param name="type">要读取的对象类型</param>
/// <param name="value">要读取的对象</param>
/// <param name="callback">处理成员的方法</param>
/// <returns>是否读取成功</returns>
public virtual Boolean ReadEnumerable(Type type, ref Object value, ReadObjectCallback callback)
{
//if (type == null)
//{
// if (value == null) return false;
// type = value.GetType();
//}
String lengths = null;
if (type.IsArray && type.GetArrayRank() > 1) lengths = ReadLengths();//lengths放在前面读取,主要是xml序列化时,lengths是写在父节点内的属性
type = CheckAndReadType("ReadEnumerableType", type, value);
if (!typeof(IEnumerable).IsAssignableFrom(type)) return false;
// 计算元素类型,如果无法计算,这里不能处理,否则能写不能读(因为不知道元素类型)
Type elementType = TypeX.GetElementType(type);
// 找不到元素类型
if (elementType == null) throw new SerializationException("无法找到" + type.FullName + "的元素类型!");
if (!ReadEnumerable(type, elementType, ref value, callback)) return false;
if (type.IsArray && type.GetArrayRank() > 1)
{
if (String.IsNullOrEmpty(lengths)) return false;
String[] strs = lengths.Split(',');
Int32[] param = new Int32[strs.Length];
for (int i = 0; i < strs.Length; i++)
{
param[i] = Convert.ToInt32(strs[i]);
}
Array array = Array.CreateInstance(type.GetElementType(), param);
Array sub = value as Array;
foreach (Object item in sub)
{
ArrEnum(array, ix => array.SetValue(item, ix), item);
}
if (array.Length > 0) value = array;
}
return true;
}
/// <summary>尝试读取枚举</summary>
/// <remarks>重点和难点在于如果得知枚举元素类型,这里假设所有元素类型一致,否则实在无法处理</remarks>
/// <param name="type">类型</param>
/// <param name="elementType">元素类型数组</param>
/// <param name="value">要读取的对象</param>
/// <param name="callback">处理成员的方法</param>
/// <returns>是否读取成功</returns>
public virtual Boolean ReadEnumerable(Type type, Type elementType, ref Object value, ReadObjectCallback callback)
{
if (!typeof(IEnumerable).IsAssignableFrom(type)) return false;
Int32 count = ReadSize();
// 提前创建对象,因为对象引用可能用到
Int32 index = objRefIndex;
if (index > 0 && Settings.UseObjRef && value == null)
{
if (type.IsArray && type.HasElementType && type.GetElementType() == elementType)
{
// 如果是数组,在不知道元素个数时,不处理
if (count > 0)
{
Array arr = TypeX.CreateInstance(type, count) as Array;
value = arr;
if (value != null) AddObjRef(index, value);
}
}
else
{
value = TypeX.CreateInstance(type);
if (value != null) AddObjRef(index, value);
}
}
IList list = ReadItems(type, elementType, count, callback);
if (list == null)
{
value = null;
// 结果为空,重新把对象引用设为空。不用担心里面里面已经引用了有对象的对象引用,因为既然列表返回空,表明里面没有元素
if (index > 0 && Settings.UseObjRef) AddObjRef(index, value);
return true;
}
if (ProcessItems(type, elementType, ref value, list)) return true;
// 无法处理
//WriteLog("ReadEnumerable", String.Format("已完成{1}元素列表的读取,但无法写入到{0}的枚举对象中", type, elementType));
XTrace.WriteLine("已完成{1}元素列表的读取,但无法写入到{0}的枚举对象中", type, elementType);
return false;
}
/// <summary>读取元素集合</summary>
/// <param name="type"></param>
/// <param name="elementType"></param>
/// <param name="count">元素个数</param>
/// <param name="callback">处理元素的方法</param>
/// <returns></returns>
protected virtual IList ReadItems(Type type, Type elementType, Int32 count, ReadObjectCallback callback)
{
//ArrayList list = new ArrayList();
Type listType = typeof(List<>).MakeGenericType(elementType);
IList list = TypeX.CreateInstance(listType) as IList;
// 元素个数小于0,可能是因为不支持元素个数,直接设为最大值
if (count < 0) count = Int32.MaxValue;
for (int i = 0; i < count; i++)
{
// 一旦有一个元素读不到,就中断
Object obj = null;
Depth++;
if (!ReadItem(elementType, ref obj, i, callback))
{
Depth--;
break;
}
Depth--;
list.Add(obj);
}
return list;
}
/// <summary>读取项</summary>
/// <param name="type"></param>
/// <param name="value"></param>
/// <param name="index">元素序号</param>
/// <param name="callback">处理元素的方法</param>
/// <returns></returns>
protected Boolean ReadItem(Type type, ref Object value, Int32 index, ReadObjectCallback callback)
{
// 读取成员前
ReadItemEventArgs e = null;
if (OnItemReading != null)
{
e = new ReadItemEventArgs(value, type, index, callback);
OnItemReading(this, e);
// 事件里面有可能改变了参数
value = e.Value;
type = e.Type;
index = e.Index;
callback = e.Callback;
// 事件处理器可能已经成功读取对象
if (e.Success) return true;
}
Boolean rs = OnReadItem(type, ref value, index, callback);
// 读取成员后
if (OnItemReaded != null)
{
if (e == null) e = new ReadItemEventArgs(value, type, index, callback);
e.Value = value;
e.Success = rs;
OnItemReaded(this, e);
// 事件处理器可以影响结果
value = e.Value;
rs = e.Success;
}
return rs;
}
/// <summary>读取项</summary>
/// <param name="type"></param>
/// <param name="value"></param>
/// <param name="index">元素序号</param>
/// <param name="callback">处理元素的方法</param>
/// <returns></returns>
protected virtual Boolean OnReadItem(Type type, ref Object value, Int32 index, ReadObjectCallback callback)
{
// 如果无法取得元素类型,则每个元素都单独写入类型
//if (type == null || type == typeof(object))
//{
// WriteLog("ReadItemType");
// type = ReadType();
// WriteLog("ReadItemType", type.Name);
//}
// type = CheckAndReadType("ReadItemType", type, value);
return ReadObject(type, ref value, callback);
}
/// <summary>处理结果集</summary>
/// <param name="type"></param>
/// <param name="elementType"></param>
/// <param name="value"></param>
/// <param name="items"></param>
/// <returns></returns>
protected Boolean ProcessItems(Type type, Type elementType, ref Object value, IList items)
{
if (type == items.GetType())
{
value = items;
return true;
}
// 添加方法
MethodInfoX method = null;
#region 如果源对象不为空,则尽量使用源对象
if (value != null)
{
if (type.IsArray)
{
Array arr = value as Array;
if (arr != null)
{
//if (XTrace.Debug && arr.Length != items.Count) throw new XSerializationException(null, "数组元素个数不匹配!");
for (int i = 0; i < arr.Length && i < items.Count; i++)
{
arr.SetValue(items[i], i);
}
return true;
}
}
if (typeof(IList).IsAssignableFrom(type))
{
IList list = value as IList;
if (list != null)
{
foreach (Object item in items)
{
list.Add(item);
}
return true;
}
}
//method = MethodInfoX.Create(type, "Add", new Type[] { elementType });
//if (method != null)
//{
// foreach (Object item in items)
// {
// method.Invoke(value, item);
// }
// return true;
//}
}
#endregion
#region 数组
if (type.IsArray && type.HasElementType && type.GetElementType() == elementType)
{
Array arr = TypeX.CreateInstance(type, items.Count) as Array;
items.CopyTo(arr, 0);
value = arr;
return true;
}
#endregion
#region 检查类型是否有指定类型的构造函数,如果有,直接创建类型,并把数组作为构造函数传入
ConstructorInfoX ci = ConstructorInfoX.Create(type, new Type[] { typeof(IEnumerable) });
if (ci != null)
{
value = ci.CreateInstance(items);
return true;
}
#endregion
#region 检查是否实现IEnumerable<>接口,如果不是,转为该接口,后面的构造函数需要用
Type enumType = typeof(IEnumerable<>).MakeGenericType(elementType);
// 如果数据不是IEnumerable<>类型,则需要转换
if (!enumType.IsAssignableFrom(items.GetType()))
{
// 用List<>来转换
Type listType = typeof(List<>).MakeGenericType(elementType);
IList list = TypeX.CreateInstance(listType) as IList;
if (list != null)
{
foreach (Object item in items)
{
list.Add(item);
}
if (type == listType)
{
value = list;
return true;
}
items = list;
}
}
#endregion
#region 泛型枚举接口IEnumerable<>的构造函数
ci = ConstructorInfoX.Create(type, new Type[] { enumType });
if (ci != null)
{
value = ci.CreateInstance(items);
return true;
}
#endregion
#region 是否具有Add方法
if (method == null) method = MethodInfoX.Create(type, "Add", new Type[] { elementType });
if (method != null)
{
if (value == null) value = TypeX.CreateInstance(type);
foreach (Object item in items)
{
method.Invoke(value, item);
}
return true;
}
method = MethodInfoX.Create(type, "AddRange", new Type[] { typeof(ICollection) });
if (method == null) method = MethodInfoX.Create(type, "AddRange", new Type[] { typeof(IList) });
if (method != null)
{
method.Invoke(value, items);
return true;
}
#endregion
return false;
}
#endregion
#region 序列化接口
/// <summary>读取实现了可序列化接口的对象</summary>
/// <param name="type">要读取的对象类型</param>
/// <param name="value">要读取的对象</param>
/// <param name="callback">处理成员的方法</param>
/// <returns>是否读取成功</returns>
public virtual Boolean ReadSerializable(Type type, ref Object value, ReadObjectCallback callback)
{
if (!typeof(ISerializable).IsAssignableFrom(type)) return false;
WriteLog("ReadSerializable", type.Name);
IObjectMemberInfo[] mis = GetMembers(type, value);
if (mis == null || mis.Length < 1) return true;
// 调试输出成员列表
if (Debug) ShowMembers("ReadSerializable", mis);
for (int i = 0; i < mis.Length; i++)
{
Depth++;
IObjectMemberInfo member = GetMemberBeforeRead(type, value, mis, i);
// 没有可读成员
if (member == null) continue;
WriteLog("ReadMember", member.Name, member.Type.Name);
if (!ReadMember(member.Type, ref value, member, i, callback)) return false;
Depth--;
}
// 如果为空,实例化并赋值。
if (value == null)
{
SerializationInfo info = new SerializationInfo(type, new FormatterConverter());
foreach (IObjectMemberInfo item in mis)
{
info.AddValue(item.Name, item[value], item.Type);
}
value = TypeX.CreateInstance(type, info, ObjectInfo.DefaultStreamingContext);
if (value != null) AddObjRef(objRefIndex, value);
}
return true;
}
#endregion
#region 未知对象
/// <summary>读取未知对象(其它所有方法都无法识别的对象),采用BinaryFormatter或者XmlSerialization</summary>
/// <param name="type">要读取的对象类型</param>
/// <param name="value">要读取的对象</param>
/// <param name="callback">处理成员的方法</param>
/// <returns>是否读取成功</returns>
public virtual Boolean ReadUnKnown(Type type, ref Object value, ReadObjectCallback callback)
{
WriteLog("ReadBinaryFormatter", type.Name);
// 调用.Net的二进制序列化来解决剩下的事情
BinaryFormatter bf = new BinaryFormatter();
MemoryStream ms = new MemoryStream(ReadBytes(-1));
value = bf.Deserialize(ms);
return true;
}
#endregion
#region 扩展处理类型
/// <summary>扩展读取,反射查找合适的读取方法</summary>
/// <param name="type">要读取的对象类型</param>
/// <param name="value">要读取的对象</param>
/// <returns></returns>
public Boolean ReadX(Type type, ref Object value)
{
if (type == typeof(Byte[]))
{
value = ReadBytes(-1);
return true;
}
if (type == typeof(Char[]))
{
value = ReadChars(-1);
return true;
}
if (type == typeof(Guid))
{
value = OnReadGuid();
return true;
}
if (type == typeof(IPAddress))
{
value = OnReadIPAddress();
return true;
}
if (type == typeof(IPEndPoint))
{
value = OnReadIPEndPoint();
return true;
}
if (typeof(Type).IsAssignableFrom(type))
{
value = OnReadType();
return true;
}
return false;
}
/// <summary>读取Guid</summary>
/// <returns></returns>
public virtual Guid ReadGuid() { return ReadObjRef<Guid>(OnReadGuid); }
/// <summary>读取Guid</summary>
/// <returns></returns>
protected virtual Guid OnReadGuid() { return new Guid(ReadBytes(16)); }
/// <summary>读取IPAddress</summary>
/// <returns></returns>
public virtual IPAddress ReadIPAddress() { return ReadObjRef<IPAddress>(OnReadIPAddress); }
/// <summary>读取IPAddress</summary>
/// <returns></returns>
protected virtual IPAddress OnReadIPAddress() { return new IPAddress(ReadBytes(-1)); }
/// <summary>读取IPEndPoint</summary>
/// <returns></returns>
public virtual IPEndPoint ReadIPEndPoint() { return ReadObjRef<IPEndPoint>(OnReadIPEndPoint); }
/// <summary>读取IPEndPoint</summary>
/// <returns></returns>
protected virtual IPEndPoint OnReadIPEndPoint()
{
IPEndPoint ep = new IPEndPoint(IPAddress.Any, 0);
//! 直接调用OnWrite,不写对象引用,将来可能得考虑写对象引用
ep.Address = OnReadIPAddress();
ep.Port = ReadInt32();
return ep;
}
/// <summary>读取Type</summary>
/// <returns></returns>
public Type ReadType()
{
Depth++;
// 分离出去,便于重载,而又能有效利用对象引用
Type type = ReadObjRef<Type>(OnReadType);
if (type != null) WriteLog("ReadType", type.FullName);
Depth--;
return type;
}
/// <summary>读取Type</summary>
/// <returns></returns>
protected virtual Type OnReadType()
{
String typeName = ReadString();
if (String.IsNullOrEmpty(typeName)) return null;
Type type = TypeX.GetType(typeName, true);
if (type != null) return type;
throw new XException("无法找到名为{0}的类型!", typeName);
}
/// <summary>检查对象类型与指定写入类型是否一致,若不一致,则先写入类型,以保证读取的时候能够以正确的类型读取。同时返回对象实际类型。</summary>
/// <param name="action"></param>
/// <param name="type"></param>
/// <param name="value"></param>
/// <returns></returns>
protected Type CheckAndReadType(String action, Type type, Object value)
{
if (!IsExactType(type))
{
WriteLog(action);
Type t = ReadObjectType();
//TODO 可以在Xml和Json测试猜测类型,写入后,删除Type部分,再尝试读取
if (t == null && type != null) t = GuessType(type);
type = t;
WriteLog(action, type.Name);
}
return type;
}
/// <summary>猜测类型。对于无法读取到对象类型的类型,并且是接口之类的,可以猜测</summary>
/// <param name="type"></param>
/// <returns></returns>
static Type GuessType(Type type)
{
if (type.IsInterface || type.IsAbstract)
{
// IEnumerable
if (typeof(IEnumerable).IsAssignableFrom(type))
{
if (!type.IsGenericType)
{
// IDictionary
if (type == typeof(IDictionary)) return typeof(Hashtable);
// IList
if (type == typeof(IList)) return typeof(ArrayList);
// IEnumerable
if (type == typeof(ICollection) || type == typeof(IEnumerable)) return typeof(ArrayList);
}
else
{
// 处理泛型
Type gt = type.GetGenericTypeDefinition();
if (gt != null)
{
// 处理泛型参数
Type[] gs = type.GetGenericArguments();
// IDictionary<,>
if (type == typeof(IDictionary<,>)) return typeof(Dictionary<,>).MakeGenericType(gs);
// IList<>
if (type == typeof(IList<>)) return typeof(List<>).MakeGenericType(gs);
// IEnumerable<>
if (type == typeof(ICollection<>) || type == typeof(IEnumerable<>)) typeof(List<>).MakeGenericType(gs);
}
}
}
return FindFirstExactType(type);
}
return type;
}
static Type FindFirstExactType(Type type)
{
if (IsExactType(type)) return type;
// 找到所有实现了该接口的类型,并返回第一个精确类型
//Type[] ts = TypeResolver.ResolveAll(type);
//if (ts != null && ts.Length > 0)
//{
// foreach (Type item in ts)
// {
// if (IsExactType(item)) return item;
// }
//}
//return null;
return AssemblyX.FindAllPlugins(type).FirstOrDefault(t => IsExactType(t));
}
/// <summary>读对象类型</summary>
/// <returns></returns>
protected virtual Type ReadObjectType() { return ReadType(); }
#endregion
#region 复杂对象
/// <summary>主要入口方法。从数据流中读取指定类型的对象</summary>
/// <param name="type">类型</param>
/// <returns>对象</returns>
public Object ReadObject(Type type)
{
Object value = null;
try
{
//return ReadObject(type, ref value, null) ? value : null;
// 尽管读取对象出错,但是可能已经读取部分,还是需要准确返回
ReadObject(type, ref value, null);
return value;
}
catch (XSerializationException ex)
{
// 如果本身就是序列化异常,砍断内部的异常链,太长没有意义
var se = new XSerializationException(ex.Member, "读取对象的" + (ex.Member == null ? "" : ex.Member.Name) + "出错,可能已读取部分,请查看Value属性!" + ex.Message);
se.Value = value;
throw se;
}
catch (Exception ex)
{
// 如果不是序列化异常,则包括内部异常链
var se = new XSerializationException(null, "读取对象出错,可能已读取部分,请查看Value属性!" + ex.Message, ex);
se.Value = value;
throw se;
}
}
/// <summary>主要入口方法。从数据流中读取指定类型的对象</summary>
/// <returns>对象</returns>
public T ReadObject<T>() { return (T)ReadObject(typeof(T)); }
/// <summary>主要入口方法。尝试读取目标对象指定成员的值,通过委托方法递归处理成员</summary>
/// <param name="type">要读取的对象类型</param>
/// <param name="value">要读取的对象</param>
/// <returns>是否读取成功</returns>
public Boolean ReadObject(Type type, ref Object value) { return ReadObject(type, ref value, ReadMember); }
/// <summary>尝试读取目标对象指定成员的值,处理基础类型、特殊类型、基础类型数组、特殊类型数组,通过委托方法处理成员</summary>
/// <param name="type">要读取的对象类型</param>
/// <param name="value">要读取的对象</param>
/// <param name="callback">处理成员的方法</param>
/// <returns>是否读取成功</returns>
public Boolean ReadObject(Type type, ref Object value, ReadObjectCallback callback)
{
// 检查数据流是否结束
if (EndOfStream) return false;
if (type == null && value != null) type = value.GetType();
if (callback == null) callback = ReadMember;
Object old = CurrentObject;
try
{
// 检查IAcessor接口
IAccessor accessor = null;
if (typeof(IAccessor).IsAssignableFrom(type))
{
// 如果为空,实例化并赋值。
if (value == null)
{
CurrentObject = value = TypeX.CreateInstance(type);
if (value != null) AddObjRef(objRefIndex, value);
}
accessor = value as IAccessor;
if (accessor != null && accessor.Read(this)) return true;
}
Boolean rs = ReadObjectWithEvent(type, ref value, callback);
// 检查IAcessor接口
if (accessor != null) rs = accessor.ReadComplete(this, rs);
return rs;
}
finally { CurrentObject = old; }
}
Boolean ReadObjectWithEvent(Type type, ref Object value, ReadObjectCallback callback)
{
// 事件
ReadObjectEventArgs e = null;
if (OnObjectReading != null)
{
e = new ReadObjectEventArgs(value, type, callback);
OnObjectReading(this, e);
// 事件里面有可能改变了参数
value = e.Value;
type = e.Type;
callback = e.Callback;
// 事件处理器可能已经成功读取对象
if (e.Success) return true;
}
Boolean rs = OnReadObject(type, ref value, callback);
// 事件
if (OnObjectReaded != null)
{
if (e == null) e = new ReadObjectEventArgs(value, type, callback);
e.Value = value;
e.Success = rs;
OnObjectReaded(this, e);
// 事件处理器可以影响结果
value = e.Value;
rs = e.Success;
}
return rs;
}
/// <summary>尝试读取目标对象指定成员的值,处理基础类型、特殊类型、基础类型数组、特殊类型数组,通过委托方法处理成员</summary>
/// <param name="type">要读取的对象类型</param>
/// <param name="value">要读取的对象</param>
/// <param name="callback">处理成员的方法</param>
/// <returns>是否读取成功</returns>
protected virtual Boolean OnReadObject(Type type, ref Object value, ReadObjectCallback callback)
{
if (callback == null) callback = ReadMember;
//! 2011-05-27 17:33
//! 精确类型,直接写入值
//! 未知类型,写对象引用,写类型,写对象
if (IsExactType(type))
{
// 基本类型
if (ReadValue(type, ref value)) return true;
// 读取对象引用
Int32 index = 0;
if (ReadObjRef(type, ref value, out index)) return true;
objRefIndex = index;
// 特殊类型
if (ReadX(type, ref value))
{
if (value != null) AddObjRef(index, value);
return true;
}
// 读取引用对象
if (ReadRefObject(type, ref value, callback))
{
if (value != null) AddObjRef(index, value);
return true;
}
return false;
}
else
{
// 读取对象引用
Int32 index = 0;
if (ReadObjRef(type, ref value, out index)) return true;
// 写对象类型时增加缩进,避免写顶级对象类型的对象引用时无法写入(Depth=1的对象是不写对象引用的)
Depth++;
type = CheckAndReadType("ReadObjectType", type, value);
Depth--;
// 基本类型
if (ReadValue(type, ref value))
{
if (value != null) AddObjRef(index, value);
return true;
}
// 特殊类型
if (ReadX(type, ref value))
{
if (value != null) AddObjRef(index, value);
return true;
}
// 读取引用对象
objRefIndex = index;
if (ReadRefObject(type, ref value, callback))
{
if (value != null) AddObjRef(index, value);
return true;
}
return false;
}
//return true;
}
/// <summary>尝试读取引用对象</summary>
/// <param name="type">要读取的对象类型</param>
/// <param name="value">要读取的对象</param>
/// <param name="callback">处理成员的方法</param>
/// <returns>是否读取成功</returns>
protected virtual Boolean ReadRefObject(Type type, ref Object value, ReadObjectCallback callback)
{
// 字典
if (typeof(IDictionary).IsAssignableFrom(type))
{
WriteLog("ReadDictionary", type.Name);
if (ReadDictionary(type, ref value, callback)) return true;
}
// 枚举
if (typeof(IEnumerable).IsAssignableFrom(type))
{
WriteLog("ReadEnumerable", type.Name);
if (ReadEnumerable(type, ref value, callback)) return true;
}
// 可序列化接口
if (ReadSerializable(type, ref value, callback)) return true;
// 复杂类型,处理对象成员
if (ReadCustomObject(type, ref value, callback)) return true;
// 检查数据流是否结束
if (EndOfStream) return false;
return ReadUnKnown(type, ref value, callback);
}
#region 对象引用
/// <summary>读取引用对象的包装,能自动从引用对象集合里面读取,如果不存在,则调用委托读取对象,并加入引用对象集合</summary>
/// <typeparam name="T"></typeparam>
/// <param name="func"></param>
/// <returns></returns>
T ReadObjRef<T>(Func<T> func)
{
Object obj = null;
Int32 index = 0;
if (ReadObjRef(typeof(T), ref obj, out index)) return (T)obj;
if (func != null)
{
obj = func();
if (obj != null) AddObjRef(index, obj);
return (T)obj;
}
return default(T);
}
List<Object> objRefs = new List<Object>();
Int32 objRefIndex = 0;
/// <summary>读取对象引用。</summary>
/// <param name="type">类型</param>
/// <param name="value">对象</param>
/// <param name="index">引用计数</param>
/// <returns>是否读取成功</returns>
public Boolean ReadObjRef(Type type, ref Object value, out Int32 index)
{
index = 0;
if (!Settings.UseObjRef) return false;
// 顶级特殊处理
if (Depth <= 1)
index = 1;
else
index = OnReadObjRefIndex();
if (index < 0) return false;
if (index == 0)
{
WriteLog("ReadObjRef", "null", type.Name);
value = null;
return true;
}
//// 如果引用计数刚好是下一个引用对象,说明这是该对象的第一次引用,返回false
//if (index == objRefs.Count + 1) return false;
//if (index > objRefs.Count) throw new XException("对象引用错误,无法找到引用计数为" + index + "的对象!");
// 引用计数等于索引加一
if (index > objRefs.Count)
{
WriteLog("ReadObjRef", index, type == null ? null : type.Name);
return false;
}
value = objRefs[index - 1];
if (value != null)
WriteLog("ReadObjRef", index, value.ToString(), value.GetType().Name);
else
WriteLog("ReadObjRef", index, "", type == null ? "" : type.Name);
return true;
}
/// <summary>读取对象引用计数</summary>
/// <returns></returns>
protected virtual Int32 OnReadObjRefIndex() { return ReadInt32(); }
/// <summary>添加对象引用</summary>
/// <param name="index">引用计数</param>
/// <param name="value">对象</param>
protected virtual void AddObjRef(Int32 index, Object value)
{
if (!Settings.UseObjRef || index < 1) return;
//if (value == null) return;
while (index > objRefs.Count) objRefs.Add(null);
objRefs[index - 1] = value;
}
#endregion
#endregion
#region 自定义对象
/// <summary>尝试读取自定义对象</summary>
/// <param name="type">要读取的对象类型</param>
/// <param name="value">要读取的对象</param>
/// <param name="callback">处理成员的方法</param>
/// <returns>是否读取成功</returns>
public virtual Boolean ReadCustomObject(Type type, ref Object value, ReadObjectCallback callback)
{
Object old = CurrentObject;
CurrentObject = value;
try
{
IObjectMemberInfo[] mis = GetMembers(type, value);
if (callback == null) callback = ReadMember;
// 如果为空,实例化并赋值。
if (value == null)
{
CurrentObject = value = TypeX.CreateInstance(type);
if (value != null) AddObjRef(objRefIndex, value);
}
if (mis == null || mis.Length < 1) return true;
// 调试输出成员列表
if (Debug) ShowMembers("ReadCustomObject", mis);
for (int i = 0; i < mis.Length; i++)
{
Depth++;
IObjectMemberInfo member = GetMemberBeforeRead(type, value, mis, i);
// 没有可读成员
if (member == null) continue;
// 基础类型输出日志时,同时输出值,更直观
if (Type.GetTypeCode(mis[i].Type) == TypeCode.Object)
WriteLog("ReadMember", member.Name, member.Type.Name);
if (!ReadMember(member.Type, ref value, member, i, callback)) return false;
// 基础类型输出日志时,同时输出值,更直观
if (Type.GetTypeCode(mis[i].Type) != TypeCode.Object)
WriteLog("ReadMember", member.Name, member.Type.Name, mis[i][value]);
Depth--;
}
return true;
}
finally { CurrentObject = old; }
}
/// <summary>读取成员之前获取要读取的成员,默认是index处的成员,实现者可以重载,改变当前要读取的成员,如果当前成员不在数组里面,则实现者自己跳到下一个可读成员。</summary>
/// <param name="type">要读取的对象类型</param>
/// <param name="value">要读取的对象</param>
/// <param name="members">可匹配成员数组</param>
/// <param name="index">索引</param>
/// <returns></returns>
protected virtual IObjectMemberInfo GetMemberBeforeRead(Type type, Object value, IObjectMemberInfo[] members, Int32 index) { return members[index]; }
/// <summary>根据名称,从成员数组中查找成员</summary>
/// <param name="members">可匹配成员数组</param>
/// <param name="name">名称</param>
/// <returns></returns>
protected IObjectMemberInfo GetMemberByName(IObjectMemberInfo[] members, String name)
{
foreach (IObjectMemberInfo item in members)
{
if (item.Name == name) return item;
}
return null;
}
/// <summary>读取对象成员</summary>
/// <param name="type">要读取的对象类型</param>
/// <param name="value">要读取的对象</param>
/// <param name="member">成员</param>
/// <param name="index">成员索引</param>
/// <param name="callback">处理成员的方法</param>
/// <returns>是否读取成功</returns>
public Boolean ReadMember(Type type, ref Object value, IObjectMemberInfo member, Int32 index, ReadObjectCallback callback)
{
if (callback == null) callback = ReadMember;
IObjectMemberInfo old = CurrentMember;
CurrentMember = member;
#if !DEBUG
try
#endif
{
// 读取成员前
ReadMemberEventArgs e = null;
if (OnMemberReading != null)
{
e = new ReadMemberEventArgs(value, type, member, index, callback);
OnMemberReading(this, e);
// 事件里面有可能改变了参数
value = e.Value;
type = e.Type;
member = e.Member;
index = e.Index;
callback = e.Callback;
// 事件处理器可能已经成功读取对象
if (e.Success)
{
CurrentMember = old;
return true;
}
}
Object obj = null;
Boolean rs = OnReadMember(type, ref obj, member, index, callback);
// 读取成员后
if (OnMemberReaded != null)
{
if (e == null) e = new ReadMemberEventArgs(value, type, member, index, callback);
e.Value = obj;
e.Success = rs;
OnMemberReaded(this, e);
// 事件处理器可以影响结果
obj = e.Value;
rs = e.Success;
}
// 设置成员的值
member[value] = obj;
CurrentMember = old;
return rs;
}
#if !DEBUG
catch (XException) { throw; }
catch (Exception ex)
{
throw new XSerializationException(member, ex);
}
#endif
}
/// <summary>读取对象成员</summary>
/// <param name="type">要读取的对象类型</param>
/// <param name="value">要读取的对象</param>
/// <param name="member">成员</param>
/// <param name="index">成员索引</param>
/// <param name="callback">处理成员的方法</param>
/// <returns>是否读取成功</returns>
protected virtual Boolean OnReadMember(Type type, ref Object value, IObjectMemberInfo member, Int32 index, ReadObjectCallback callback)
{
//type = CheckAndReadType("ReadMemberType", type, value);
//if (type == typeof(Object))
//{
// WriteLog("ReadMemberType");
// type = ReadType();
// WriteLog("ReadMemberType", type.Name);
//}
return callback(this, type, ref value, callback);
}
static Boolean ReadMember(IReader reader, Type type, ref Object value, ReadObjectCallback callback) { return reader.ReadObject(type, ref value, callback); }
#endregion
#region 事件
/// <summary>读对象前触发。</summary>
public event EventHandler<ReadObjectEventArgs> OnObjectReading;
/// <summary>读对象后触发。</summary>
public event EventHandler<ReadObjectEventArgs> OnObjectReaded;
/// <summary>读成员前触发。</summary>
public event EventHandler<ReadMemberEventArgs> OnMemberReading;
/// <summary>读成员后触发。</summary>
public event EventHandler<ReadMemberEventArgs> OnMemberReaded;
/// <summary>读字典项前触发。</summary>
public event EventHandler<ReadDictionaryEventArgs> OnDictionaryReading;
/// <summary>读字典项后触发。</summary>
public event EventHandler<ReadDictionaryEventArgs> OnDictionaryReaded;
/// <summary>读枚举项前触发。</summary>
public event EventHandler<ReadItemEventArgs> OnItemReading;
/// <summary>读枚举项后触发。</summary>
public event EventHandler<ReadItemEventArgs> OnItemReaded;
#endregion
#region 方法
/// <summary>读取大小</summary>
/// <returns></returns>
public Int32 ReadSize()
{
if (!UseSize) return -1;
Int32 size = OnReadSize();
WriteLog("ReadSize", size);
return size;
}
/// <summary>读取大小</summary>
/// <returns></returns>
protected virtual Int32 OnReadSize()
{
switch (Settings.SizeFormat)
{
case TypeCode.Int16:
case TypeCode.UInt16:
return ReadInt16();
case TypeCode.Int32:
case TypeCode.UInt32:
case TypeCode.Int64:
case TypeCode.UInt64:
default:
return ReadInt32();
}
}
/// <summary>读取多维数组相关参数</summary>
/// <returns></returns>
protected virtual String ReadLengths()
{
String lengths = ReadString();
WriteLog("ReadLengths", lengths);
return lengths;
}
#endregion
#region 辅助方法
/// <summary>给多维数组赋值</summary>
/// <param name="arr"></param>
/// <param name="func"></param>
/// <param name="value"></param>
protected void ArrEnum(Array arr, Action<Int32[]> func, Object value)
{
Int32[] ix = new Int32[arr.Rank];
Int32 rank = 0;
for (int i = 0; i < arr.Length; i++)
{
// 当前层以下都清零
for (int j = rank + 1; j < arr.Rank; j++)
{
ix[j] = 0;
}
// 设置为最底层
rank = arr.Rank - 1;
//do something
//arr.SetValue(i, ix);
Object val = arr.GetValue(ix);
if (val == null || (val.Equals(0) && val != value))
{
func(ix);
return;
}
// 当前层递加
ix[rank]++;
// 如果超过上限,则减少层次
while (ix[rank] >= arr.GetLength(rank))
{
rank--;
if (rank < 0) break;
ix[rank]++;
}
}
}
#endregion
#region 辅助属性
/// <summary>获取一个值,该值表示当前的流位置是否在流的末尾。</summary>
/// <returns>如果当前的流位置在流的末尾,则为 true;否则为 false。</returns>
public virtual Boolean EndOfStream
{
get
{
var s = Stream;
if (s == null) return false;
return s.Position == s.Length;
}
}
#endregion
}
}
|