Exemple #1
0
        internal static AttributeFamily GetContractFamily(Type type, object[] attributes)
        {
            AttributeFamily family = AttributeFamily.None;

            if (attributes == null)
            {
                attributes = type.GetCustomAttributes(false);
            }
            for (int i = 0; i < attributes.Length; i++)
            {
                switch (attributes[i].GetType().FullName)
                {
                case "ProtoBuf.ProtoContractAttribute":
                    bool tmp = false;
                    GetFieldBoolean(ref tmp, (Attribute)attributes[i], "UseProtoMembersOnly");
                    if (tmp)
                    {
                        return(AttributeFamily.ProtoBuf);
                    }
                    family |= AttributeFamily.ProtoBuf;
                    break;

                case "System.Xml.Serialization.XmlTypeAttribute": family |= AttributeFamily.XmlSerializer; break;

                case "System.Runtime.Serialization.DataContractAttribute": family |= AttributeFamily.DataContractSerialier; break;
                }
            }
            return(family);
        }
Exemple #2
0
        internal static AttributeFamily GetContractFamily(Type type, object[] attributes)
        {
            AttributeFamily family = AttributeFamily.None;

            if (attributes == null)
            {
                attributes = type.GetCustomAttributes(true);
            }
            for (int i = 0; i < attributes.Length; i++)
            {
                switch (attributes[i].GetType().FullName)
                {
                case "ProtoBuf.ProtoContractAttribute": family |= AttributeFamily.ProtoBuf; break;

                case "System.Xml.Serialization.XmlTypeAttribute": family |= AttributeFamily.XmlSerializer; break;

                case "System.Runtime.Serialization.DataContractAttribute": family |= AttributeFamily.DataContractSerialier; break;
                }
            }
            return(family);
        }
