Beispiel #1
0
        private bool CanSerialize(Type type, bool allowBasic, bool allowContract, bool allowLists)
        {
            if (type == null)
            {
                throw new ArgumentNullException("type");
            }
            Type tmp = Helpers.GetUnderlyingType(type);

            if (tmp != null)
            {
                type = tmp;
            }
            switch (Helpers.GetTypeCode(type))
            {
            case ProtoTypeCode.Empty:
            case ProtoTypeCode.Unknown:
            {
                int modelKey = this.GetKey(ref type);
                if (modelKey >= 0)
                {
                    return(allowContract);
                }
                if (allowLists)
                {
                    Type itemType = null;
                    if (type.IsArray)
                    {
                        if (type.GetArrayRank() == 1)
                        {
                            itemType = type.GetElementType();
                        }
                    }
                    else
                    {
                        itemType = TypeModel.GetListItemType(this, type);
                    }
                    if (itemType != null)
                    {
                        return(this.CanSerialize(itemType, allowBasic, allowContract, false));
                    }
                }
                return(false);
            }

            default:
                return(allowBasic);
            }
        }
Beispiel #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);
        }
Beispiel #3
0
        public MetaType Add(Type type, bool applyDefaultBehaviour)
        {
            if (type == null)
            {
                throw new ArgumentNullException("type");
            }
            MetaType newType = this.FindWithoutAdd(type);

            if (newType != null)
            {
                return(newType);
            }
            int opaqueToken = 0;

            if (type.IsInterface && base.MapType(MetaType.ienumerable).IsAssignableFrom(type) && TypeModel.GetListItemType(this, type) == null)
            {
                throw new ArgumentException("IEnumerable[<T>] data cannot be used as a meta-type unless an Add method can be resolved");
            }
            try
            {
                newType = this.RecogniseCommonTypes(type);
                if (newType != null)
                {
                    if (!applyDefaultBehaviour)
                    {
                        throw new ArgumentException("Default behaviour must be observed for certain types with special handling; " + type.FullName, "applyDefaultBehaviour");
                    }
                    applyDefaultBehaviour = false;
                }
                if (newType == null)
                {
                    newType = this.Create(type);
                }
                newType.Pending = true;
                this.TakeLock(ref opaqueToken);
                if (this.FindWithoutAdd(type) != null)
                {
                    throw new ArgumentException("Duplicate type", "type");
                }
                this.ThrowIfFrozen();
                this.types.Add(newType);
                if (applyDefaultBehaviour)
                {
                    newType.ApplyDefaultBehaviour();
                }
                newType.Pending = false;
            }
            finally
            {
                this.ReleaseLock(opaqueToken);
            }
            return(newType);
        }
Beispiel #4
0
 internal void ResolveListTypes(Type type, ref Type itemType, ref Type defaultType)
 {
     if (type == null)
     {
         return;
     }
     if (Helpers.GetTypeCode(type) != ProtoTypeCode.Unknown)
     {
         return;
     }
     if (this[type].IgnoreListHandling)
     {
         return;
     }
     if (type.IsArray)
     {
         if (type.GetArrayRank() != 1)
         {
             throw new NotSupportedException("Multi-dimension arrays are supported");
         }
         itemType = type.GetElementType();
         if (itemType == base.MapType(typeof(byte)))
         {
             Type type2;
             itemType    = (type2 = null);
             defaultType = type2;
         }
         else
         {
             defaultType = type;
         }
     }
     if (itemType == null)
     {
         itemType = TypeModel.GetListItemType(this, type);
     }
     if (itemType != null)
     {
         Type nestedItemType    = null;
         Type nestedDefaultType = null;
         this.ResolveListTypes(itemType, ref nestedItemType, ref nestedDefaultType);
         if (nestedItemType != null)
         {
             throw TypeModel.CreateNestedListsNotSupported();
         }
     }
     if (itemType != null && defaultType == null)
     {
         if (type.IsClass && !type.IsAbstract && Helpers.GetConstructor(type, Helpers.EmptyTypes, true) != null)
         {
             defaultType = type;
         }
         if (defaultType == null && type.IsInterface)
         {
             Type[] genArgs;
             if (type.IsGenericType && type.GetGenericTypeDefinition() == base.MapType(typeof(IDictionary <,>)) && itemType == base.MapType(typeof(KeyValuePair <,>)).MakeGenericType(genArgs = type.GetGenericArguments()))
             {
                 defaultType = base.MapType(typeof(Dictionary <,>)).MakeGenericType(genArgs);
             }
             else
             {
                 defaultType = base.MapType(typeof(List <>)).MakeGenericType(new Type[]
                 {
                     itemType
                 });
             }
         }
         if (defaultType != null && !Helpers.IsAssignableFrom(type, defaultType))
         {
             defaultType = null;
         }
     }
 }
