/// <summary>
        /// 序列化一个对象到Byte数组,无法序列化,将抛出ArgumentException异常
        /// </summary>
        /// <param name="obj">对象</param>
        /// <param name="writeToBytes">将要在这个数组基础上开始写入,指定Null表示新建一个数组</param>
        /// <param name="startIndex">将要从数组的哪个位置开始写入</param>
        /// <param name="maxWriteSize">最大允许的写入长度</param>
        /// <param name="fullLengthSchema">是否完整包含每个子对象的长度</param>
        /// <returns>返回有效大小</returns>
        public static int SerializeTo(object obj, ref byte[] writeToBytes, int startIndex, int maxWriteSize, bool fullLengthSchema = true)
        {
            //try
            {
                bool isFieldNullable = false;

                //数据块
                ZipBytesWriter bwData;
                if (writeToBytes != null)
                {
                    bwData = new ZipBytesWriter(writeToBytes, startIndex, maxWriteSize);
                }
                else
                {
                    bwData = new ZipBytesWriter(maxWriteSize);
                }

                //写标识头
                bwData.Write((fullLengthSchema) ? Byte_One : Byte_Zero);

                if (obj == null)
                {
                    if (fullLengthSchema)
                    {
                        bwData.Write((ushort)1);
                    }
                    bwData.Write(Byte_Zero);
                    writeToBytes = bwData.Bytes;
                    return(bwData.EffectiveBytesLength);
                }
                int metablockStart             = 0;
                int metablockLen               = 0;
                Stack <SerializeInfo> bufStack = new Stack <SerializeInfo>();

                bufStack.Push(new SerializeInfo(obj, isFieldNullable, bwData.EffectiveBytesLength));
                if (fullLengthSchema)
                {
                    bwData.Write(DefaultFieldLen);
                }
                while (bufStack.Count > 0)
                {
                    SerializeInfo nowSerializeInfo = bufStack.Peek();

                    if (nowSerializeInfo.TheObject == null)
                    {
                        bwData.WriteNullHead(true); //写入null
                        bufStack.Pop();
                        if (fullLengthSchema)
                        {
                            metablockStart = nowSerializeInfo.ByteStartIndexOrEndPoint;
                            metablockLen   = bwData.EffectiveBytesLength - metablockStart - 2;
                            ZipBytesWriter.WriteAtUshort(bwData.Bytes, metablockStart, (ushort)metablockLen);
                        }
                    }
                    else
                    {
                        if (nowSerializeInfo.TheType == null)  //未检查过
                        {
                            if (nowSerializeInfo.IsNullable)
                            {
                                bwData.WriteNullHead(false);
                            }

                            nowSerializeInfo.TheType = nowSerializeInfo.TheObject.GetType();

                            //是基础元素
                            if (BytesHelper.TryWriteBytes(nowSerializeInfo.TheObject, nowSerializeInfo.TheType, bwData))
                            {
                                bufStack.Pop();
                                if (fullLengthSchema)
                                {
                                    metablockStart = nowSerializeInfo.ByteStartIndexOrEndPoint;
                                    metablockLen   = bwData.EffectiveBytesLength - metablockStart - 2;
                                    if (metablockLen > ushort.MaxValue)
                                    {
                                        throw new Exception("序列化的子字段大小超出65535:" + nowSerializeInfo.FieldInfos[nowSerializeInfo.Index - 1].FieldName);
                                    }
                                    ZipBytesWriter.WriteAtUshort(bwData.Bytes, metablockStart, (ushort)metablockLen);
                                }
                            }
                            else //不是基础元素
                            {
                                if (nowSerializeInfo.TheType.IsArray)
                                {
                                    nowSerializeInfo.IsArray          = true;
                                    nowSerializeInfo.Length_FieldInfo = (nowSerializeInfo.TheObject as Array).Length;

                                    //写入数组长度
                                    bwData.WriteArrayHead(nowSerializeInfo.Length_FieldInfo);
                                }
                                else if (nowSerializeInfo.TheType.GetInterface("IList`1", false) != null)
                                {
                                    nowSerializeInfo.IsIList = true;

                                    nowSerializeInfo.Length_FieldInfo = (nowSerializeInfo.TheObject as IList).Count;

                                    //写入数组长度
                                    bwData.WriteArrayHead(nowSerializeInfo.Length_FieldInfo);
                                }
                                else if (nowSerializeInfo.TheType.GetInterface("IDictionary`2", false) != null)
                                {
                                    nowSerializeInfo.IsIDictionary = true;

                                    IDictionary id      = nowSerializeInfo.TheObject as IDictionary;
                                    int         dLength = id.Count;
                                    nowSerializeInfo.Length_FieldInfo = dLength * 2;

                                    object[] kvs = new object[nowSerializeInfo.Length_FieldInfo];
                                    id.Keys.CopyTo(kvs, 0);
                                    id.Values.CopyTo(kvs, dLength);

                                    nowSerializeInfo.TheObject = kvs;

                                    //写入数组长度
                                    bwData.WriteArrayHead(nowSerializeInfo.Length_FieldInfo);
                                }
                                else
                                {
                                    bwData.WriteNullHead(false);

                                    DynamicFieldInfo[] fis;

                                    lock (FI_Lookup)
                                    {
                                        if (FI_Lookup.ContainsKey(nowSerializeInfo.TheType))
                                        {
                                            fis = FI_Lookup[nowSerializeInfo.TheType];
                                        }
                                        else
                                        {
                                            PropertyInfo[]          fi      = nowSerializeInfo.TheType.GetProperties(AllInstanceBindingFlags).OrderBy(c => c.Name).ToArray();
                                            List <DynamicFieldInfo> tempFis = new List <DynamicFieldInfo>();
                                            for (int i = 0; i < fi.Length; i++)
                                            {
                                                PropertyInfo fiNow = fi[i];
                                                object[]     at    = fiNow.GetCustomAttributes(typeof(System.NonSerializedAttribute), true);
                                                if (at.Length == 0)
                                                {
                                                    tempFis.Add(new DynamicFieldInfo()
                                                    {
                                                        TheField = fiNow
                                                    });
                                                }
                                            }
                                            fis = tempFis.ToArray();
                                            FI_Lookup.Add(nowSerializeInfo.TheType, fis);
                                        }
                                    }


                                    nowSerializeInfo.FieldInfos       = fis;
                                    nowSerializeInfo.Length_FieldInfo = fis.Length;
                                }



                                if (nowSerializeInfo.Length_FieldInfo == 0)  //虽然不是基础元素,但没有可序列化的字段
                                {
                                    bufStack.Pop();
                                    if (fullLengthSchema)
                                    {
                                        metablockStart = nowSerializeInfo.ByteStartIndexOrEndPoint;
                                        metablockLen   = bwData.EffectiveBytesLength - metablockStart - 2;
                                        if (metablockLen > ushort.MaxValue)
                                        {
                                            throw new Exception("序列化的子字段大小超出65535:" + nowSerializeInfo.FieldInfos[nowSerializeInfo.Index - 1].FieldName);
                                        }
                                        ZipBytesWriter.WriteAtUshort(bwData.Bytes, metablockStart, (ushort)metablockLen);
                                    }
                                }
                                else
                                {
                                    nowSerializeInfo.Index = 0;

                                    isFieldNullable = false;
                                    object innerObject = nowSerializeInfo.GetInnerField(ref isFieldNullable);
                                    nowSerializeInfo.Index++;

                                    bufStack.Push(new SerializeInfo(innerObject, isFieldNullable, bwData.EffectiveBytesLength));
                                    if (fullLengthSchema)
                                    {
                                        bwData.Write(DefaultFieldLen);
                                    }
                                }
                            }
                        }
                        else //上次检查过
                        {
                            if (nowSerializeInfo.Length_FieldInfo == nowSerializeInfo.Index)  //检查完了
                            {
                                bufStack.Pop();
                                if (fullLengthSchema)
                                {
                                    metablockStart = nowSerializeInfo.ByteStartIndexOrEndPoint;
                                    metablockLen   = bwData.EffectiveBytesLength - metablockStart - 2;
                                    if (metablockLen > ushort.MaxValue)
                                    {
                                        throw new Exception("序列化的子字段大小超出65535:" + nowSerializeInfo.FieldInfos[nowSerializeInfo.Index - 1].FieldName);
                                    }
                                    ZipBytesWriter.WriteAtUshort(bwData.Bytes, metablockStart, (ushort)metablockLen);
                                }
                            }
                            else
                            {
                                isFieldNullable = false;
                                object innerObject = nowSerializeInfo.GetInnerField(ref isFieldNullable);
                                nowSerializeInfo.Index++;

                                bufStack.Push(new SerializeInfo(innerObject, isFieldNullable, bwData.EffectiveBytesLength));
                                if (fullLengthSchema)
                                {
                                    bwData.Write(DefaultFieldLen);
                                }
                            }
                        }
                    }
                }

                writeToBytes = bwData.Bytes;
                return(bwData.EffectiveBytesLength);
            }
            //catch (Exception ee)
            {
                //throw new SerializeException(obj.GetType().ToString() + "Data bytes and type not match:" + ee.Message);
            }
        }
