示例#1
0
        /// <summary>
        /// This is the more "complete" version of Serialize, which handles single instances of mapped types.
        /// The value is written as a complete field, including field-header and (for sub-objects) a
        /// length-prefix
        /// In addition to that, this provides support for:
        ///  - basic values; individual int / string / Guid / etc
        ///  - IEnumerable sequences of any type handled by TrySerializeAuxiliaryType
        ///
        /// </summary>
        internal bool TrySerializeAuxiliaryType(ProtoWriter writer, Type type, DataFormat format, int tag, object value)
        {
            if (type == null)
            {
                type = value.GetType();
            }

            TypeCode typecode = Type.GetTypeCode(type);
            int      modelKey;
            // note the "ref type" here normalizes against proxies
            WireType wireType = GetWireType(typecode, format, ref type, out modelKey);


            if (modelKey >= 0)
            {   // write the header, but defer to the model
                ProtoWriter.WriteFieldHeader(tag, wireType, writer);
                switch (wireType)
                {
                case WireType.None:
                    throw ProtoWriter.CreateException(writer);

                case WireType.StartGroup:
                case WireType.String:
                    // needs a wrapping length etc
                    SubItemToken token = ProtoWriter.StartSubItem(value, writer);
                    Serialize(modelKey, value, writer);
                    ProtoWriter.EndSubItem(token, writer);
                    return(true);

                default:
                    Serialize(modelKey, value, writer);
                    return(true);
                }
            }

            if (wireType != WireType.None)
            {
                ProtoWriter.WriteFieldHeader(tag, wireType, writer);
            }
            switch (typecode)
            {
            case TypeCode.Int16: ProtoWriter.WriteInt16((short)value, writer); return(true);

            case TypeCode.Int32: ProtoWriter.WriteInt32((int)value, writer); return(true);

            case TypeCode.Int64: ProtoWriter.WriteInt64((long)value, writer); return(true);

            case TypeCode.UInt16: ProtoWriter.WriteUInt16((ushort)value, writer); return(true);

            case TypeCode.UInt32: ProtoWriter.WriteUInt32((uint)value, writer); return(true);

            case TypeCode.UInt64: ProtoWriter.WriteUInt64((ulong)value, writer); return(true);

            case TypeCode.Boolean: ProtoWriter.WriteBoolean((bool)value, writer); return(true);

            case TypeCode.SByte: ProtoWriter.WriteSByte((sbyte)value, writer); return(true);

            case TypeCode.Byte: ProtoWriter.WriteByte((byte)value, writer); return(true);

            case TypeCode.Char: ProtoWriter.WriteUInt16((ushort)(char)value, writer); return(true);

            case TypeCode.Double: ProtoWriter.WriteDouble((double)value, writer); return(true);

            case TypeCode.Single: ProtoWriter.WriteSingle((float)value, writer); return(true);

            case TypeCode.DateTime: BclHelpers.WriteDateTime((DateTime)value, writer); return(true);

            case TypeCode.Decimal: BclHelpers.WriteDecimal((decimal)value, writer); return(true);

            case TypeCode.String: ProtoWriter.WriteString((string)value, writer); return(true);
            }
            if (type == typeof(byte[]))
            {
                ProtoWriter.WriteBytes((byte[])value, writer); return(true);
            }
            if (type == typeof(TimeSpan))
            {
                BclHelpers.WriteTimeSpan((TimeSpan)value, writer); return(true);
            }
            if (type == typeof(Guid))
            {
                BclHelpers.WriteGuid((Guid)value, writer); return(true);
            }
            if (type == typeof(Uri))
            {
                ProtoWriter.WriteString(((Uri)value).AbsoluteUri, writer); return(true);
            }

            // by now, we should have covered all the simple cases; if we wrote a field-header, we have
            // forgotten something!
            Helpers.DebugAssert(wireType == WireType.None);

            // now attempt to handle sequences (including arrays and lists)
            IEnumerable sequence = value as IEnumerable;

            if (sequence != null)
            {
                foreach (object item in sequence)
                {
                    if (item == null)
                    {
                        throw new NullReferenceException();
                    }
                    if (!TrySerializeAuxiliaryType(writer, null, format, tag, item))
                    {
                        ThrowUnexpectedType(item.GetType());
                    }
                }
                return(true);
            }
            return(false);
        }
