internal static IProtoSerializer TryGetCoreSerializer(RuntimeTypeModel model, DataFormat dataFormat, Type type, out WireType defaultWireType, bool asReference, bool dynamicType, bool overwriteList, bool allowComplexTypes) { #if !NO_GENERICS { Type tmp = Helpers.GetUnderlyingType(type); if (tmp != null) { type = tmp; } } #endif if (Helpers.IsEnum(type)) { if (allowComplexTypes && model != null) { // need to do this before checking the typecode; an int enum will report Int32 etc defaultWireType = WireType.Variant; return(new EnumSerializer(type, model.GetEnumMap(type))); } else { // enum is fine for adding as a meta-type defaultWireType = WireType.None; return(null); } } ProtoTypeCode code = Helpers.GetTypeCode(type); switch (code) { case ProtoTypeCode.Int32: defaultWireType = GetIntWireType(dataFormat, 32); return(new Int32Serializer(model)); case ProtoTypeCode.UInt32: defaultWireType = GetIntWireType(dataFormat, 32); return(new UInt32Serializer(model)); case ProtoTypeCode.Int64: defaultWireType = GetIntWireType(dataFormat, 64); return(new Int64Serializer(model)); case ProtoTypeCode.UInt64: defaultWireType = GetIntWireType(dataFormat, 64); return(new UInt64Serializer(model)); case ProtoTypeCode.String: defaultWireType = WireType.String; if (asReference) { return(new NetObjectSerializer(model, model.MapType(typeof(string)), 0, BclHelpers.NetObjectOptions.AsReference)); } return(new StringSerializer(model)); case ProtoTypeCode.Single: defaultWireType = WireType.Fixed32; return(new SingleSerializer(model)); case ProtoTypeCode.Double: defaultWireType = WireType.Fixed64; return(new DoubleSerializer(model)); case ProtoTypeCode.Boolean: defaultWireType = WireType.Variant; return(new BooleanSerializer(model)); case ProtoTypeCode.DateTime: defaultWireType = GetDateTimeWireType(dataFormat); return(new DateTimeSerializer(dataFormat, model)); case ProtoTypeCode.Decimal: defaultWireType = WireType.String; return(new DecimalSerializer(model)); case ProtoTypeCode.Byte: defaultWireType = GetIntWireType(dataFormat, 32); return(new ByteSerializer(model)); case ProtoTypeCode.SByte: defaultWireType = GetIntWireType(dataFormat, 32); return(new SByteSerializer(model)); case ProtoTypeCode.Char: defaultWireType = WireType.Variant; return(new CharSerializer(model)); case ProtoTypeCode.Int16: defaultWireType = GetIntWireType(dataFormat, 32); return(new Int16Serializer(model)); case ProtoTypeCode.UInt16: defaultWireType = GetIntWireType(dataFormat, 32); return(new UInt16Serializer(model)); case ProtoTypeCode.TimeSpan: defaultWireType = GetDateTimeWireType(dataFormat); return(new TimeSpanSerializer(dataFormat, model)); case ProtoTypeCode.Guid: defaultWireType = dataFormat == DataFormat.Group ? WireType.StartGroup : WireType.String; return(new GuidSerializer(model)); case ProtoTypeCode.Uri: defaultWireType = WireType.String; return(new StringSerializer(model)); case ProtoTypeCode.ByteArray: defaultWireType = WireType.String; return(new BlobSerializer(model, overwriteList)); case ProtoTypeCode.Type: defaultWireType = WireType.String; return(new SystemTypeSerializer(model)); } IProtoSerializer parseable = model.AllowParseableTypes ? ParseableSerializer.TryCreate(type, model) : null; if (parseable != null) { defaultWireType = WireType.String; return(parseable); } if (allowComplexTypes && model != null) { int key = model.GetKey(type, false, true); MetaType meta = null; if (key >= 0) { meta = model[type]; if (dataFormat == DataFormat.Default && meta.IsGroup) { dataFormat = DataFormat.Group; } } if (asReference || dynamicType) { BclHelpers.NetObjectOptions options = BclHelpers.NetObjectOptions.None; if (asReference) { options |= BclHelpers.NetObjectOptions.AsReference; } if (dynamicType) { options |= BclHelpers.NetObjectOptions.DynamicType; } if (meta != null) { // exists if (asReference && Helpers.IsValueType(type)) { string message = "AsReference cannot be used with value-types"; if (type.Name == "KeyValuePair`2") { message += "; please see http://stackoverflow.com/q/14436606/"; } else { message += ": " + type.FullName; } throw new InvalidOperationException(message); } if (asReference && meta.IsAutoTuple) { options |= BclHelpers.NetObjectOptions.LateSet; } if (meta.UseConstructor) { options |= BclHelpers.NetObjectOptions.UseConstructor; } } defaultWireType = dataFormat == DataFormat.Group ? WireType.StartGroup : WireType.String; return(new NetObjectSerializer(model, type, key, options)); } if (key >= 0) { defaultWireType = dataFormat == DataFormat.Group ? WireType.StartGroup : WireType.String; return(new SubItemSerializer(type, key, meta, true)); } } defaultWireType = WireType.None; return(null); }
internal static IProtoSerializer TryGetCoreSerializer(RuntimeTypeModel model, DataFormat dataFormat, Type type, out WireType defaultWireType, bool asReference, bool dynamicType, bool overwriteList, bool allowComplexTypes) { Type underlyingType = Helpers.GetUnderlyingType(type); if (underlyingType != null) { type = underlyingType; } if (Helpers.IsEnum(type)) { if (allowComplexTypes && (model != null)) { defaultWireType = WireType.Variant; return(new EnumSerializer(type, model.GetEnumMap(type))); } defaultWireType = WireType.None; return(null); } switch (Helpers.GetTypeCode(type)) { case ProtoTypeCode.Boolean: defaultWireType = WireType.Variant; return(new BooleanSerializer(model)); case ProtoTypeCode.Char: defaultWireType = WireType.Variant; return(new CharSerializer(model)); case ProtoTypeCode.SByte: defaultWireType = GetIntWireType(dataFormat, 0x20); return(new SByteSerializer(model)); case ProtoTypeCode.Byte: defaultWireType = GetIntWireType(dataFormat, 0x20); return(new ByteSerializer(model)); case ProtoTypeCode.Int16: defaultWireType = GetIntWireType(dataFormat, 0x20); return(new Int16Serializer(model)); case ProtoTypeCode.UInt16: defaultWireType = GetIntWireType(dataFormat, 0x20); return(new UInt16Serializer(model)); case ProtoTypeCode.Int32: defaultWireType = GetIntWireType(dataFormat, 0x20); return(new Int32Serializer(model)); case ProtoTypeCode.UInt32: defaultWireType = GetIntWireType(dataFormat, 0x20); return(new UInt32Serializer(model)); case ProtoTypeCode.Int64: defaultWireType = GetIntWireType(dataFormat, 0x40); return(new Int64Serializer(model)); case ProtoTypeCode.UInt64: defaultWireType = GetIntWireType(dataFormat, 0x40); return(new UInt64Serializer(model)); case ProtoTypeCode.Single: defaultWireType = WireType.Fixed32; return(new SingleSerializer(model)); case ProtoTypeCode.Double: defaultWireType = WireType.Fixed64; return(new DoubleSerializer(model)); case ProtoTypeCode.Decimal: defaultWireType = WireType.String; return(new DecimalSerializer(model)); case ProtoTypeCode.DateTime: defaultWireType = GetDateTimeWireType(dataFormat); return(new DateTimeSerializer(model)); case ProtoTypeCode.String: defaultWireType = WireType.String; if (!asReference) { return(new StringSerializer(model)); } return(new NetObjectSerializer(model, model.MapType(typeof(string)), 0, BclHelpers.NetObjectOptions.AsReference)); case ProtoTypeCode.TimeSpan: defaultWireType = GetDateTimeWireType(dataFormat); return(new TimeSpanSerializer(model)); case ProtoTypeCode.ByteArray: defaultWireType = WireType.String; return(new BlobSerializer(model, overwriteList)); case ProtoTypeCode.Guid: defaultWireType = WireType.String; return(new GuidSerializer(model)); case ProtoTypeCode.Uri: defaultWireType = WireType.String; return(new StringSerializer(model)); case ProtoTypeCode.Type: defaultWireType = WireType.String; return(new SystemTypeSerializer(model)); } IProtoSerializer serializer = model.AllowParseableTypes ? ParseableSerializer.TryCreate(type, model) : null; if (serializer != null) { defaultWireType = WireType.String; return(serializer); } if (allowComplexTypes && (model != null)) { int key = model.GetKey(type, false, true); if (asReference || dynamicType) { defaultWireType = (dataFormat == DataFormat.Group) ? WireType.StartGroup : WireType.String; BclHelpers.NetObjectOptions none = BclHelpers.NetObjectOptions.None; if (asReference) { none = (BclHelpers.NetObjectOptions)((byte)(none | BclHelpers.NetObjectOptions.AsReference)); } if (dynamicType) { none = (BclHelpers.NetObjectOptions)((byte)(none | BclHelpers.NetObjectOptions.DynamicType)); } if (key >= 0) { if (asReference && Helpers.IsValueType(type)) { string message = "AsReference cannot be used with value-types"; if (type.Name == "KeyValuePair`2") { message = message + "; please see http://stackoverflow.com/q/14436606/"; } else { message = message + ": " + type.FullName; } throw new InvalidOperationException(message); } MetaType type3 = model[type]; if (asReference && type3.IsAutoTuple) { none = (BclHelpers.NetObjectOptions)((byte)(none | BclHelpers.NetObjectOptions.LateSet)); } if (type3.UseConstructor) { none = (BclHelpers.NetObjectOptions)((byte)(none | (BclHelpers.NetObjectOptions.None | BclHelpers.NetObjectOptions.UseConstructor))); } } return(new NetObjectSerializer(model, type, key, none)); } if (key >= 0) { defaultWireType = (dataFormat == DataFormat.Group) ? WireType.StartGroup : WireType.String; return(new SubItemSerializer(type, key, model[type], true)); } } defaultWireType = WireType.None; return(null); }
protected ListDecorator( RuntimeTypeModel model, Type declaredType, Type concreteTypeDefault, IProtoSerializerWithWireType tail, bool writePacked, WireType packedWireType, bool overwriteList, bool protoCompatibility, bool writeSubType) : base(tail) { if (overwriteList) { _options |= OPTIONS_OverwriteList; } PackedWireTypeForRead = packedWireType; _protoCompatibility = protoCompatibility; _writeSubType = writeSubType && !protoCompatibility; if (writePacked) { _options |= OPTIONS_WritePacked; } if (declaredType == null) { throw new ArgumentNullException(nameof(declaredType)); } if (declaredType.IsArray) { throw new ArgumentException("Cannot treat arrays as lists", nameof(declaredType)); } this.ExpectedType = declaredType; this._concreteTypeDefault = concreteTypeDefault ?? declaredType; // look for a public list.Add(typedObject) method if (RequireAdd) { bool isList; _add = TypeModel.ResolveListAdd(model, declaredType, tail.ExpectedType, out isList); if (isList) { _options |= OPTIONS_IsList; string fullName = declaredType.FullName; if (fullName != null && fullName.StartsWith("System.Data.Linq.EntitySet`1[[", StringComparison.Ordinal)) { // see http://stackoverflow.com/questions/6194639/entityset-is-there-a-sane-reason-that-ilist-add-doesnt-set-assigned _options |= OPTIONS_SuppressIList; } } if (_add == null) { throw new InvalidOperationException("Unable to resolve a suitable Add method for " + declaredType.FullName); } } ListHelpers = new ListHelpers(WritePacked, PackedWireTypeForRead, _protoCompatibility, tail, false); if (!protoCompatibility) { int key = model.GetKey(declaredType, false, false); if (key >= 0) { _metaType = model[key]; } else { _writeSubType = false; // warn? } } }