Exemple #3
0
        private ValueMember ApplyDefaultBehaviour(bool isEnum, AttributeFamily family, MemberInfo member, BasicList partialMembers)
        {
            if (member == null || (family == AttributeFamily.None && !isEnum))
            {
                return(null);                                                               // nix
            }
            Type effectiveType;

            switch (member.MemberType)
            {
            case MemberTypes.Field:
                effectiveType = ((FieldInfo)member).FieldType; break;

            case MemberTypes.Property:
                effectiveType = ((PropertyInfo)member).PropertyType; break;

            default:
                return(null);    // nothing doing
            }

            int    fieldNumber = 0;
            bool   isPacked    = false;
            string name        = null;
            bool   isRequired  = false;
            Type   itemType    = null;
            Type   defaultType = null;

            ResolveListTypes(effectiveType, ref itemType, ref defaultType);
            object[]   attribs = member.GetCustomAttributes(true);
            Attribute  attrib;
            DataFormat dataFormat   = DataFormat.Default;
            bool       ignore       = false;
            object     defaultValue = null;

            // implicit zero default
            switch (Type.GetTypeCode(effectiveType))
            {
            case TypeCode.Boolean: defaultValue = false; break;

            case TypeCode.Decimal: defaultValue = (decimal)0; break;

            case TypeCode.Single: defaultValue = (float)0; break;

            case TypeCode.Double: defaultValue = (double)0; break;

            case TypeCode.Byte: defaultValue = (byte)0;  break;

            case TypeCode.Char: defaultValue = (char)0; break;

            case TypeCode.Int16: defaultValue = (short)0; break;

            case TypeCode.Int32: defaultValue = (int)0; break;

            case TypeCode.Int64: defaultValue = (long)0; break;

            case TypeCode.SByte: defaultValue = (sbyte)0; break;

            case TypeCode.UInt16: defaultValue = (ushort)0; break;

            case TypeCode.UInt32: defaultValue = (uint)0; break;

            case TypeCode.UInt64: defaultValue = (ulong)0; break;

            default:
                if (effectiveType == typeof(TimeSpan))
                {
                    defaultValue = TimeSpan.Zero;
                }
                if (effectiveType == typeof(Guid))
                {
                    defaultValue = Guid.Empty;
                }
                break;
            }
            bool done = false;

            if (isEnum)
            {
                attrib = GetAttribute(attribs, "ProtoBuf.ProtoIgnoreAttribute");
                if (attrib != null)
                {
                    ignore = true;
                }
                else
                {
                    attrib      = GetAttribute(attribs, "ProtoBuf.ProtoEnumAttribute");
                    fieldNumber = Convert.ToInt32(((FieldInfo)member).GetValue(null));
                    if (attrib != null)
                    {
                        GetFieldName(ref name, attrib, "Name");
                        if ((bool)attrib.GetType().GetMethod("HasValue").Invoke(attrib, null))
                        {
                            fieldNumber = (int)GetMemberValue(attrib, "Value");
                        }
                    }
                }
                done = true;
            }
            if (!ignore && !done) // always consider ProtoMember
            {
                attrib = GetAttribute(attribs, "ProtoBuf.ProtoMemberAttribute");
                GetIgnore(ref ignore, attrib, attribs, "ProtoBuf.ProtoIgnoreAttribute");
                if (!ignore)
                {
                    GetFieldNumber(ref fieldNumber, attrib, "Tag");
                    GetFieldName(ref name, attrib, "Name");
                    GetFieldBoolean(ref isRequired, attrib, "IsRequired");
                    GetFieldBoolean(ref isPacked, attrib, "IsPacked");
                    GetDataFormat(ref dataFormat, attrib, "DataFormat");
                    done = fieldNumber > 0;
                }

                if (!done && partialMembers != null)
                {
                    foreach (ProtoPartialMemberAttribute ppma in partialMembers)
                    {
                        if (ppma.MemberName == member.Name)
                        {
                            GetFieldNumber(ref fieldNumber, ppma, "Tag");
                            GetFieldName(ref name, ppma, "Name");
                            GetFieldBoolean(ref isRequired, ppma, "IsRequired");
                            GetFieldBoolean(ref isPacked, ppma, "IsPacked");
                            GetDataFormat(ref dataFormat, ppma, "DataFormat");
                            if (done = fieldNumber > 0)
                            {
                                break;
                            }
                        }
                    }
                }
            }
            if (!ignore && !done && HasFamily(family, AttributeFamily.DataContractSerialier))
            {
                attrib = GetAttribute(attribs, "System.Runtime.Serialization.DataMemberAttribute");
                GetFieldNumber(ref fieldNumber, attrib, "Order");
                GetFieldName(ref name, attrib, "Name");
                GetFieldBoolean(ref isRequired, attrib, "IsRequired");
                done = fieldNumber > 0;
            }
            if (!ignore && !done && HasFamily(family, AttributeFamily.XmlSerializer))
            {
                attrib = GetAttribute(attribs, "System.Xml.Serialization.XmlElementAttribute");
                GetIgnore(ref ignore, attrib, attribs, "System.Xml.Serialization.XmlIgnoreAttribute");
                if (!ignore)
                {
                    GetFieldNumber(ref fieldNumber, attrib, "Order");
                    GetFieldName(ref name, attrib, "ElementName");
                }
                attrib = GetAttribute(attribs, "System.Xml.Serialization.XmlArrayAttribute");
                GetIgnore(ref ignore, attrib, attribs, "ProtoBuf.XmlIgnoreAttribute");
                if (!ignore)
                {
                    GetFieldNumber(ref fieldNumber, attrib, "Order");
                    GetFieldName(ref name, attrib, "ElementName");
                }
                done = fieldNumber > 0;
            }
            if (!ignore && (attrib = GetAttribute(attribs, "System.ComponentModel.DefaultValueAttribute")) != null)
            {
                defaultValue = GetMemberValue(attrib, "Value");
            }
            ValueMember vm = ((isEnum || fieldNumber > 0) && !ignore)
                ? new ValueMember(model, type, fieldNumber, member, effectiveType, itemType, defaultType, dataFormat, defaultValue)
                    : null;

            if (vm != null)
            {
                PropertyInfo prop = type.GetProperty(member.Name + "Specified", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public,
                                                     null, typeof(bool), Helpers.EmptyTypes, null);
                if (prop != null)
                {
                    vm.SetSpecified(prop.GetGetMethod(true), prop.GetSetMethod(true));
                }
                else
                {
                    MethodInfo method = type.GetMethod("ShouldSerialize" + member.Name, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public,
                                                       null, Helpers.EmptyTypes, null);
                    if (method != null && method.ReturnType == typeof(bool))
                    {
                        vm.SetSpecified(method, null);
                    }
                }
                if (!Helpers.IsNullOrEmpty(name))
                {
                    vm.SetName(name);
                }
                vm.IsPacked   = isPacked;
                vm.IsRequired = isRequired;
            }
            return(vm);
        }
Exemple #4
0
 private static bool HasFamily(AttributeFamily value, AttributeFamily required)
 {
     return((value & required) == required);
 }
