Exemplo n.º 1
0
        internal static bool TryGetTag(MemberInfo member, out int tag, out string name, bool callerIsTagInference, out DataFormat format, out MemberSerializationOptions options)
        {
            name    = member.Name;
            format  = DataFormat.Default;
            tag     = -1;
            options = MemberSerializationOptions.None;

            // check for delegates (don't even try!)
            Type valueType;

            switch (member.MemberType)
            {
            case MemberTypes.Property:
                valueType = ((PropertyInfo)member).PropertyType;
                break;

            case MemberTypes.Field:
                valueType = ((FieldInfo)member).FieldType;
                break;

            default:     // not sure what this is!
                return(false);
            }
            if (valueType.IsSubclassOf(typeof(Delegate)))
            {
                return(false);
            }

            // check for exclusion
            if (AttributeUtils.GetAttribute <ProtoIgnoreAttribute>(member) != null ||
                AttributeUtils.GetAttribute <ProtoPartialIgnoreAttribute>(member.ReflectedType,
                                                                          delegate(ProtoPartialIgnoreAttribute ppia)
                                                                          { return(ppia.MemberName == member.Name); }) != null)
            {
                return(false);
            }

            // check against the property
            ProtoMemberAttribute pm = AttributeUtils.GetAttribute <ProtoMemberAttribute>(member);

            if (pm == null)
            { // check also against the type
                pm = AttributeUtils.GetAttribute <ProtoPartialMemberAttribute>(member.ReflectedType,
                                                                               delegate(ProtoPartialMemberAttribute ppma) { return(ppma.MemberName == member.Name); });
            }
            if (pm != null)
            {
                format = pm.DataFormat;
                if (!string.IsNullOrEmpty(pm.Name))
                {
                    name = pm.Name;
                }
                tag     = pm.Tag;
                options = pm.Options;
                return(tag > 0);
            }

            ProtoContractAttribute pca = AttributeUtils.GetAttribute <ProtoContractAttribute>(member.DeclaringType);

            if (pca != null && pca.ImplicitFields != ImplicitFields.None)
            {
                if (callerIsTagInference)
                {
                    return(true);                     // short-circuit
                }
                List <MemberInfo> members = new List <MemberInfo>();
                switch (pca.ImplicitFields)
                {
                case ImplicitFields.AllFields:
                    AddImplicitByDeclaringType(member.DeclaringType, members,
                                               member.DeclaringType.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic));
                    break;

                case ImplicitFields.AllPublic:
                    AddImplicitByDeclaringType(member.DeclaringType, members,
                                               member.DeclaringType.GetFields(BindingFlags.Instance | BindingFlags.Public));
                    AddImplicitByDeclaringType(member.DeclaringType, members,
                                               member.DeclaringType.GetProperties(BindingFlags.Instance | BindingFlags.Public));
                    break;

                default:
                    throw new NotSupportedException("Unknown ImplicitFields option: " + pca.ImplicitFields);
                }
                members.Sort(delegate(MemberInfo x, MemberInfo y)
                {
                    return(string.CompareOrdinal(x.Name, y.Name));
                });
                int index = members.IndexOf(member);
                if (index >= 0)
                {
                    tag = index + pca.ImplicitFirstTag;
                    return(true);
                }
                return(false);
            }


            XmlElementAttribute xe = AttributeUtils.GetAttribute <XmlElementAttribute>(member);

            if (xe != null)
            {
                if (!string.IsNullOrEmpty(xe.ElementName))
                {
                    name = xe.ElementName;
                }
                tag = xe.Order;
                return(tag > 0);
            }

            XmlArrayAttribute xa = AttributeUtils.GetAttribute <XmlArrayAttribute>(member);

            if (xa != null)
            {
                if (!string.IsNullOrEmpty(xa.ElementName))
                {
                    name = xa.ElementName;
                }
                tag = xa.Order;
                return(tag > 0);
            }

            return(false);
        }
Exemplo n.º 2
0
 internal static bool HasOption(MemberSerializationOptions options, MemberSerializationOptions required)
 {
     return((options & required) == required);
 }
Exemplo n.º 3
0
 /// <summary>
 /// Supports various different property metadata patterns:
 /// [ProtoMember] is the most specific, allowing the data-format to be set.
 /// [DataMember], [XmlElement] are supported for compatibility.
 /// In any event, there must be a unique positive Tag/Order.
 /// </summary>
 internal static bool TryGetTag(MemberInfo member, out int tag, out string name, out DataFormat format, out MemberSerializationOptions options)
 {
     return(TryGetTag(member, out tag, out name, false, out format, out options));
 }
Exemplo n.º 4
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 == 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(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(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(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.IsEnum)
            {
                format = DataFormat.TwosComplement;
                return(PropertyUtil <T> .CreateTypedProperty("CreatePropertyEnum", type));
            }

            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);
        }