示例#1
0
        private void SerializeCore(ProtoWriter writer, object value)
        {
            if (value == null)
            {
                throw new ArgumentNullException("value");
            }
            Type type = value.GetType();
            int  key  = this.GetKey(ref type);

            if (key >= 0)
            {
                this.Serialize(key, value, writer);
                return;
            }
            if (!this.TrySerializeAuxiliaryType(writer, type, DataFormat.Default, 1, value, false))
            {
                TypeModel.ThrowUnexpectedType(type);
            }
        }
示例#2
0
        internal bool TryDeserializeAuxiliaryType(ProtoReader reader, DataFormat format, int tag, Type type, ref object value, bool skipOtherFields, bool asListItem, bool autoCreate, bool insideList)
        {
            if (type == null)
            {
                throw new ArgumentNullException("type");
            }
            ProtoTypeCode typecode = Helpers.GetTypeCode(type);
            int           modelKey;
            WireType      wiretype = this.GetWireType(typecode, format, ref type, out modelKey);
            bool          found    = false;

            if (wiretype == WireType.None)
            {
                Type itemType = TypeModel.GetListItemType(this, type);
                if (itemType == null && type.IsArray && type.GetArrayRank() == 1 && type != typeof(byte[]))
                {
                    itemType = type.GetElementType();
                }
                if (itemType != null)
                {
                    if (insideList)
                    {
                        throw TypeModel.CreateNestedListsNotSupported();
                    }
                    found = this.TryDeserializeList(this, reader, format, tag, type, itemType, ref value);
                    if (!found && autoCreate)
                    {
                        value = TypeModel.CreateListInstance(type, itemType);
                    }
                    return(found);
                }
                else
                {
                    TypeModel.ThrowUnexpectedType(type);
                }
            }
            while (!found || !asListItem)
            {
                int fieldNumber = reader.ReadFieldHeader();
                if (fieldNumber <= 0)
                {
                    break;
                }
                if (fieldNumber != tag)
                {
                    if (!skipOtherFields)
                    {
                        throw ProtoReader.AddErrorData(new InvalidOperationException("Expected field " + tag.ToString() + ", but found " + fieldNumber.ToString()), reader);
                    }
                    reader.SkipField();
                }
                else
                {
                    found = true;
                    reader.Hint(wiretype);
                    if (modelKey >= 0)
                    {
                        switch (wiretype)
                        {
                        case WireType.String:
                        case WireType.StartGroup:
                        {
                            SubItemToken token = ProtoReader.StartSubItem(reader);
                            value = this.Deserialize(modelKey, value, reader);
                            ProtoReader.EndSubItem(token, reader);
                            break;
                        }

                        default:
                            value = this.Deserialize(modelKey, value, reader);
                            break;
                        }
                    }
                    else
                    {
                        ProtoTypeCode protoTypeCode = typecode;
                        switch (protoTypeCode)
                        {
                        case ProtoTypeCode.Boolean:
                            value = reader.ReadBoolean();
                            break;

                        case ProtoTypeCode.Char:
                            value = (char)reader.ReadUInt16();
                            break;

                        case ProtoTypeCode.SByte:
                            value = reader.ReadSByte();
                            break;

                        case ProtoTypeCode.Byte:
                            value = reader.ReadByte();
                            break;

                        case ProtoTypeCode.Int16:
                            value = reader.ReadInt16();
                            break;

                        case ProtoTypeCode.UInt16:
                            value = reader.ReadUInt16();
                            break;

                        case ProtoTypeCode.Int32:
                            value = reader.ReadInt32();
                            break;

                        case ProtoTypeCode.UInt32:
                            value = reader.ReadUInt32();
                            break;

                        case ProtoTypeCode.Int64:
                            value = reader.ReadInt64();
                            break;

                        case ProtoTypeCode.UInt64:
                            value = reader.ReadUInt64();
                            break;

                        case ProtoTypeCode.Single:
                            value = reader.ReadSingle();
                            break;

                        case ProtoTypeCode.Double:
                            value = reader.ReadDouble();
                            break;

                        case ProtoTypeCode.Decimal:
                            value = BclHelpers.ReadDecimal(reader);
                            break;

                        case ProtoTypeCode.DateTime:
                            value = BclHelpers.ReadDateTime(reader);
                            break;

                        case (ProtoTypeCode)17:
                            break;

                        case ProtoTypeCode.String:
                            value = reader.ReadString();
                            break;

                        default:
                            switch (protoTypeCode)
                            {
                            case ProtoTypeCode.TimeSpan:
                                value = BclHelpers.ReadTimeSpan(reader);
                                break;

                            case ProtoTypeCode.ByteArray:
                                value = ProtoReader.AppendBytes((byte[])value, reader);
                                break;

                            case ProtoTypeCode.Guid:
                                value = BclHelpers.ReadGuid(reader);
                                break;

                            case ProtoTypeCode.Uri:
                                value = new Uri(reader.ReadString());
                                break;
                            }
                            break;
                        }
                    }
                }
            }
            if (!found && !asListItem && autoCreate && type != typeof(string))
            {
                value = Activator.CreateInstance(type);
            }
            return(found);
        }