Exemple #5
0
        internal void ApplyDefaultBehaviour()
        {
            if (model.FindWithoutAdd(type.BaseType) == null &&
                GetContractFamily(type.BaseType, null) != MetaType.AttributeFamily.None)
            {
                model.FindOrAddAuto(type.BaseType, true, false, false);
            }

            object[]        typeAttribs = type.GetCustomAttributes(true);
            AttributeFamily family      = GetContractFamily(type, typeAttribs);
            bool            isEnum      = type.IsEnum;

            if (family == AttributeFamily.None && !isEnum)
            {
                return;                                            // and you'd like me to do what, exactly?
            }
            BasicList partialIgnores = null, partialMembers = null;

            for (int i = 0; i < typeAttribs.Length; i++)
            {
                if (!isEnum && typeAttribs[i] is ProtoIncludeAttribute)
                {
                    ProtoIncludeAttribute pia = (ProtoIncludeAttribute)typeAttribs[i];
                    AddSubType(pia.Tag, pia.KnownType);
                }
                if (typeAttribs[i] is ProtoPartialIgnoreAttribute)
                {
                    if (partialIgnores == null)
                    {
                        partialIgnores = new BasicList();
                    }
                    partialIgnores.Add(((ProtoPartialIgnoreAttribute)typeAttribs[i]).MemberName);
                }
                if (!isEnum && typeAttribs[i] is ProtoPartialMemberAttribute)
                {
                    if (partialMembers == null)
                    {
                        partialMembers = new BasicList();
                    }
                    partialMembers.Add(typeAttribs[i]);
                }
            }
            MethodInfo[] callbacks = null;
            foreach (MemberInfo member in type.GetMembers(isEnum ? BindingFlags.Public | BindingFlags.Static
                : BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance))
            {
                if (member.DeclaringType != type)
                {
                    continue;
                }
                if (member.IsDefined(typeof(ProtoIgnoreAttribute), true))
                {
                    continue;
                }
                if (partialIgnores != null && partialIgnores.Contains(member.Name))
                {
                    continue;
                }

                switch (member.MemberType)
                {
                case MemberTypes.Property:
                case MemberTypes.Field:
                    ValueMember vm = ApplyDefaultBehaviour(isEnum, family, member, partialMembers);
                    if (vm != null)
                    {
                        Add(vm);
                    }
                    break;

                case MemberTypes.Method:
                    if (isEnum)
                    {
                        continue;
                    }
                    MethodInfo method        = (MethodInfo)member;
                    object[]   memberAttribs = Attribute.GetCustomAttributes(method);
                    if (memberAttribs != null && memberAttribs.Length > 0)
                    {
                        CheckForCallback(method, memberAttribs, "ProtoBuf.ProtoBeforeSerializationAttribute", ref callbacks, 0);
                        CheckForCallback(method, memberAttribs, "ProtoBuf.ProtoAfterSerializationAttribute", ref callbacks, 1);
                        CheckForCallback(method, memberAttribs, "ProtoBuf.ProtoBeforeDeserializationAttribute", ref callbacks, 2);
                        CheckForCallback(method, memberAttribs, "ProtoBuf.ProtoAfterDeserializationAttribute", ref callbacks, 3);
                        CheckForCallback(method, memberAttribs, "System.Runtime.Serialization.OnSerializingAttribute", ref callbacks, 4);
                        CheckForCallback(method, memberAttribs, "System.Runtime.Serialization.OnSerializedAttribute", ref callbacks, 5);
                        CheckForCallback(method, memberAttribs, "System.Runtime.Serialization.OnDeserializingAttribute", ref callbacks, 6);
                        CheckForCallback(method, memberAttribs, "System.Runtime.Serialization.OnDeserializedAttribute", ref callbacks, 7);
                    }
                    break;
                }
            }
            if (callbacks != null)
            {
                SetCallbacks(callbacks[0] ?? callbacks[4], callbacks[1] ?? callbacks[5],
                             callbacks[2] ?? callbacks[6], callbacks[3] ?? callbacks[7]);
            }
        }
        private ValueMember ApplyDefaultBehaviour(bool isEnum, AttributeFamily family, MemberInfo member, BasicList partialMembers)
        {
            if (member == null || (family == AttributeFamily.None && !isEnum)) return null; // nix
            Type effectiveType;
            switch (member.MemberType)
            {
                case MemberTypes.Field:
                    effectiveType = ((FieldInfo)member).FieldType; break;
                case MemberTypes.Property:
                    effectiveType = ((PropertyInfo)member).PropertyType; break;
                default:
                    return null; // nothing doing
            }

            int fieldNumber = 0;
            bool isPacked = false;
            string name = null;
            bool isRequired = false;
            Type itemType = null;
            Type defaultType = null;
            ResolveListTypes(effectiveType, ref itemType, ref defaultType);
            object[] attribs = member.GetCustomAttributes(true);
            Attribute attrib;
            DataFormat dataFormat = DataFormat.Default;
            bool ignore = false;
            object defaultValue = null;
            // implicit zero default
            switch (Type.GetTypeCode(effectiveType))
            {
                case TypeCode.Boolean: defaultValue = false; break;
                case TypeCode.Decimal: defaultValue = (decimal)0; break;
                case TypeCode.Single: defaultValue = (float)0; break;
                case TypeCode.Double: defaultValue = (double)0; break;
                case TypeCode.Byte: defaultValue = (byte)0;  break;
                case TypeCode.Char: defaultValue = (char)0; break;
                case TypeCode.Int16: defaultValue = (short)0; break;
                case TypeCode.Int32: defaultValue = (int)0; break;
                case TypeCode.Int64: defaultValue = (long)0; break;
                case TypeCode.SByte: defaultValue = (sbyte)0; break;
                case TypeCode.UInt16: defaultValue = (ushort)0; break;
                case TypeCode.UInt32: defaultValue = (uint)0; break;
                case TypeCode.UInt64: defaultValue = (ulong)0; break;
                default:
                    if (effectiveType == typeof(TimeSpan)) defaultValue = TimeSpan.Zero;
                    if (effectiveType == typeof(Guid)) defaultValue = Guid.Empty;
                    break;
            }
            bool done = false;
            if (isEnum)
            {
                attrib = GetAttribute(attribs, "ProtoBuf.ProtoIgnoreAttribute");
                if (attrib != null)
                {
                    ignore = true;
                }
                else
                {
                    attrib = GetAttribute(attribs, "ProtoBuf.ProtoEnumAttribute");
                    fieldNumber = Convert.ToInt32(((FieldInfo)member).GetValue(null));
                    if (attrib != null)
                    {
                        GetFieldName(ref name, attrib, "Name");
                        if ((bool)attrib.GetType().GetMethod("HasValue").Invoke(attrib, null))
                        {
                            fieldNumber = (int) GetMemberValue(attrib, "Value");
                        }
                    }
                        
                }
                done = true;
            }
            if (!ignore && !done) // always consider ProtoMember 
            {
                attrib = GetAttribute(attribs, "ProtoBuf.ProtoMemberAttribute");
                GetIgnore(ref ignore, attrib, attribs, "ProtoBuf.ProtoIgnoreAttribute");
                if (!ignore)
                {
                    GetFieldNumber(ref fieldNumber, attrib, "Tag");
                    GetFieldName(ref name, attrib, "Name");
                    GetFieldBoolean(ref isRequired, attrib, "IsRequired");
                    GetFieldBoolean(ref isPacked, attrib, "IsPacked");
                    GetDataFormat(ref dataFormat, attrib, "DataFormat");
                    done = fieldNumber > 0;
                }

                if (!done && partialMembers != null)
                {
                    foreach (ProtoPartialMemberAttribute ppma in partialMembers)
                    {
                        if (ppma.MemberName == member.Name)
                        {
                            GetFieldNumber(ref fieldNumber, ppma, "Tag");
                            GetFieldName(ref name, ppma, "Name");
                            GetFieldBoolean(ref isRequired, ppma, "IsRequired");
                            GetFieldBoolean(ref isPacked, ppma, "IsPacked");
                            GetDataFormat(ref dataFormat, ppma, "DataFormat");
                            if (done = fieldNumber > 0) break;                            
                        }
                    }
                }
            }
            if (!ignore && !done && HasFamily(family, AttributeFamily.DataContractSerialier))
            {
                attrib = GetAttribute(attribs, "System.Runtime.Serialization.DataMemberAttribute");
                GetFieldNumber(ref fieldNumber, attrib, "Order");
                GetFieldName(ref name, attrib, "Name");
                GetFieldBoolean(ref isRequired, attrib, "IsRequired");
                done = fieldNumber > 0;
            }
            if (!ignore && !done && HasFamily(family, AttributeFamily.XmlSerializer))
            {
                attrib = GetAttribute(attribs, "System.Xml.Serialization.XmlElementAttribute");
                GetIgnore(ref ignore, attrib, attribs, "System.Xml.Serialization.XmlIgnoreAttribute");
                if (!ignore)
                {
                    GetFieldNumber(ref fieldNumber, attrib, "Order");
                    GetFieldName(ref name, attrib, "ElementName");
                }
                attrib = GetAttribute(attribs, "System.Xml.Serialization.XmlArrayAttribute");
                GetIgnore(ref ignore, attrib, attribs, "ProtoBuf.XmlIgnoreAttribute");
                if (!ignore)
                {
                    GetFieldNumber(ref fieldNumber, attrib, "Order");
                    GetFieldName(ref name, attrib, "ElementName");
                }
                done = fieldNumber > 0;
            }
            if (!ignore && (attrib = GetAttribute(attribs, "System.ComponentModel.DefaultValueAttribute")) != null)
            {
                defaultValue = GetMemberValue(attrib, "Value");
            }
            ValueMember vm = ((isEnum || fieldNumber > 0) && !ignore)
                ? new ValueMember(model, type, fieldNumber, member, effectiveType, itemType, defaultType, dataFormat, defaultValue)
                    : null;
            if (vm != null)
            {
                PropertyInfo prop = type.GetProperty(member.Name + "Specified", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public,
                    null, typeof(bool), Helpers.EmptyTypes, null);
                if (prop != null)
                {
                    vm.SetSpecified(prop.GetGetMethod(true), prop.GetSetMethod(true));
                }
                else
                {
                    MethodInfo method = type.GetMethod("ShouldSerialize" + member.Name, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public,
                        null, Helpers.EmptyTypes, null);
                    if (method != null && method.ReturnType == typeof(bool))
                    {
                        vm.SetSpecified(method, null);
                    }
                }
                if(!Helpers.IsNullOrEmpty(name)) vm.SetName(name);
                vm.IsPacked = isPacked;
                vm.IsRequired = isRequired;
            }
            return vm;
        }
 private static bool HasFamily(AttributeFamily value, AttributeFamily required)
 {
     return (value & required) == required;
 }