Beispiel #2
0
        /// <summary>
        /// 尝试直接序列化基础值类型(包括其数组)
        /// </summary>
        /// <param name="value">对象</param>
        /// <param name="type">对象的类型</param>
        /// <param name="theByteWriter">写入Write</param>
        /// <returns>能否执行</returns>
        public static bool TryWriteBytes(object value, Type type, ZipBytesWriter theByteWriter)
        {
            if (value == null)
            {
                return false;
            }
            
            if (type.IsEnum)
            {
                type = type.GetFields()[0].FieldType;
            }

            if (type == Type_Bool)
            {
                theByteWriter.Write((bool)value);
                return true;
            }
            if (type == Type_Byte)
            {
                theByteWriter.Write((byte)value);
                return true;
            }
            if (type == Type_SByte)
            {
                theByteWriter.Write((sbyte)value);
                return true;
            }
            if (type == Type_UInt16)
            {
                theByteWriter.Write((UInt16)value);
                return true;
            }
            if (type == Type_Int16)
            {
                theByteWriter.Write((Int16)value);
                return true;
            }
            if (type == Type_Char)
            {
                theByteWriter.Write((Char)value);
                return true;
            }
            if (type == Type_UInt32)
            {
                theByteWriter.Write((UInt32)value);
                return true;
            }
            if (type == Type_Int32)
            {
                theByteWriter.Write((Int32)value);
                return true;
            }
            if (type == Type_UInt64)
            {
                theByteWriter.Write((UInt64)value);
                return true;
            }
            if (type == Type_Int64)
            {
                theByteWriter.Write((Int64)value);
                return true;
            }
            if (type == Type_Single)
            {
                theByteWriter.Write((Single)value);
                return true;
            }
            if (type == Type_Double)
            {
                theByteWriter.Write((Double)value);
                return true;
            }
            if (type == Type_Decimal)
            {
                theByteWriter.Write((Decimal)value);
                return true;
            }
            if (type == Type_Guid)
            {
                theByteWriter.Write((Guid)value);
                return true;
            }
            if (type == Type_DateTime)
            {
                theByteWriter.Write((DateTime)value);
                return true;
            }
            if (type == Type_TimeSpan)
            {
                theByteWriter.Write((TimeSpan)value);
                return true;
            }
            if (type == Type_String)
            {
                theByteWriter.Write((String)value);
                return true;
            }

            
            if (type.IsArray)
            {
                Type elemtT = type.GetElementType();
                if (elemtT.IsEnum)
                {
#if Server || WP
                    type = elemtT.GetFields()[0].FieldType;
                    type = type.MakeArrayType();

#else
                    Type elemtUnderType = null;
                    FieldInfo elemtValueField = null;

                    elemtValueField = elemtT.GetFields()[0];
                    elemtUnderType = elemtValueField.FieldType;
                    type = elemtUnderType.MakeArrayType();

                    Array oArray = value as Array;
                    int arrayLength = oArray.Length;
                    Array newArray = Array.CreateInstance(elemtUnderType, arrayLength);
                    Array.Copy(oArray, 0, newArray, 0, arrayLength);

                    value = newArray;
#endif
                }
            }

            if (type == Type_Bools)
            {
                theByteWriter.Write((bool[])value);
                return true;
            }
            if (type == Type_Bytes)
            {
                theByteWriter.Write((byte[])value, ((byte[])value).Length);
                return true;
            }
            if (type == Type_SBytes)
            {
                theByteWriter.Write((sbyte[])value);
                return true;
            }
            if (type == Type_UInt16s)
            {
                theByteWriter.Write((UInt16[])value);
                return true;
            }
            if (type == Type_Int16s)
            {
                theByteWriter.Write((Int16[])value);
                return true;
            }
            if (type == Type_Chars)
            {
                theByteWriter.Write((Char[])value);
                return true;
            }
            if (type == Type_UInt32s)
            {
                theByteWriter.Write((UInt32[])value);
                return true;
            }
            if (type == Type_Int32s)
            {
                theByteWriter.Write((Int32[])value);
                return true;
            }
            if (type == Type_UInt64s)
            {
                theByteWriter.Write((UInt64[])value);
                return true;
            }
            if (type == Type_Int64s)
            {
                theByteWriter.Write((Int64[])value);
                return true;
            }
            if (type == Type_Singles)
            {
                theByteWriter.Write((Single[])value);
                return true;
            }
            if (type == Type_Doubles)
            {
                theByteWriter.Write((Double[])value);
                return true;
            }
            if (type == Type_Decimals)
            {
                theByteWriter.Write((Decimal[])value);
                return true;
            }
            if (type == Type_Guids)
            {
                theByteWriter.Write((Guid[])value);
                return true;
            }
            if (type == Type_DateTimes)
            {
                theByteWriter.Write((DateTime[])value);
                return true;
            }
            if (type == Type_TimeSpans)
            {
                theByteWriter.Write((TimeSpan[])value);
                return true;
            }

            return false;
        }