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); } }
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); }
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); }
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; } } }
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); } } }