Exemple #8
0
        private static ProtoMemberAttribute NormalizeProtoMember(MemberInfo member, AttributeFamily family, bool forced, bool isEnum, BasicList partialMembers, int dataMemberOffset, bool inferByTagName)
        {
            if (member == null || (family == AttributeFamily.None && !isEnum)) return null; // nix
            int fieldNumber = int.MinValue, minAcceptFieldNumber = inferByTagName ? -1 : 1;
            string name = null;
            bool isPacked = false, ignore = false, done = false, isRequired = false, asReference = false, dynamicType = false, tagIsPinned = false, overwriteList = false;
            DataFormat dataFormat = DataFormat.Default;
            if (isEnum) forced = true;
            object[] attribs = member.GetCustomAttributes(true);
            Attribute attrib;

            if (isEnum)
            {
                attrib = GetAttribute(attribs, "ProtoBuf.ProtoIgnoreAttribute");
                if (attrib != null)
                {
                    ignore = true;
                }
                else
                {
                    attrib = GetAttribute(attribs, "ProtoBuf.ProtoEnumAttribute");
                    fieldNumber = Convert.ToInt32(((FieldInfo)member).GetValue(null));
                    if (attrib != null)
                    {
                        GetFieldName(ref name, attrib, "Name");
                        if ((bool)attrib.GetType().GetMethod("HasValue").Invoke(attrib, null))
                        {
                            fieldNumber = (int)GetMemberValue(attrib, "Value");
                        }
                    }

                }
                done = true;
            }

            if (!ignore && !done) // always consider ProtoMember
            {
                attrib = GetAttribute(attribs, "ProtoBuf.ProtoMemberAttribute");
                GetIgnore(ref ignore, attrib, attribs, "ProtoBuf.ProtoIgnoreAttribute");
                if (!ignore && attrib != null)
                {
                    GetFieldNumber(ref fieldNumber, attrib, "Tag");
                    GetFieldName(ref name, attrib, "Name");
                    GetFieldBoolean(ref isRequired, attrib, "IsRequired");
                    GetFieldBoolean(ref isPacked, attrib, "IsPacked");
                    GetFieldBoolean(ref overwriteList, attrib, "OverwriteList");
                    GetDataFormat(ref dataFormat, attrib, "DataFormat");
                    GetFieldBoolean(ref asReference, attrib, "AsReference");
                    GetFieldBoolean(ref dynamicType, attrib, "DynamicType");
                    done = tagIsPinned = fieldNumber > 0; // note minAcceptFieldNumber only applies to non-proto
                }

                if (!done && partialMembers != null)
                {
                    foreach (ProtoPartialMemberAttribute ppma in partialMembers)
                    {
                        if (ppma.MemberName == member.Name)
                        {
                            GetFieldNumber(ref fieldNumber, ppma, "Tag");
                            GetFieldName(ref name, ppma, "Name");
                            GetFieldBoolean(ref isRequired, ppma, "IsRequired");
                            GetFieldBoolean(ref isPacked, ppma, "IsPacked");
                            GetFieldBoolean(ref overwriteList, attrib, "OverwriteList");
                            GetDataFormat(ref dataFormat, ppma, "DataFormat");
                            GetFieldBoolean(ref asReference, ppma, "AsReference");
                            GetFieldBoolean(ref dynamicType, ppma, "DynamicType");
                            if (done = tagIsPinned = fieldNumber > 0) break; // note minAcceptFieldNumber only applies to non-proto
                        }
                    }
                }
            }

            if (!ignore && !done && HasFamily(family, AttributeFamily.DataContractSerialier))
            {
                attrib = GetAttribute(attribs, "System.Runtime.Serialization.DataMemberAttribute");
                if (attrib != null)
                {
                    GetFieldNumber(ref fieldNumber, attrib, "Order");
                    GetFieldName(ref name, attrib, "Name");
                    GetFieldBoolean(ref isRequired, attrib, "IsRequired");
                    done = fieldNumber >= minAcceptFieldNumber;
                    if (done) fieldNumber += dataMemberOffset; // dataMemberOffset only applies to DCS flags, to allow us to "bump" WCF by a notch
                }
            }
            if (!ignore && !done && HasFamily(family, AttributeFamily.XmlSerializer))
            {
                attrib = GetAttribute(attribs, "System.Xml.Serialization.XmlElementAttribute");
                if(attrib == null) attrib = GetAttribute(attribs, "System.Xml.Serialization.XmlArrayAttribute");
                GetIgnore(ref ignore, attrib, attribs, "System.Xml.Serialization.XmlIgnoreAttribute");
                if (attrib != null && !ignore)
                {
                    GetFieldNumber(ref fieldNumber, attrib, "Order");
                    GetFieldName(ref name, attrib, "ElementName");
                    done = fieldNumber >= minAcceptFieldNumber;
                }
            }
            if (!ignore && !done)
            {
                if (GetAttribute(attribs, "System.NonSerializedAttribute") != null) ignore = true;
            }
            if (ignore || (fieldNumber < minAcceptFieldNumber && !forced)) return null;
            ProtoMemberAttribute result = new ProtoMemberAttribute(fieldNumber, forced || inferByTagName);
            result.AsReference = asReference;
            result.DataFormat = dataFormat;
            result.DynamicType = dynamicType;
            result.IsPacked = isPacked;
            result.OverwriteList = overwriteList;
            result.IsRequired = isRequired;
            result.Name = Helpers.IsNullOrEmpty(name) ? member.Name : name;
            result.Member = member;
            result.TagIsPinned = tagIsPinned;
            return result;
        }
