Beispiel #1
0
        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);
        }
Beispiel #2
0
        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);
        }
Beispiel #3
0
        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?
                }
            }
        }