示例#3
0
        private object DeserializeWithLengthPrefix(Stream source, object value, Type type, PrefixStyle style, int expectedField, Serializer.TypeResolver resolver, out int bytesRead, out bool haveObject, SerializationContext context)
        {
            haveObject = false;
            bytesRead  = 0;
            if (type == null && (style != PrefixStyle.Base128 || resolver == null))
            {
                throw new InvalidOperationException("A type must be provided unless base-128 prefixing is being used in combination with a resolver");
            }
            while (true)
            {
                bool expectPrefix = expectedField > 0 || resolver != null;
                int  actualField;
                int  tmpBytesRead;
                int  len = ProtoReader.ReadLengthPrefix(source, expectPrefix, style, out actualField, out tmpBytesRead);
                if (tmpBytesRead == 0)
                {
                    break;
                }
                bytesRead += tmpBytesRead;
                if (len < 0)
                {
                    return(value);
                }
                bool skip;
                if (style == PrefixStyle.Base128)
                {
                    if (expectPrefix && expectedField == 0 && type == null && resolver != null)
                    {
                        type = resolver(actualField);
                        skip = (type == null);
                    }
                    else
                    {
                        skip = (expectedField != actualField);
                    }
                }
                else
                {
                    skip = false;
                }
                if (skip)
                {
                    if (len == 2147483647)
                    {
                        goto Block_12;
                    }
                    ProtoReader.Seek(source, len, null);
                    bytesRead += len;
                }
                if (!skip)
                {
                    goto Block_13;
                }
            }
            return(value);

Block_12:
            throw new InvalidOperationException();
Block_13:
            ProtoReader reader = null;
            object result;

            try
            {
                int len;
                reader = ProtoReader.Create(source, this, context, len);
                int key = this.GetKey(ref type);
                if (key >= 0 && !Helpers.IsEnum(type))
                {
                    value = this.Deserialize(key, value, reader);
                }
                else
                {
                    if (!this.TryDeserializeAuxiliaryType(reader, DataFormat.Default, 1, type, ref value, true, false, true, false) && len != 0)
                    {
                        TypeModel.ThrowUnexpectedType(type);
                    }
                }
                bytesRead += reader.Position;
                haveObject = true;
                result     = value;
            }
            finally
            {
                ProtoReader.Recycle(reader);
            }
            return(result);
        }
