Beispiel #1
0
        private void InitPrivate(int tag, DataFormat dataFormat, bool isOptional, MemberInfo member, Delegate getValue, Delegate setValue, object defaultValue)
        {
            if (this.prefix != 0)
            {
                throw new InvalidOperationException("Can only initialise a property once");
            }

            if (member != null)
            {
                MemberSerializationOptions options;
                if (!Serializer.TryGetTag(member, out tag, out name, out dataFormat, out options))
                {
                    throw new ArgumentException(member.Name + " cannot be used for serialization", "member");
                }
                isOptional = !PropertyFactory.HasOption(options, MemberSerializationOptions.Required);
                {
                    DefaultValueAttribute dva = AttributeUtils.GetAttribute <DefaultValueAttribute>(member);
                    defaultValue = dva == null ? null : dva.Value;
                }
#if CF
                this.description = null; // not used in CF; assigned to get rid of warning
#else
                {
                    DescriptionAttribute da = AttributeUtils.GetAttribute <DescriptionAttribute>(member);
                    this.description = da == null ? null : da.Description;
                }
#endif
            }
            this.isOptional   = isOptional;
            this.defaultValue = defaultValue;
            this.dataFormat   = dataFormat; // set initial format, and use the *field* for the "ref" so either usage is valid
            OnBeforeInit(member, getValue, setValue, tag, ref this.dataFormat);
            this.prefix = Serializer.GetFieldToken(tag, WireType);
            OnAfterInit();
        }