Exemple #9
0
        private static ProtoMemberAttribute NormalizeProtoMember(MemberInfo member, AttributeFamily family, bool forced, bool isEnum, BasicList partialMembers, int dataMemberOffset, bool inferByTagName)
        {
            if (member == null || (family == AttributeFamily.None && !isEnum))
            {
                return(null);                                                               // nix
            }
            int        fieldNumber = int.MinValue, minAcceptFieldNumber = inferByTagName ? -1 : 1;
            string     name = null;
            bool       isPacked = false, ignore = false, done = false, isRequired = false, asReference = false, dynamicType = false, tagIsPinned = false, overwriteList = false;
            DataFormat dataFormat = DataFormat.Default;

            if (isEnum)
            {
                forced = true;
            }
            object[]  attribs = member.GetCustomAttributes(true);
            Attribute attrib;

            if (isEnum)
            {
                attrib = GetAttribute(attribs, "ProtoBuf.ProtoIgnoreAttribute");
                if (attrib != null)
                {
                    ignore = true;
                }
                else
                {
                    attrib      = GetAttribute(attribs, "ProtoBuf.ProtoEnumAttribute");
                    fieldNumber = Convert.ToInt32(((FieldInfo)member).GetValue(null));
                    if (attrib != null)
                    {
                        GetFieldName(ref name, attrib, "Name");
                        if ((bool)attrib.GetType().GetMethod("HasValue").Invoke(attrib, null))
                        {
                            fieldNumber = (int)GetMemberValue(attrib, "Value");
                        }
                    }
                }
                done = true;
            }

            if (!ignore && !done) // always consider ProtoMember
            {
                attrib = GetAttribute(attribs, "ProtoBuf.ProtoMemberAttribute");
                GetIgnore(ref ignore, attrib, attribs, "ProtoBuf.ProtoIgnoreAttribute");
                if (!ignore && attrib != null)
                {
                    GetFieldNumber(ref fieldNumber, attrib, "Tag");
                    GetFieldName(ref name, attrib, "Name");
                    GetFieldBoolean(ref isRequired, attrib, "IsRequired");
                    GetFieldBoolean(ref isPacked, attrib, "IsPacked");
                    GetFieldBoolean(ref overwriteList, attrib, "OverwriteList");
                    GetDataFormat(ref dataFormat, attrib, "DataFormat");
                    GetFieldBoolean(ref asReference, attrib, "AsReference");
                    GetFieldBoolean(ref dynamicType, attrib, "DynamicType");
                    done = tagIsPinned = fieldNumber > 0; // note minAcceptFieldNumber only applies to non-proto
                }

                if (!done && partialMembers != null)
                {
                    foreach (ProtoPartialMemberAttribute ppma in partialMembers)
                    {
                        if (ppma.MemberName == member.Name)
                        {
                            GetFieldNumber(ref fieldNumber, ppma, "Tag");
                            GetFieldName(ref name, ppma, "Name");
                            GetFieldBoolean(ref isRequired, ppma, "IsRequired");
                            GetFieldBoolean(ref isPacked, ppma, "IsPacked");
                            GetFieldBoolean(ref overwriteList, attrib, "OverwriteList");
                            GetDataFormat(ref dataFormat, ppma, "DataFormat");
                            GetFieldBoolean(ref asReference, ppma, "AsReference");
                            GetFieldBoolean(ref dynamicType, ppma, "DynamicType");
                            if (done = tagIsPinned = fieldNumber > 0)
                            {
                                break;                                       // note minAcceptFieldNumber only applies to non-proto
                            }
                        }
                    }
                }
            }

            if (!ignore && !done && HasFamily(family, AttributeFamily.DataContractSerialier))
            {
                attrib = GetAttribute(attribs, "System.Runtime.Serialization.DataMemberAttribute");
                if (attrib != null)
                {
                    GetFieldNumber(ref fieldNumber, attrib, "Order");
                    GetFieldName(ref name, attrib, "Name");
                    GetFieldBoolean(ref isRequired, attrib, "IsRequired");
                    done = fieldNumber >= minAcceptFieldNumber;
                    if (done)
                    {
                        fieldNumber += dataMemberOffset;       // dataMemberOffset only applies to DCS flags, to allow us to "bump" WCF by a notch
                    }
                }
            }
            if (!ignore && !done && HasFamily(family, AttributeFamily.XmlSerializer))
            {
                attrib = GetAttribute(attribs, "System.Xml.Serialization.XmlElementAttribute");
                if (attrib == null)
                {
                    attrib = GetAttribute(attribs, "System.Xml.Serialization.XmlArrayAttribute");
                }
                GetIgnore(ref ignore, attrib, attribs, "System.Xml.Serialization.XmlIgnoreAttribute");
                if (attrib != null && !ignore)
                {
                    GetFieldNumber(ref fieldNumber, attrib, "Order");
                    GetFieldName(ref name, attrib, "ElementName");
                    done = fieldNumber >= minAcceptFieldNumber;
                }
            }
            if (!ignore && !done)
            {
                if (GetAttribute(attribs, "System.NonSerializedAttribute") != null)
                {
                    ignore = true;
                }
            }
            if (ignore || (fieldNumber < minAcceptFieldNumber && !forced))
            {
                return(null);
            }
            ProtoMemberAttribute result = new ProtoMemberAttribute(fieldNumber, forced || inferByTagName);

            result.AsReference   = asReference;
            result.DataFormat    = dataFormat;
            result.DynamicType   = dynamicType;
            result.IsPacked      = isPacked;
            result.OverwriteList = overwriteList;
            result.IsRequired    = isRequired;
            result.Name          = Helpers.IsNullOrEmpty(name) ? member.Name : name;
            result.Member        = member;
            result.TagIsPinned   = tagIsPinned;
            return(result);
        }
