public bool CanPack(Type type, BinaryDataFormat?contentBinaryFormatHint) { return(type != _model.MapType(typeof(string)) && !CanTypeBeNull(type) && !RuntimeTypeModel.CheckTypeIsCollection(_model, type) && ListDecorator.CanPack(HelpersInternal.GetWireType(HelpersInternal.GetTypeCode(type), contentBinaryFormatHint.GetValueOrDefault()))); }
private IEnumerable <IRenderable> GenerateHtmlElements(int min, int max) { yield return(new BeginList(_ulClass)); // Previous yield return(new ListDecorator( new LinkDecorator( new ContentItem(_resource.Previous), _currentPage > 1 ? _urlBuilder(_currentPage - 1) : "#"))); // 1 if (min >= 2) { yield return(new ListDecorator( new LinkDecorator( new ContentItem("1"), _urlBuilder(1)))); } // ... var dots = new ListDecorator( new SpanDecorator( new ContentItem(_resource.Separator)), _liDisabledClass); if (min >= 3) { yield return(dots); } // 4 5 [6] 7 9 foreach (var x in Enumerable.Range(min, max - min + 1).ToList()) { yield return (new ListDecorator( new LinkDecorator( new ContentItem(x.ToString(CultureInfo.InvariantCulture)), _urlBuilder(x)), x == _currentPage ? _currentPageClass : string.Empty)); } // ... if (max + 1 < _total) { yield return(dots); } // 999 if (max < _total) { yield return(new ListDecorator( new LinkDecorator( new ContentItem(_total.ToString(CultureInfo.InvariantCulture)), _urlBuilder(_total)))); } // Next yield return(new ListDecorator( new LinkDecorator( new ContentItem(_resource.Next), _currentPage < _total ? _urlBuilder(_currentPage + 1) : "#"))); yield return(new EndList()); }
public void Insert() { var decorator = new ListDecorator<int>() { 1, 2, 3 }; decorator.Insert(1, 5); Assert.Equal(5, decorator[1]); }
public void Clear() { var decorator = new ListDecorator<int> { 1, 2, 3 }; decorator.Clear(); Assert.True(decorator.Empty()); }
public void RemoveAt() { var decorator = new ListDecorator<int> { 1, 2, 3 }; decorator.RemoveAt(1); Assert.Equal(2, decorator.Count); }
public void Remove() { var decorator = new ListDecorator<int> { 1, 2, 3 }; decorator.Remove(1); Assert.Equal(2, decorator.Count); }
public void CopyTo() { var decorator = new ListDecorator<int> { 1, 2, 3 }; int[] array = new int[3]; decorator.CopyTo(array, 0); Assert.True(decorator.SequenceEqual(array)); }
private IProtoSerializer BuildSerializer() { WireType wireType; IProtoSerializer ser = GetCoreSerializer(itemType ?? memberType, out wireType); // apply tags ser = new TagDecorator(fieldNumber, wireType, isStrict, ser); // apply lists if appropriate if (itemType != null) { Helpers.DebugAssert(itemType == ser.ExpectedType, "Wrong type in the tail"); if (memberType.IsArray) { ser = new ArrayDecorator(ser, isPacked ? fieldNumber : 0, isPacked ? wireType : WireType.None); } else { ser = new ListDecorator(memberType, defaultType, ser, isPacked ? fieldNumber : 0, isPacked ? wireType : WireType.None); } } else if (defaultValue != null && !isRequired) { ser = new DefaultValueDecorator(defaultValue, ser); } if (memberType == typeof(Uri)) { ser = new UriDecorator(ser); } switch (member.MemberType) { case MemberTypes.Property: ser = new PropertyDecorator(parentType, (PropertyInfo)member, ser); break; case MemberTypes.Field: ser = new FieldDecorator(parentType, (FieldInfo)member, ser); break; default: throw new InvalidOperationException(); } if (getSpecified != null || setSpecified != null) { ser = new MemberSpecifiedDecorator(getSpecified, setSpecified, ser); } return(ser); }
public void IsReadOnly() { var decorator = new ListDecorator<int> { 1, 2, 3 }; Assert.False(decorator.IsReadOnly); }
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); 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(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 : Nullable.GetUnderlyingType(itemType) ?? itemType; #endif Helpers.DebugAssert(underlyingItemType == ser.ExpectedType, "Wrong type in the tail; expected {0}, received {1}", ser.ExpectedType, underlyingItemType); if (memberType.IsArray) { ser = new ArrayDecorator(ser, fieldNumber, IsPacked, wireType, memberType, OverwriteList, SupportNull); } else { ser = new ListDecorator(memberType, defaultType, ser, fieldNumber, IsPacked, wireType, member == null || PropertyDecorator.CanWrite(member), OverwriteList, SupportNull); } } else if (defaultValue != null && !IsRequired) { ser = new DefaultValueDecorator(defaultValue, ser); } if (memberType == typeof(Uri)) { ser = new UriDecorator(ser); } if (member != null) { switch (member.MemberType) { case MemberTypes.Property: ser = new PropertyDecorator(parentType, (PropertyInfo)member, ser); break; case MemberTypes.Field: ser = new FieldDecorator(parentType, (FieldInfo)member, ser); break; default: throw new InvalidOperationException(); } if (getSpecified != null || setSpecified != null) { ser = new MemberSpecifiedDecorator(getSpecified, setSpecified, ser); } } return(ser); } finally { model.ReleaseLock(opaqueToken); } }
public void Contains() { var decorator = new ListDecorator<int> { 1, 2, 3 }; Assert.True(decorator.Contains(2)); }
// Token: 0x0600040A RID: 1034 RVA: 0x00015168 File Offset: 0x00013368 private IProtoSerializer BuildSerializer() { int opaqueToken = 0; IProtoSerializer result; try { this.model.TakeLock(ref opaqueToken); Type type = (this.itemType == null) ? this.memberType : this.itemType; WireType wireType; IProtoSerializer protoSerializer = ValueMember.TryGetCoreSerializer(this.model, this.dataFormat, type, out wireType, this.asReference, this.dynamicType, this.OverwriteList, true); if (protoSerializer == null) { throw new InvalidOperationException("No serializer defined for type: " + type.FullName); } if (this.itemType != null && this.SupportNull) { if (this.IsPacked) { throw new NotSupportedException("Packed encodings cannot support null values"); } protoSerializer = new TagDecorator(1, wireType, this.IsStrict, protoSerializer); protoSerializer = new NullDecorator(this.model, protoSerializer); protoSerializer = new TagDecorator(this.fieldNumber, WireType.StartGroup, false, protoSerializer); } else { protoSerializer = new TagDecorator(this.fieldNumber, wireType, this.IsStrict, protoSerializer); } if (this.itemType != null) { if (!this.SupportNull) { if (Helpers.GetUnderlyingType(this.itemType) == null) { Type type2 = this.itemType; } } else { Type type3 = this.itemType; } if (this.memberType.IsArray) { protoSerializer = new ArrayDecorator(this.model, protoSerializer, this.fieldNumber, this.IsPacked, wireType, this.memberType, this.OverwriteList, this.SupportNull); } else { protoSerializer = ListDecorator.Create(this.model, this.memberType, this.defaultType, protoSerializer, this.fieldNumber, this.IsPacked, wireType, this.member != null && PropertyDecorator.CanWrite(this.model, this.member), this.OverwriteList, this.SupportNull); } } else if (this.defaultValue != null && !this.IsRequired && this.getSpecified == null) { protoSerializer = new DefaultValueDecorator(this.model, this.defaultValue, protoSerializer); } if (this.memberType == this.model.MapType(typeof(Uri))) { protoSerializer = new UriDecorator(this.model, protoSerializer); } if (this.member != null) { if (this.member is PropertyInfo) { protoSerializer = new PropertyDecorator(this.model, this.parentType, (PropertyInfo)this.member, protoSerializer); } else { if (!(this.member is FieldInfo)) { throw new InvalidOperationException(); } protoSerializer = new FieldDecorator(this.parentType, (FieldInfo)this.member, protoSerializer); } if (this.getSpecified != null || this.setSpecified != null) { protoSerializer = new MemberSpecifiedDecorator(this.getSpecified, this.setSpecified, protoSerializer); } } result = protoSerializer; } finally { this.model.ReleaseLock(opaqueToken); } return(result); }
private IProtoSerializer BuildSerializer() { IProtoSerializer serializer2; int opaqueToken = 0; try { WireType type; this.model.TakeLock(ref opaqueToken); Type type2 = (this.itemType == null) ? this.memberType : this.itemType; IProtoSerializer tail = TryGetCoreSerializer(this.model, this.dataFormat, type2, out type, this.asReference, this.dynamicType, this.OverwriteList, true); if (tail == null) { throw new InvalidOperationException("No serializer defined for type: " + type2.FullName); } if ((this.itemType != null) && this.SupportNull) { if (this.IsPacked) { throw new NotSupportedException("Packed encodings cannot support null values"); } tail = new TagDecorator(1, type, this.IsStrict, tail); tail = new NullDecorator(this.model, tail); tail = new TagDecorator(this.fieldNumber, WireType.StartGroup, false, tail); } else { tail = new TagDecorator(this.fieldNumber, type, this.IsStrict, tail); } if (this.itemType != null) { if (!this.SupportNull) { Helpers.GetUnderlyingType(this.itemType); } if (this.memberType.IsArray) { tail = new ArrayDecorator(this.model, tail, this.fieldNumber, this.IsPacked, type, this.memberType, this.OverwriteList, this.SupportNull); } else { tail = new ListDecorator(this.model, this.memberType, this.defaultType, tail, this.fieldNumber, this.IsPacked, type, (this.member != null) && PropertyDecorator.CanWrite(this.model, this.member), this.OverwriteList, this.SupportNull); } } else if (((this.defaultValue != null) && !this.IsRequired) && (this.getSpecified == null)) { tail = new DefaultValueDecorator(this.model, this.defaultValue, tail); } if (this.memberType == this.model.MapType(typeof(Uri))) { tail = new UriDecorator(this.model, tail); } if (this.member != null) { PropertyInfo member = this.member as PropertyInfo; if (member != null) { tail = new PropertyDecorator(this.model, this.parentType, (PropertyInfo)this.member, tail); } else { FieldInfo info2 = this.member as FieldInfo; if (info2 == null) { throw new InvalidOperationException(); } tail = new FieldDecorator(this.parentType, (FieldInfo)this.member, tail); } if ((this.getSpecified != null) || (this.setSpecified != null)) { tail = new MemberSpecifiedDecorator(this.getSpecified, this.setSpecified, tail); } } serializer2 = tail; } finally { this.model.ReleaseLock(opaqueToken); } return(serializer2); }
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); } }
public void IndexOf() { var decorator = new ListDecorator<int>() { 1, 2, 3 }; Assert.Equal(2, decorator.IndexOf(3)); }
IProtoSerializerWithWireType BuildValueFinalSerializer(ValueSerializationSettings settings, bool isMemberOrNested, out WireType wireType, int levelNumber) { object defaultValue; var l = CompleteLevel(settings, levelNumber, out defaultValue).Basic; // to ensure that model can be copied and used again for (int i = 1; i <= 3; i++) { var l2 = CompleteLevel(settings, levelNumber, out defaultValue); Debug.Assert(l.Equals(l2.Basic)); } Debug.Assert(l.ContentBinaryFormatHint != null, "l.ContentBinaryFormatHint != null"); Debug.Assert(l.WriteAsDynamicType != null, "l.WriteAsDynamicType != null"); Debug.Assert(l.Collection.Append != null, "l.Collection.Append != null"); // postpone all checks for types when adding member till BuildSerializer, resolve everything only on buildserializer! till that have only local not inherited settings. // do not allow EnumPassthru and other settings to affect anything until buildling serializer wireType = 0; Type itemType = l.Collection.ItemType ?? l.EffectiveType; bool itemTypeCanBeNull = CanTypeBeNull(itemType); bool isPacked = CanBePackedCollection(l); IProtoSerializerWithWireType ser = null; if (l.Collection.IsCollection) { Type nestedItemType = null; Type nestedDefaultType = null; int idx = _model.FindOrAddAuto(itemType, false, true, false); MetaType type = idx < 0 ? null : _model[itemType]; if (!type?.GetFinalSettingsCopy().IgnoreListHandling ?? true) { MetaType.ResolveListTypes(_model, itemType, ref nestedItemType, ref nestedDefaultType); } bool itemIsNestedCollection = nestedItemType != null; // primitive types except System.Object may be handled as nested through recursion bool tryHandleAsRegistered = !isMemberOrNested || itemType == _model.MapType(typeof(object)); if (tryHandleAsRegistered) { var nestedLevel = settings.GetSettingsCopy(levelNumber + 1); nestedLevel = PrepareNestedLevelForBuild(nestedLevel, itemType); settings.SetSettings(nestedLevel, levelNumber + 1); // should use its level settings and merge from type, ... ser = BuildValueFinalSerializer(settings, true, out wireType, levelNumber + 1); //object dummy = null; //ser = TryGetCoreSerializer(l.ContentBinaryFormatHint.Value, nestedLevel.Basic.EffectiveType, out wireType, ref nestedLevel.Basic.Format, nestedLevel.Basic.WriteAsDynamicType.GetValueOrDefault(), l.Collection.Append.Value, isPacked, true, ref dummy); //if (ser != null) // ThrowIfHasMoreLevels(settings, levelNumber + 1, l, ", no more nested type detected"); } else if (!itemIsNestedCollection) { var nestedLevel = settings.GetSettingsCopy(levelNumber + 1); nestedLevel = PrepareNestedLevelForBuild(nestedLevel, itemType); nestedLevel.Basic.Collection.ItemType = null; // IgnoreListHandling or not a collection settings.SetSettings(nestedLevel, levelNumber + 1); ser = BuildValueFinalSerializer(settings, true, out wireType, levelNumber + 1); } if (ser == null && itemIsNestedCollection) { // if we already tried to lookup registered type no need to do it again MetaType metaType; if (_model.FindOrAddAuto(itemType, false, true, false, out metaType) >= 0) { nestedDefaultType = metaType.GetFinalSettingsCopy().ConstructType ?? nestedDefaultType ?? metaType.Type; } var nestedLevel = settings.GetSettingsCopy(levelNumber + 1); if (nestedLevel.Basic.Collection.ConcreteType == null) { nestedLevel.Basic.Collection.ConcreteType = nestedDefaultType; } if (nestedLevel.IsNotAssignable) { throw new ProtoException("Nested collection item should be assignable"); } nestedLevel.Basic.Collection.Append = false; // TODO throw if set to true: throw new ProtoException("AppendCollection is not supported for nested types: " + objectType.Name); if (nestedLevel.Basic.Collection.ItemType == null) { nestedLevel.Basic.Collection.ItemType = nestedItemType; } else if (!Helpers.IsAssignableFrom(nestedItemType, nestedLevel.Basic.Collection.ItemType)) { throw new ProtoException( "Nested collection item type " + nestedLevel.Basic.Collection.ItemType + " is not assignable to " + nestedItemType + " for declared collection type " + l.EffectiveType); } nestedLevel = PrepareNestedLevelForBuild(nestedLevel, itemType); settings.SetSettings(nestedLevel, levelNumber + 1); WireType wt; ser = BuildValueFinalSerializer( settings, true, out wt, levelNumber + 1); isPacked = false; } } else { // handled outside and not wrapped with collection if (!isMemberOrNested) { l.Format = ValueFormat.Compact; } isPacked = false; // it's not even a collection ser = TryGetCoreSerializer(l.ContentBinaryFormatHint.Value, itemType, out wireType, ref l.Format, l.WriteAsDynamicType.Value, l.Collection.Append.Value, isPacked, true, ref defaultValue); if (ser != null) { ThrowIfHasMoreLevels(settings, levelNumber, l, ", no more nested type detected"); } } if (ser == null) { throw new InvalidOperationException("No serializer defined for type: " + itemType.FullName); } if (itemTypeCanBeNull && ( (Helpers.GetNullableUnderlyingType(itemType) != null && Helpers.GetNullableUnderlyingType(ser.ExpectedType) == null) // TODO get rid of ugly casting, maybe use builder pattern || (!Helpers.IsValueType(itemType) && !(ser is NetObjectValueDecorator)) )) { // nested level may be not collection and already wrapped with nonull, may later add check whether handled as registered vs as nested if (!(ser is NoNullDecorator)) { // if not wrapped with net obj - wrap with write-null check ser = new NoNullDecorator(_model, ser, l.Collection.ItemType != null); // throw only for collection elements, otherwise don't write } } if (itemType != ser.ExpectedType && (!l.WriteAsDynamicType.Value || !Helpers.IsAssignableFrom(ser.ExpectedType, itemType))) { throw new ProtoException(string.Format("Wrong type in the tail; expected {0}, received {1}", ser.ExpectedType, itemType)); } // apply lists if appropriate if (l.Collection.IsCollection) { bool protoCompatibility = l.Collection.Format == CollectionFormat.Protobuf || l.Collection.Format == CollectionFormat.ProtobufNotPacked; WireType packedReadWt; if (!protoCompatibility) { packedReadWt = WireType.None; Debug.Assert(!isPacked); // should be determinated before passing to TryGetCoreSerializer isPacked = false; } else { packedReadWt = CanPack(l.Collection.ItemType, l.ContentBinaryFormatHint) ? l.Collection.PackedWireTypeForRead.GetValueOrDefault(wireType) : WireType.None; } if (l.EffectiveType.IsArray) { if (l.EffectiveType.GetArrayRank() == 1) { ser = new ArrayDecorator( _model, ser, isPacked, packedReadWt, l.EffectiveType, !l.Collection.Append.Value, l.Collection.ArrayLengthReadLimit.Value, protoCompatibility); } else { if (protoCompatibility) { throw new NotSupportedException("Multi-dimensional arrays are supported only in Enhanced collection format"); } ser = new MultiDimensionalArrayDecorator( _model, ser, l.EffectiveType, !l.Collection.Append.Value, l.Collection.ArrayLengthReadLimit.Value); } } else { ser = ListDecorator.Create( _model, l.EffectiveType, l.Collection.ConcreteType, ser, isPacked, packedReadWt, !l.Collection.Append.Value, protoCompatibility, true); } if (isMemberOrNested) { if (MetaType.IsNetObjectValueDecoratorNecessary(_model, l.Format)) { ser = new NetObjectValueDecorator( ser, Helpers.GetNullableUnderlyingType(l.EffectiveType) != null, l.Format == ValueFormat.Reference || l.Format == ValueFormat.LateReference, l.Format == ValueFormat.LateReference && CanTypeBeAsLateReferenceOnBuildStage(_model.GetKey(l.EffectiveType, false, true), _model), !_model.ProtoCompatibility.SuppressNullWireType, _model); } else if (!Helpers.IsValueType(l.EffectiveType) || Helpers.GetNullableUnderlyingType(l.EffectiveType) != null) { ser = new NoNullDecorator(_model, ser, false); } } if (l.EffectiveType != ser.ExpectedType && (!l.WriteAsDynamicType.Value || !Helpers.IsAssignableFrom(ser.ExpectedType, itemType))) { throw new ProtoException(string.Format("Wrong type in the tail; expected {0}, received {1}", ser.ExpectedType, itemType)); } } if (levelNumber == 0 && defaultValue != null) { ser = new DefaultValueDecorator(_model, defaultValue, ser); } return(ser); }
private IProtoSerializer BuildSerializer() { bool lockTaken = false; try { model.TakeLock(ref lockTaken);// 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); if (ser == null) { throw new InvalidOperationException("No serializer defined for type: " + finalType.FullName); } // apply tags ser = new TagDecorator(fieldNumber, wireType, IsStrict, ser); // apply lists if appropriate if (itemType != null) { Helpers.DebugAssert(itemType == ser.ExpectedType, "Wrong type in the tail"); if (memberType.IsArray) { ser = new ArrayDecorator(ser, fieldNumber, IsPacked, wireType, memberType, OverwriteList); } else { ser = new ListDecorator(memberType, defaultType, ser, fieldNumber, IsPacked, wireType, member == null || PropertyDecorator.CanWrite(member), OverwriteList); } } else if (defaultValue != null && !IsRequired) { ser = new DefaultValueDecorator(defaultValue, ser); } if (memberType == typeof(Uri)) { ser = new UriDecorator(ser); } if (member != null) { switch (member.MemberType) { case MemberTypes.Property: ser = new PropertyDecorator(parentType, (PropertyInfo)member, ser); break; case MemberTypes.Field: ser = new FieldDecorator(parentType, (FieldInfo)member, ser); break; default: throw new InvalidOperationException(); } if (getSpecified != null || setSpecified != null) { ser = new MemberSpecifiedDecorator(getSpecified, setSpecified, ser); } } return(ser); } finally { model.ReleaseLock(lockTaken); } }
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); } }
private IProtoSerializer BuildSerializer() { int opaqueToken = 0; try { model.TakeLock(ref opaqueToken); Type type = (itemType == null) ? memberType : itemType; IProtoSerializer protoSerializer = TryGetCoreSerializer(model, dataFormat, type, out WireType defaultWireType, asReference, dynamicType, OverwriteList, allowComplexTypes: true); if (protoSerializer == null) { throw new InvalidOperationException("No serializer defined for type: " + type.FullName); } if (itemType != null && SupportNull) { if (IsPacked) { throw new NotSupportedException("Packed encodings cannot support null values"); } protoSerializer = new TagDecorator(1, defaultWireType, IsStrict, protoSerializer); protoSerializer = new NullDecorator(model, protoSerializer); protoSerializer = new TagDecorator(fieldNumber, WireType.StartGroup, strict: false, protoSerializer); } else { protoSerializer = new TagDecorator(fieldNumber, defaultWireType, IsStrict, protoSerializer); } if (itemType != null) { if (!SupportNull) { if (Helpers.GetUnderlyingType(itemType) == null) { _ = itemType; } } else { _ = itemType; } protoSerializer = ((!memberType.IsArray) ? ((ProtoDecoratorBase)ListDecorator.Create(model, memberType, defaultType, protoSerializer, fieldNumber, IsPacked, defaultWireType, member != null && PropertyDecorator.CanWrite(model, member), OverwriteList, SupportNull)) : ((ProtoDecoratorBase) new ArrayDecorator(model, protoSerializer, fieldNumber, IsPacked, defaultWireType, memberType, OverwriteList, SupportNull))); } else if (defaultValue != null && !IsRequired && getSpecified == null) { protoSerializer = new DefaultValueDecorator(model, defaultValue, protoSerializer); } if (memberType == model.MapType(typeof(Uri))) { protoSerializer = new UriDecorator(model, protoSerializer); } if (member != null) { if (member is PropertyInfo) { protoSerializer = new PropertyDecorator(model, parentType, (PropertyInfo)member, protoSerializer); } else { if (!(member is FieldInfo)) { throw new InvalidOperationException(); } protoSerializer = new FieldDecorator(parentType, (FieldInfo)member, protoSerializer); } if (getSpecified != null || setSpecified != null) { protoSerializer = new MemberSpecifiedDecorator(getSpecified, setSpecified, protoSerializer); } } return(protoSerializer); } finally { model.ReleaseLock(opaqueToken); } }
internal void WriteSchema(System.Text.StringBuilder builder, int indent, ref bool requiresBclImport) { Serializer.GetHashCode(); if (_surrogate != null) { return; // nothing to write } ValueMember[] fieldsArr = new ValueMember[_fields.Count]; _fields.CopyTo(fieldsArr, 0); Array.Sort(fieldsArr, ValueMember.Comparer.Default); if (IsList) { string itemTypeName = _model.GetSchemaTypeName(TypeModel.GetListItemType(_model, Type), BinaryDataFormat.Default, false, false, ref requiresBclImport); NewLine(builder, indent).Append("message ").Append(GetSchemaTypeName()).Append(" {"); NewLine(builder, indent + 1).Append("repeated ").Append(itemTypeName).Append(" items = 1;"); NewLine(builder, indent).Append('}'); } else if (_settingsValueFinal.IsAutoTuple) { // key-value-pair etc MemberInfo[] mapping; if (ResolveTupleConstructor(Type, out mapping) != null) { NewLine(builder, indent).Append("message ").Append(GetSchemaTypeName()).Append(" {"); for (int i = 0; i < mapping.Length; i++) { Type effectiveType; if (mapping[i] is PropertyInfo) { effectiveType = ((PropertyInfo)mapping[i]).PropertyType; } else if (mapping[i] is FieldInfo) { effectiveType = ((FieldInfo)mapping[i]).FieldType; } else { throw new NotSupportedException("Unknown member type: " + mapping[i].GetType().Name); } NewLine(builder, indent + 1) .Append("optional ") .Append(_model.GetSchemaTypeName(effectiveType, BinaryDataFormat.Default, false, false, ref requiresBclImport).Replace('.', '_')) .Append(' ').Append(mapping[i].Name).Append(" = ").Append(i + 1).Append(';'); } NewLine(builder, indent).Append('}'); } } else if (Helpers.IsEnum(Type)) { NewLine(builder, indent).Append("enum ").Append(GetSchemaTypeName()).Append(" {"); if (_settingsValueFinal.EnumPassthru.GetValueOrDefault()) { if (Type #if WINRT .GetTypeInfo() #endif .IsDefined(_model.MapType(typeof(FlagsAttribute)), false)) { NewLine(builder, indent + 1).Append("// this is a composite/flags enumeration"); } else { NewLine(builder, indent + 1).Append("// this enumeration will be passed as a raw value"); } foreach (FieldInfo field in #if WINRT Type.GetRuntimeFields() #else Type.GetFields() #endif ) { if (field.IsStatic && field.IsLiteral) { object enumVal; #if WINRT || PORTABLE || CF || FX11 enumVal = field.GetValue(null); #else enumVal = field.GetRawConstantValue(); #endif NewLine(builder, indent + 1).Append(field.Name).Append(" = ").Append(enumVal).Append(";"); } } } else { foreach (ValueMember member in fieldsArr) { NewLine(builder, indent + 1).Append(member.Name).Append(" = ").Append(member.FieldNumber).Append(';'); } } NewLine(builder, indent).Append('}'); } else { NewLine(builder, indent).Append("message ").Append(GetSchemaTypeName()).Append(" {"); foreach (ValueMember member in fieldsArr) { member.Serializer.GetHashCode(); MemberLevelSettingsValue s = member.GetFinalSettingsCopy(0); string ordinality = s.Collection.IsCollection ? "repeated" : member.IsRequired ? "required" : "optional"; NewLine(builder, indent + 1).Append(ordinality).Append(' '); if (s.ContentBinaryFormatHint.GetValueOrDefault() == BinaryDataFormat.Group) { builder.Append("group "); } string schemaTypeName = member.GetSchemaTypeName(true, ref requiresBclImport); builder.Append(schemaTypeName).Append(" ") .Append(member.Name).Append(" = ").Append(member.FieldNumber); object defaultValue = member.GetFinalDefaultValue(); if (defaultValue != null && member.IsRequired == false) { if (defaultValue is string) { builder.Append(" [default = \"").Append(defaultValue).Append("\"]"); } else if (defaultValue is bool) { // need to be lower case (issue 304) builder.Append((bool)defaultValue ? " [default = true]" : " [default = false]"); } else { builder.Append(" [default = ").Append(defaultValue).Append(']'); } } if (s.Collection.IsCollection && s.Collection.Format == CollectionFormat.Protobuf && ListDecorator.CanPack(HelpersInternal.GetWireType(Helpers.GetTypeCode(member.MemberType), s.ContentBinaryFormatHint.GetValueOrDefault()))) { builder.Append(" [packed=true]"); } builder.Append(';'); if (schemaTypeName == "bcl.NetObjectProxy" && (s.Format == ValueFormat.Reference || s.Format == ValueFormat.LateReference) && !s.WriteAsDynamicType.GetValueOrDefault()) // we know what it is; tell the user { builder.Append(" // reference-tracked ").Append(member.GetSchemaTypeName(false, ref requiresBclImport)); } } if (_subTypes != null && _subTypes.Count != 0) { NewLine(builder, indent + 1).Append("// the following represent sub-types; at most 1 should have a value"); SubType[] subTypeArr = new SubType[_subTypes.Count]; _subTypes.CopyTo(subTypeArr, 0); Array.Sort(subTypeArr, SubType.Comparer.Default); foreach (SubType subType in subTypeArr) { string subTypeName = subType.DerivedType.GetSchemaTypeName(); NewLine(builder, indent + 1).Append("optional ").Append(subTypeName) .Append(" ").Append(subTypeName).Append(" = ").Append(subType.FieldNumber).Append(';'); } } NewLine(builder, indent).Append('}'); } }