IProtoSerializerWithWireType DecorateValueSerializer(Type type, BinaryDataFormat?dynamicTypeDataFormat, ref ValueFormat format, IProtoSerializerWithWireType ser) { // Uri decorator is applied after default value // because default value for Uri is treated as string if (ser.ExpectedType == _model.MapType(typeof(string)) && type == _model.MapType(typeof(Uri))) { ser = new UriDecorator(_model, ser); } #if PORTABLE else if (ser.ExpectedType == _model.MapType(typeof(string)) && type.FullName == typeof(Uri).FullName) { // In PCLs, the Uri type may not match (WinRT uses Internal/Uri, .Net uses System/Uri) ser = new ReflectedUriDecorator(type, _model, ser); } #endif if (dynamicTypeDataFormat != null) { ser = new NetObjectValueDecorator(type, format == ValueFormat.Reference || format == ValueFormat.LateReference, dynamicTypeDataFormat.Value, !_model.ProtoCompatibility.SuppressNullWireType, _model); } else if (MetaType.IsNetObjectValueDecoratorNecessary(_model, format)) { ser = new NetObjectValueDecorator( ser, Helpers.GetNullableUnderlyingType(type) != null, format == ValueFormat.Reference || format == ValueFormat.LateReference, format == ValueFormat.LateReference && CanTypeBeAsLateReferenceOnBuildStage(_model.GetKey(type, false, true), _model), !_model.ProtoCompatibility.SuppressNullWireType, _model); } else { format = ValueFormat.Compact; } return(ser); }
private IProtoSerializer BuildSerializer() { int opaqueToken = 0; try { model.TakeLock(ref opaqueToken);// check nobody is still adding this type WireType wireType; Type finalType = itemType == null ? memberType : itemType; IProtoSerializer ser = TryGetCoreSerializer(model, dataFormat, finalType, out wireType, asReference, dynamicType, OverwriteList, true); if (ser == null) { throw new InvalidOperationException("No serializer defined for type: " + finalType.FullName); } // apply tags if (itemType != null && SupportNull) { if (IsPacked) { throw new NotSupportedException("Packed encodings cannot support null values"); } ser = new TagDecorator(NullDecorator.Tag, wireType, IsStrict, ser); ser = new NullDecorator(model, ser); ser = new TagDecorator(fieldNumber, WireType.StartGroup, false, ser); } else { ser = new TagDecorator(fieldNumber, wireType, IsStrict, ser); } // apply lists if appropriate if (itemType != null) { #if NO_GENERICS Type underlyingItemType = itemType; #else Type underlyingItemType = SupportNull ? itemType : Helpers.GetUnderlyingType(itemType) ?? itemType; #endif Helpers.DebugAssert(underlyingItemType == ser.ExpectedType || (ser.ExpectedType == model.MapType(typeof(object)) && !Helpers.IsValueType(underlyingItemType)) , "Wrong type in the tail; expected {0}, received {1}", ser.ExpectedType, underlyingItemType); if (memberType.IsArray) { ser = new ArrayDecorator(model, ser, fieldNumber, IsPacked, wireType, memberType, OverwriteList, SupportNull); } else { ser = ListDecorator.Create(model, memberType, defaultType, ser, fieldNumber, IsPacked, wireType, member != null && PropertyDecorator.CanWrite(model, member), OverwriteList, SupportNull); } } else if (defaultValue != null && !IsRequired && getSpecified == null) { // note: "ShouldSerialize*" / "*Specified" / etc ^^^^ take precedence over defaultValue, // as does "IsRequired" ser = new DefaultValueDecorator(model, defaultValue, ser); } if (memberType == model.MapType(typeof(Uri))) { ser = new UriDecorator(model, ser); } #if PORTABLE else if (memberType.FullName == typeof(Uri).FullName) { // In PCLs, the Uri type may not match (WinRT uses Internal/Uri, .Net uses System/Uri) ser = new ReflectedUriDecorator(memberType, model, ser); } #endif if (member != null) { PropertyInfo prop = member as PropertyInfo; if (prop != null) { ser = new PropertyDecorator(model, parentType, (PropertyInfo)member, ser); } else { FieldInfo fld = member as FieldInfo; if (fld != null) { ser = new FieldDecorator(parentType, (FieldInfo)member, ser); } else { throw new InvalidOperationException(); } } if (getSpecified != null || setSpecified != null) { ser = new MemberSpecifiedDecorator(getSpecified, setSpecified, ser); } } return(ser); } finally { model.ReleaseLock(opaqueToken); } }
private IProtoSerializer BuildSerializer() { int opaqueToken = 0; try { model.TakeLock(ref opaqueToken);// check nobody is still adding this type var member = backingMember ?? originalMember; IProtoSerializer ser; if (IsMap) { ResolveMapTypes(out var dictionaryType, out var keyType, out var valueType); if (dictionaryType == null) { throw new InvalidOperationException("Unable to resolve map type for type: " + memberType.FullName); } var concreteType = defaultType; if (concreteType == null && Helpers.IsClass(memberType)) { concreteType = memberType; } var keySer = TryGetCoreSerializer(model, MapKeyFormat, keyType, out var keyWireType, false, false, false, false); if (!AsReference) { AsReference = MetaType.GetAsReferenceDefault(model, valueType); } var valueSer = TryGetCoreSerializer(model, MapValueFormat, valueType, out var valueWireType, AsReference, DynamicType, false, true); #if PROFILE259 IEnumerable <ConstructorInfo> ctors = typeof(MapDecorator <, ,>).MakeGenericType(new Type[] { dictionaryType, keyType, valueType }).GetTypeInfo().DeclaredConstructors; if (ctors.Count() != 1) { throw new InvalidOperationException("Unable to resolve MapDecorator constructor"); } ser = (IProtoSerializer)ctors.First().Invoke(new object[] { model, concreteType, keySer, valueSer, fieldNumber, DataFormat == DataFormat.Group ? WireType.StartGroup : WireType.String, keyWireType, valueWireType, OverwriteList }); #else var ctors = typeof(MapDecorator <, ,>).MakeGenericType(new Type[] { dictionaryType, keyType, valueType }).GetConstructors( BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance); if (ctors.Length != 1) { throw new InvalidOperationException("Unable to resolve MapDecorator constructor"); } ser = (IProtoSerializer)ctors[0].Invoke(new object[] { model, concreteType, keySer, valueSer, fieldNumber, DataFormat == DataFormat.Group ? WireType.StartGroup : WireType.String, keyWireType, valueWireType, OverwriteList }); #endif } else { WireType wireType; Type finalType = itemType == null ? memberType : itemType; ser = TryGetCoreSerializer(model, dataFormat, finalType, out wireType, AsReference, DynamicType, OverwriteList, true); if (ser == null) { throw new InvalidOperationException("No serializer defined for type: " + finalType.FullName); } // apply tags if (itemType != null && SupportNull) { if (IsPacked) { throw new NotSupportedException("Packed encodings cannot support null values"); } ser = new TagDecorator(NullDecorator.Tag, wireType, IsStrict, ser); ser = new NullDecorator(model, ser); ser = new TagDecorator(fieldNumber, WireType.StartGroup, false, ser); } else { ser = new TagDecorator(fieldNumber, wireType, IsStrict, ser); } // apply lists if appropriate if (itemType != null) { Type underlyingItemType = SupportNull ? itemType : Helpers.GetUnderlyingType(itemType) ?? itemType; Helpers.DebugAssert(underlyingItemType == ser.ExpectedType || (ser.ExpectedType == model.MapType(typeof(object)) && !Helpers.IsValueType(underlyingItemType)) , "Wrong type in the tail; expected {0}, received {1}", ser.ExpectedType, underlyingItemType); if (memberType.IsArray) { ser = new ArrayDecorator(model, ser, fieldNumber, IsPacked, wireType, memberType, OverwriteList, SupportNull); } else { ser = ListDecorator.Create(model, memberType, defaultType, ser, fieldNumber, IsPacked, wireType, member != null && PropertyDecorator.CanWrite(model, member), OverwriteList, SupportNull); } } else if (defaultValue != null && !IsRequired && getSpecified == null) { // note: "ShouldSerialize*" / "*Specified" / etc ^^^^ take precedence over defaultValue, // as does "IsRequired" ser = new DefaultValueDecorator(model, defaultValue, ser); } if (memberType == model.MapType(typeof(Uri))) { ser = new UriDecorator(model, ser); } #if PORTABLE else if (memberType.FullName == typeof(Uri).FullName) { // In PCLs, the Uri type may not match (WinRT uses Internal/Uri, .Net uses System/Uri) ser = new ReflectedUriDecorator(memberType, model, ser); } #endif } if (member != null) { if (member is PropertyInfo prop) { ser = new PropertyDecorator(model, parentType, prop, ser); } else if (member is FieldInfo fld) { ser = new FieldDecorator(parentType, fld, ser); } else { throw new InvalidOperationException(); } if (getSpecified != null || setSpecified != null) { ser = new MemberSpecifiedDecorator(getSpecified, setSpecified, ser); } } return(ser); } finally { model.ReleaseLock(opaqueToken); } }