Beispiel #5
0
 private void CascadeDependents(BasicList list, MetaType metaType)
 {
     if (metaType.IsList)
     {
         Type     itemType = TypeModel.GetListItemType(this, metaType.Type);
         WireType defaultWireType;
         if (ValueMember.TryGetCoreSerializer(this, DataFormat.Default, itemType, out defaultWireType, false, false, false, false) == null)
         {
             int index = this.FindOrAddAuto(itemType, false, false, false);
             if (index >= 0)
             {
                 MetaType tmp = ((MetaType)this.types[index]).GetSurrogateOrBaseOrSelf(false);
                 if (!list.Contains(tmp))
                 {
                     list.Add(tmp);
                     this.CascadeDependents(list, tmp);
                     return;
                 }
             }
         }
     }
     else
     {
         MetaType tmp;
         if (metaType.IsAutoTuple)
         {
             MemberInfo[] mapping;
             if (MetaType.ResolveTupleConstructor(metaType.Type, out mapping) != null)
             {
                 for (int i = 0; i < mapping.Length; i++)
                 {
                     Type type = null;
                     if (mapping[i] is PropertyInfo)
                     {
                         type = ((PropertyInfo)mapping[i]).PropertyType;
                     }
                     else
                     {
                         if (mapping[i] is FieldInfo)
                         {
                             type = ((FieldInfo)mapping[i]).FieldType;
                         }
                     }
                     WireType defaultWireType2;
                     if (ValueMember.TryGetCoreSerializer(this, DataFormat.Default, type, out defaultWireType2, false, false, false, false) == null)
                     {
                         int index2 = this.FindOrAddAuto(type, false, false, false);
                         if (index2 >= 0)
                         {
                             tmp = ((MetaType)this.types[index2]).GetSurrogateOrBaseOrSelf(false);
                             if (!list.Contains(tmp))
                             {
                                 list.Add(tmp);
                                 this.CascadeDependents(list, tmp);
                             }
                         }
                     }
                 }
             }
         }
         else
         {
             foreach (ValueMember member in metaType.Fields)
             {
                 Type type2 = member.ItemType;
                 if (type2 == null)
                 {
                     type2 = member.MemberType;
                 }
                 WireType defaultWireType3;
                 if (ValueMember.TryGetCoreSerializer(this, DataFormat.Default, type2, out defaultWireType3, false, false, false, false) == null)
                 {
                     int index3 = this.FindOrAddAuto(type2, false, false, false);
                     if (index3 >= 0)
                     {
                         tmp = ((MetaType)this.types[index3]).GetSurrogateOrBaseOrSelf(false);
                         if (!list.Contains(tmp))
                         {
                             list.Add(tmp);
                             this.CascadeDependents(list, tmp);
                         }
                     }
                 }
             }
         }
         if (metaType.HasSubtypes)
         {
             SubType[] subtypes = metaType.GetSubtypes();
             for (int j = 0; j < subtypes.Length; j++)
             {
                 SubType subType = subtypes[j];
                 tmp = subType.DerivedType.GetSurrogateOrSelf();
                 if (!list.Contains(tmp))
                 {
                     list.Add(tmp);
                     this.CascadeDependents(list, tmp);
                 }
             }
         }
         tmp = metaType.BaseType;
         if (tmp != null)
         {
             tmp = tmp.GetSurrogateOrSelf();
         }
         if (tmp != null && !list.Contains(tmp))
         {
             list.Add(tmp);
             this.CascadeDependents(list, tmp);
         }
     }
 }