Beispiel #2
0
        /// <summary>
        /// Responsible for deciding how to encode/decode a given data-type; maybe
        /// not the most elegant solution, but it is simple and quick.
        /// </summary>
        private static Property <T> CreateProperty <T>(Type type, ref DataFormat format, MemberSerializationOptions options)
        {
            if (type.IsEnum)
            {
                if (format != DataFormat.Default && Attribute.IsDefined(type, typeof(FlagsAttribute)))
                {
                    type = Enum.GetUnderlyingType(type);
                }
                else
                {
                    format = DataFormat.TwosComplement;
                    return(PropertyUtil <T> .CreateTypedProperty("CreatePropertyEnum", type));
                }
            }

            if (type == typeof(int))
            {
                switch (format)
                {
                case DataFormat.Default:
                case DataFormat.TwosComplement:
                    format = DataFormat.TwosComplement;
                    return(new PropertyInt32Variant <T>());

                case DataFormat.ZigZag:
                    return(new PropertyInt32ZigZag <T>());

                case DataFormat.FixedSize:
                    return(new PropertyInt32Fixed <T>());
                }
            }
            if (type == typeof(short))
            {
                switch (format)
                {
                case DataFormat.Default:
                case DataFormat.TwosComplement:
                    format = DataFormat.TwosComplement;
                    return(new PropertyInt16Variant <T>());

                case DataFormat.ZigZag:
                    return(new PropertyInt16ZigZag <T>());
                }
            }
            if (type == typeof(long))
            {
                switch (format)
                {
                case DataFormat.Default:
                case DataFormat.TwosComplement:
                    format = DataFormat.TwosComplement;
                    return(new PropertyInt64Variant <T>());

                case DataFormat.ZigZag:
                    return(new PropertyInt64ZigZag <T>());

                case DataFormat.FixedSize:
                    return(new PropertyInt64Fixed <T>());
                }
            }
            if (type == typeof(uint))
            {
                switch (format)
                {
                case DataFormat.Default:
                case DataFormat.TwosComplement:
                    format = DataFormat.TwosComplement;
                    return(new PropertyUInt32Variant <T>());

                case DataFormat.FixedSize:
                    return(new PropertyUInt32Fixed <T>());
                }
            }
            if (type == typeof(ulong))
            {
                switch (format)
                {
                case DataFormat.Default:
                case DataFormat.TwosComplement:
                    format = DataFormat.TwosComplement;
                    return(new PropertyUInt64Variant <T>());

                case DataFormat.FixedSize:
                    return(new PropertyUInt64Fixed <T>());
                }
            }

            if (type == typeof(ushort))
            {
                switch (format)
                {
                case DataFormat.Default:
                case DataFormat.TwosComplement:
                    format = DataFormat.TwosComplement;
                    return(new PropertyUInt16Variant <T>());
                }
            }

            if (type == typeof(byte[]))
            {
                format = DataFormat.Default; return(new PropertyBlob <T>());
            }
            if (type == typeof(byte))
            {
                format = DataFormat.TwosComplement; return(new PropertyByte <T>());
            }
            if (type == typeof(sbyte))
            {
                format = DataFormat.ZigZag; return(new PropertySByte <T>());
            }
            if (type == typeof(char))
            {
                format = DataFormat.TwosComplement; return(new PropertyChar <T>());
            }
            if (type == typeof(bool))
            {
                format = DataFormat.TwosComplement; return(new PropertyBoolean <T>());
            }
            if (type == typeof(string))
            {
                format = DataFormat.Default; return(new PropertyString <T>());
            }
            if (type == typeof(float))
            {
                format = DataFormat.FixedSize; return(new PropertySingle <T>());
            }
            if (type == typeof(double))
            {
                format = DataFormat.FixedSize; return(new PropertyDouble <T>());
            }
            if (type == typeof(Uri))
            {
                format = DataFormat.Default; return(new PropertyUri <T>());
            }

            if (type == typeof(Guid))
            {
                switch (format)
                {
                case DataFormat.Group: return(new PropertyGuidGroup <T>());

                case DataFormat.Default: return(new PropertyGuidString <T>());
                }
            }
            if (type == typeof(TimeSpan))
            {
                switch (format)
                {
                case DataFormat.Group: return(new PropertyTimeSpanGroup <T>());

                case DataFormat.Default: return(new PropertyTimeSpanString <T>());

                case DataFormat.FixedSize: return(new PropertyTimeSpanFixed <T>());
                }
            }
            if (type == typeof(DateTime))
            {
                switch (format)
                {
                case DataFormat.Group: return(new PropertyDateTimeGroup <T>());

                case DataFormat.Default: return(new PropertyDateTimeString <T>());

                case DataFormat.FixedSize: return(new PropertyDateTimeFixed <T>());
                }
            }
            if (type == typeof(decimal))
            {
                switch (format)
                {
                case DataFormat.Group: return(new PropertyDecimalGroup <T>());

                case DataFormat.Default: return(new PropertyDecimalString <T>());
                }
            }


            if (Serializer.IsEntityType(type))
            {
                Type baseType = type;
                while (Serializer.IsEntityType(baseType.BaseType))
                {
                    baseType = baseType.BaseType;
                }
                switch (format)
                {
                case DataFormat.Default: return(PropertyUtil <T> .CreateTypedProperty("CreatePropertyMessageString", type, baseType, baseType));

                case DataFormat.Group: return(PropertyUtil <T> .CreateTypedProperty("CreatePropertyMessageGroup", type, baseType, baseType));
                }
            }

            if (type.IsValueType && type.IsGenericType && type.GetGenericTypeDefinition() == typeof(KeyValuePair <,>))
            {
                return(PropertyUtil <T> .CreateTypedProperty("CreatePropertyPairString", type.GetGenericArguments()));
            }
            bool isEnumerableOnly;
            Type listItemType = GetListType(type, out isEnumerableOnly);

            if (type.IsArray)
            {
                // verify that we can handle it
                if (type.GetArrayRank() != 1)
                {
                    throw new NotSupportedException("Only 1-dimensional arrays can be used; consider an array/list of a class-type instead");
                }
            }

            if (listItemType != null && listItemType != typeof(byte[]))
            {
                bool dummy;
                if (GetListType(listItemType, out dummy) != null)
                {
                    throw new NotSupportedException("Nested (jagged) arrays/lists are not supported (except for byte[]); consider an array/list of a class-type with an inner array/list instead");
                }
            }


            if (type == typeof(byte[]))
            {   // want to treat byte[] as a special case
                listItemType = null;
            }
            if (type.IsArray && listItemType != null) // second check is for byte[]
            {
                return(PropertyUtil <T> .CreateTypedProperty(
                           (PropertyFactory.HasOption(options, MemberSerializationOptions.Packed)
                        ? "CreatePropertyPackedArray" : "CreatePropertyArray"), listItemType));
            }

            if (listItemType != null)
            {
                if (isEnumerableOnly)
                {
                    if (GetAddMethod(type, listItemType) != null)
                    {
                        return(PropertyUtil <T> .CreateTypedProperty(
                                   (PropertyFactory.HasOption(options, MemberSerializationOptions.Packed)
                            ? "CreatePropertyPackedEnumerable" : "CreatePropertyEnumerable"), type, listItemType));
                    }
                }
                else
                {
                    return(PropertyUtil <T> .CreateTypedProperty(
                               (PropertyFactory.HasOption(options, MemberSerializationOptions.Packed)
                        ? "CreatePropertyPackedList" : "CreatePropertyList"), type, listItemType));
                }
            }

            Type nullType = Nullable.GetUnderlyingType(type);

            if (nullType != null)
            {
                return(PropertyUtil <T> .CreateTypedProperty("CreatePropertyNullable", nullType));
            }

            if (format == DataFormat.Default && GetParseMethod(type) != null)
            {
                return(PropertyUtil <T> .CreateTypedProperty("CreatePropertyParseable", type));
            }

            throw Serializer.ThrowNoEncoder(format, type);
        }