示例#2
0
        internal bool TrySerializeAuxiliaryType(ProtoWriter writer, Type type, DataFormat format, int tag, object value, bool isInsideList)
        {
            if (type == null)
            {
                type = value.GetType();
            }
            ProtoTypeCode typeCode = Helpers.GetTypeCode(type);
            int           modelKey;
            WireType      wireType = GetWireType(typeCode, format, ref type, out modelKey);

            if (modelKey >= 0)
            {
                if (Helpers.IsEnum(type))
                {
                    Serialize(modelKey, value, writer);
                    return(true);
                }
                ProtoWriter.WriteFieldHeader(tag, wireType, writer);
                switch (wireType)
                {
                case WireType.None:
                    throw ProtoWriter.CreateException(writer);

                case WireType.String:
                case WireType.StartGroup:
                {
                    SubItemToken token = ProtoWriter.StartSubItem(value, writer);
                    Serialize(modelKey, value, writer);
                    ProtoWriter.EndSubItem(token, writer);
                    return(true);
                }

                default:
                    Serialize(modelKey, value, writer);
                    return(true);
                }
            }
            if (wireType != WireType.None)
            {
                ProtoWriter.WriteFieldHeader(tag, wireType, writer);
            }
            switch (typeCode)
            {
            case ProtoTypeCode.Int16:
                ProtoWriter.WriteInt16((short)value, writer);
                return(true);

            case ProtoTypeCode.Int32:
                ProtoWriter.WriteInt32((int)value, writer);
                return(true);

            case ProtoTypeCode.Int64:
                ProtoWriter.WriteInt64((long)value, writer);
                return(true);

            case ProtoTypeCode.UInt16:
                ProtoWriter.WriteUInt16((ushort)value, writer);
                return(true);

            case ProtoTypeCode.UInt32:
                ProtoWriter.WriteUInt32((uint)value, writer);
                return(true);

            case ProtoTypeCode.UInt64:
                ProtoWriter.WriteUInt64((ulong)value, writer);
                return(true);

            case ProtoTypeCode.Boolean:
                ProtoWriter.WriteBoolean((bool)value, writer);
                return(true);

            case ProtoTypeCode.SByte:
                ProtoWriter.WriteSByte((sbyte)value, writer);
                return(true);

            case ProtoTypeCode.Byte:
                ProtoWriter.WriteByte((byte)value, writer);
                return(true);

            case ProtoTypeCode.Char:
                ProtoWriter.WriteUInt16((char)value, writer);
                return(true);

            case ProtoTypeCode.Double:
                ProtoWriter.WriteDouble((double)value, writer);
                return(true);

            case ProtoTypeCode.Single:
                ProtoWriter.WriteSingle((float)value, writer);
                return(true);

            case ProtoTypeCode.DateTime:
                BclHelpers.WriteDateTime((DateTime)value, writer);
                return(true);

            case ProtoTypeCode.Decimal:
                BclHelpers.WriteDecimal((decimal)value, writer);
                return(true);

            case ProtoTypeCode.String:
                ProtoWriter.WriteString((string)value, writer);
                return(true);

            case ProtoTypeCode.ByteArray:
                ProtoWriter.WriteBytes((byte[])value, writer);
                return(true);

            case ProtoTypeCode.TimeSpan:
                BclHelpers.WriteTimeSpan((TimeSpan)value, writer);
                return(true);

            case ProtoTypeCode.Guid:
                BclHelpers.WriteGuid((Guid)value, writer);
                return(true);

            case ProtoTypeCode.Uri:
                ProtoWriter.WriteString(((Uri)value).AbsoluteUri, writer);
                return(true);

            default:
            {
                IEnumerable enumerable = value as IEnumerable;
                if (enumerable != null)
                {
                    if (isInsideList)
                    {
                        throw CreateNestedListsNotSupported();
                    }
                    foreach (object item in enumerable)
                    {
                        if (item == null)
                        {
                            throw new NullReferenceException();
                        }
                        if (!TrySerializeAuxiliaryType(writer, null, format, tag, item, isInsideList: true))
                        {
                            ThrowUnexpectedType(item.GetType());
                        }
                    }
                    return(true);
                }
                return(false);
            }
            }
        }