Exemple #10
0
        internal void ApplyDefaultBehaviour()
        {
            if (type.BaseType != null && model.FindWithoutAdd(type.BaseType) == null &&
                GetContractFamily(type.BaseType, null) != MetaType.AttributeFamily.None)
            {
                model.FindOrAddAuto(type.BaseType, true, false, false);
            }

            object[]        typeAttribs = type.GetCustomAttributes(true);
            AttributeFamily family      = GetContractFamily(type, typeAttribs);
            bool            isEnum      = type.IsEnum;

            if (family == AttributeFamily.None && !isEnum)
            {
                return;                                            // and you'd like me to do what, exactly?
            }
            BasicList      partialIgnores = null, partialMembers = null;
            int            dataMemberOffset = 0, implicitFirstTag = 1;
            bool           inferTagByName = model.InferTagFromNameDefault;
            ImplicitFields implicitMode   = ImplicitFields.None;

            for (int i = 0; i < typeAttribs.Length; i++)
            {
                Attribute item = (Attribute)typeAttribs[i];
                if (!isEnum && item is ProtoIncludeAttribute)
                {
                    ProtoIncludeAttribute pia = (ProtoIncludeAttribute)item;
                    AddSubType(pia.Tag, pia.KnownType);
                }
                if (item is ProtoPartialIgnoreAttribute)
                {
                    if (partialIgnores == null)
                    {
                        partialIgnores = new BasicList();
                    }
                    partialIgnores.Add(((ProtoPartialIgnoreAttribute)item).MemberName);
                }
                if (!isEnum && item is ProtoPartialMemberAttribute)
                {
                    if (partialMembers == null)
                    {
                        partialMembers = new BasicList();
                    }
                    partialMembers.Add(item);
                }
                if (!isEnum && item is ProtoContractAttribute)
                {
                    ProtoContractAttribute pca = (ProtoContractAttribute)item;
                    dataMemberOffset = pca.DataMemberOffset;
                    if (pca.InferTagFromNameHasValue)
                    {
                        inferTagByName = pca.InferTagFromName;
                    }
                    implicitMode   = pca.ImplicitFields;
                    UseConstructor = !pca.SkipConstructor;
                    if (pca.ImplicitFirstTag > 0)
                    {
                        implicitFirstTag = pca.ImplicitFirstTag;
                    }
                }
            }
            if (implicitMode != ImplicitFields.None)
            {
                family &= AttributeFamily.ProtoBuf; // with implicit fields, **only** proto attributes are important
            }
            MethodInfo[] callbacks = null;

            BasicList members = new BasicList();

            foreach (MemberInfo member in type.GetMembers(isEnum ? BindingFlags.Public | BindingFlags.Static
                : BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance))
            {
                if (member.DeclaringType != type)
                {
                    continue;
                }
                if (member.IsDefined(typeof(ProtoIgnoreAttribute), true))
                {
                    continue;
                }
                if (partialIgnores != null && partialIgnores.Contains(member.Name))
                {
                    continue;
                }

                bool forced = false, isPublic, isField;
                Type effectiveType;
                switch (member.MemberType)
                {
                case MemberTypes.Property:
                    PropertyInfo property = (PropertyInfo)member;
                    effectiveType = property.PropertyType;
                    isPublic      = property.GetGetMethod(false) != null;
                    isField       = false;
                    goto ProcessMember;

                case MemberTypes.Field:
                    FieldInfo field = (FieldInfo)member;
                    effectiveType = field.FieldType;
                    isPublic      = field.IsPublic;
                    isField       = true;
ProcessMember:
                    switch (implicitMode)
                    {
                    case ImplicitFields.AllFields:
                        if (isField)
                        {
                            forced = true;
                        }
                        break;

                    case ImplicitFields.AllPublic:
                        if (isPublic)
                        {
                            forced = true;
                        }
                        break;
                    }
                    if (effectiveType.IsSubclassOf(typeof(Delegate)))
                    {
                        continue;                                                   // we just don't like delegate types ;p
                    }
                    ProtoMemberAttribute normalizedAttribute = NormalizeProtoMember(member, family, forced, isEnum, partialMembers, dataMemberOffset, inferTagByName);
                    if (normalizedAttribute != null)
                    {
                        members.Add(normalizedAttribute);
                    }
                    break;

                case MemberTypes.Method:
                    if (isEnum)
                    {
                        continue;
                    }
                    MethodInfo method        = (MethodInfo)member;
                    object[]   memberAttribs = Attribute.GetCustomAttributes(method);
                    if (memberAttribs != null && memberAttribs.Length > 0)
                    {
                        CheckForCallback(method, memberAttribs, "ProtoBuf.ProtoBeforeSerializationAttribute", ref callbacks, 0);
                        CheckForCallback(method, memberAttribs, "ProtoBuf.ProtoAfterSerializationAttribute", ref callbacks, 1);
                        CheckForCallback(method, memberAttribs, "ProtoBuf.ProtoBeforeDeserializationAttribute", ref callbacks, 2);
                        CheckForCallback(method, memberAttribs, "ProtoBuf.ProtoAfterDeserializationAttribute", ref callbacks, 3);
                        CheckForCallback(method, memberAttribs, "System.Runtime.Serialization.OnSerializingAttribute", ref callbacks, 4);
                        CheckForCallback(method, memberAttribs, "System.Runtime.Serialization.OnSerializedAttribute", ref callbacks, 5);
                        CheckForCallback(method, memberAttribs, "System.Runtime.Serialization.OnDeserializingAttribute", ref callbacks, 6);
                        CheckForCallback(method, memberAttribs, "System.Runtime.Serialization.OnDeserializedAttribute", ref callbacks, 7);
                    }
                    break;
                }
            }
            ProtoMemberAttribute[] arr = new ProtoMemberAttribute[members.Count];
            members.CopyTo(arr, 0);

            if (inferTagByName || implicitMode != ImplicitFields.None)
            {
                Array.Sort(arr);
                int nextTag = implicitFirstTag;
                foreach (ProtoMemberAttribute normalizedAttribute in arr)
                {
                    if (!normalizedAttribute.TagIsPinned) // if ProtoMember etc sets a tag, we'll trust it
                    {
                        normalizedAttribute.Rebase(nextTag++);
                    }
                }
            }

            foreach (ProtoMemberAttribute normalizedAttribute in arr)
            {
                ValueMember vm = ApplyDefaultBehaviour(isEnum, normalizedAttribute);
                if (vm != null)
                {
                    Add(vm);
                }
            }

            if (callbacks != null)
            {
                SetCallbacks(Coalesce(callbacks, 0, 4), Coalesce(callbacks, 1, 5),
                             Coalesce(callbacks, 2, 6), Coalesce(callbacks, 3, 7));
            }
        }
        protected virtual AttributeFamily GetContractFamily(Type type, AttributeMap[] attributes)
        {
            if (Helpers.GetNullableUnderlyingType(type) != null)
            {
                return(AttributeFamily.None);
            }
            if (!Helpers.IsEnum(type) && Helpers.GetTypeCode(type) != ProtoTypeCode.Unknown)
            {
                return(AttributeFamily.None);                                                                             // known types are not contracts
            }
            AttributeFamily family = AttributeFamily.None;
            bool            isList = type.IsArray || TypeModel.GetListItemType(Model, type) != null;

            for (int i = 0; i < attributes.Length; i++)
            {
                switch (attributes[i].AttributeType.FullName)
                {
                case "ProtoBuf.ProtoContractAttribute":
                {
                    if (CanUse(AttributeType.ProtoBuf))
                    {
                        bool tmp = false;
                        GetFieldBoolean(ref tmp, attributes[i], "UseProtoMembersOnly");
                        if (tmp)
                        {
                            return(AttributeFamily.ProtoBuf);
                        }
                        family |= AttributeFamily.ProtoBuf;
                    }
                }
                break;

                case "AqlaSerializer.SerializableTypeAttribute":
                {
                    if (CanUse(AttributeType.Aqla))
                    {
                        bool tmp = false;
                        GetFieldBoolean(ref tmp, attributes[i], "UseAqlaMembersOnly");
                        if (tmp)
                        {
                            return(AttributeFamily.Aqla);
                        }
                        family |= AttributeFamily.Aqla;
                    }
                }
                break;

                case "System.Xml.Serialization.XmlTypeAttribute":
                    if (CanUse(AttributeType.Xml))
                    {
                        family |= AttributeFamily.XmlSerializer;
                    }
                    break;

                case "System.Runtime.Serialization.DataContractAttribute":
                    if (CanUse(AttributeType.DataContract))
                    {
                        family |= AttributeFamily.DataContractSerialier;
                    }
                    break;
                }
            }

            if (family == AttributeFamily.None)
            {
                if (Helpers.IsEnum(type))
                {
                    // it's not required to specify attributes on enum

                    if (CanUse(AttributeType.ProtoBuf) && !CanUse(AttributeType.Aqla))
                    {
                        family |= AttributeFamily.ProtoBuf;
                    }
                    else
                    {
                        family |= AttributeFamily.Aqla;
                    }
                }
                else if (!DisableAutoTuples)
                {
                    // check for obvious tuples

                    // AqlaSerializer: as-reference is
                    // a default behavior for classes
                    // and if type attribute is not set
                    // such behavior should apply.
                    // This will not be called if
                    // there are any attributes!

                    MemberInfo[] mapping;
                    if (MetaType.ResolveTupleConstructor(type, out mapping) != null)
                    {
                        family |= AttributeFamily.AutoTuple;
                    }
                }
                if (family == AttributeFamily.None && ImplicitFallbackMode != ImplicitFieldsMode.None && !isList)
                {
                    if (Helpers.GetTypeCode(type) == ProtoTypeCode.Unknown &&
                        type != Model.MapType(typeof(object)) &&
                        type != Model.MapType(typeof(ValueType)))
                    {
                        family = AttributeFamily.ImplicitFallback;
                    }
                }
                if (family == AttributeFamily.None && CanUse(AttributeType.SystemSerializable) && !isList)
                {
                    for (int i = 0; i < attributes.Length; i++)
                    {
                        switch (attributes[i].AttributeType.FullName)
                        {
                        case "System.SerializableAttribute":
                            family |= AttributeFamily.SystemSerializable;
                            break;
                        }
                    }
                }
            }
            return(family);
        }