示例#4
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 = this.GetWireType(typecode, format, ref type, out modelKey);

            if (modelKey >= 0)
            {
                if (Helpers.IsEnum(type))
                {
                    this.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);
                    this.Serialize(modelKey, value, writer);
                    ProtoWriter.EndSubItem(token, writer);
                    return(true);
                }
                }
                this.Serialize(modelKey, value, writer);
                return(true);
            }
            else
            {
                if (wireType != WireType.None)
                {
                    ProtoWriter.WriteFieldHeader(tag, wireType, writer);
                }
                ProtoTypeCode protoTypeCode = typecode;
                switch (protoTypeCode)
                {
                case ProtoTypeCode.Boolean:
                    ProtoWriter.WriteBoolean((bool)value, writer);
                    return(true);

                case ProtoTypeCode.Char:
                    ProtoWriter.WriteUInt16((ushort)((char)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.Int16:
                    ProtoWriter.WriteInt16((short)value, writer);
                    return(true);

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

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

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

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

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

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

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

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

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

                case (ProtoTypeCode)17:
                    break;

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

                default:
                    switch (protoTypeCode)
                    {
                    case ProtoTypeCode.TimeSpan:
                        BclHelpers.WriteTimeSpan((TimeSpan)value, writer);
                        return(true);

                    case ProtoTypeCode.ByteArray:
                        ProtoWriter.WriteBytes((byte[])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);
                    }
                    break;
                }
                IEnumerable sequence = value as IEnumerable;
                if (sequence == null)
                {
                    return(false);
                }
                if (isInsideList)
                {
                    throw TypeModel.CreateNestedListsNotSupported();
                }
                foreach (object item in sequence)
                {
                    if (item == null)
                    {
                        throw new NullReferenceException();
                    }
                    if (!this.TrySerializeAuxiliaryType(writer, null, format, tag, item, true))
                    {
                        TypeModel.ThrowUnexpectedType(item.GetType());
                    }
                }
                return(true);
            }
        }
示例#5
0
        public object DeepClone(object value)
        {
            if (value == null)
            {
                return(null);
            }
            Type   type = value.GetType();
            int    key  = this.GetKey(ref type);
            object result;

            if (key >= 0 && !Helpers.IsEnum(type))
            {
                using (MemoryStream ms = new MemoryStream())
                {
                    using (ProtoWriter writer = new ProtoWriter(ms, this, null))
                    {
                        writer.SetRootObject(value);
                        this.Serialize(key, value, writer);
                        writer.Close();
                    }
                    ms.Position = 0L;
                    ProtoReader reader = null;
                    try
                    {
                        reader = ProtoReader.Create(ms, this, null, -1);
                        result = this.Deserialize(key, null, reader);
                        return(result);
                    }
                    finally
                    {
                        ProtoReader.Recycle(reader);
                    }
                }
            }
            if (type == typeof(byte[]))
            {
                byte[] orig  = (byte[])value;
                byte[] clone = new byte[orig.Length];
                Helpers.BlockCopy(orig, 0, clone, 0, orig.Length);
                return(clone);
            }
            int modelKey;

            if (this.GetWireType(Helpers.GetTypeCode(type), DataFormat.Default, ref type, out modelKey) != WireType.None && modelKey < 0)
            {
                return(value);
            }
            using (MemoryStream ms2 = new MemoryStream())
            {
                using (ProtoWriter writer2 = new ProtoWriter(ms2, this, null))
                {
                    if (!this.TrySerializeAuxiliaryType(writer2, type, DataFormat.Default, 1, value, false))
                    {
                        TypeModel.ThrowUnexpectedType(type);
                    }
                    writer2.Close();
                }
                ms2.Position = 0L;
                ProtoReader reader2 = null;
                try
                {
                    reader2 = ProtoReader.Create(ms2, this, null, -1);
                    value   = null;
                    this.TryDeserializeAuxiliaryType(reader2, DataFormat.Default, 1, type, ref value, true, false, true, false);
                    result = value;
                }
                finally
                {
                    ProtoReader.Recycle(reader2);
                }
            }
            return(result);
        }
示例#6
0
        internal int FindOrAddAuto(Type type, bool demand, bool addWithContractOnly, bool addEvenIfAutoDisabled)
        {
            int key = this.types.IndexOf(RuntimeTypeModel.MetaTypeFinder, type);

            if (key >= 0)
            {
                MetaType metaType = (MetaType)this.types[key];
                if (metaType.Pending)
                {
                    this.WaitOnLock(metaType);
                }
                return(key);
            }
            bool shouldAdd = this.AutoAddMissingTypes || addEvenIfAutoDisabled;

            if (Helpers.IsEnum(type) || this.TryGetBasicTypeSerializer(type) == null)
            {
                Type underlyingType = TypeModel.ResolveProxies(type);
                if (underlyingType != null)
                {
                    key  = this.types.IndexOf(RuntimeTypeModel.MetaTypeFinder, underlyingType);
                    type = underlyingType;
                }
                if (key < 0)
                {
                    int opaqueToken = 0;
                    try
                    {
                        this.TakeLock(ref opaqueToken);
                        MetaType metaType;
                        if ((metaType = this.RecogniseCommonTypes(type)) == null)
                        {
                            MetaType.AttributeFamily family = MetaType.GetContractFamily(this, type, null);
                            if (family == MetaType.AttributeFamily.AutoTuple)
                            {
                                addEvenIfAutoDisabled = (shouldAdd = true);
                            }
                            if (!shouldAdd || (!Helpers.IsEnum(type) && addWithContractOnly && family == MetaType.AttributeFamily.None))
                            {
                                if (demand)
                                {
                                    TypeModel.ThrowUnexpectedType(type);
                                }
                                return(key);
                            }
                            metaType = this.Create(type);
                        }
                        metaType.Pending = true;
                        bool weAdded = false;
                        int  winner  = this.types.IndexOf(RuntimeTypeModel.MetaTypeFinder, type);
                        if (winner < 0)
                        {
                            this.ThrowIfFrozen();
                            key     = this.types.Add(metaType);
                            weAdded = true;
                        }
                        else
                        {
                            key = winner;
                        }
                        if (weAdded)
                        {
                            metaType.ApplyDefaultBehaviour();
                            metaType.Pending = false;
                        }
                    }
                    finally
                    {
                        this.ReleaseLock(opaqueToken);
                    }
                    return(key);
                }
                return(key);
            }
            if (shouldAdd && !addWithContractOnly)
            {
                throw MetaType.InbuiltType(type);
            }
            return(-1);
        }