void parse() { MemberInfo[] mbs = type.GetMembers(); foreach (MemberInfo mb in mbs) { PBMember pbm = new PBMember(); //获取所有ProtoMemberAttribute属性(PB字段) ProtoMemberAttribute attr = Attribute.GetCustomAttribute(mb, typeof(ProtoMemberAttribute)) as ProtoMemberAttribute; if (attr != null) { pbm.name = attr.Name; pbm.tag = attr.Tag; pbm.datafmt = attr.DataFormat; DefaultValueAttribute dva = Attribute.GetCustomAttribute(mb, typeof(DefaultValueAttribute)) as DefaultValueAttribute; if (dva != null) { pbm.defaultVaule = dva.Value; } pbm.isRequire = attr.IsRequired; pbm.isPacked = attr.IsPacked; pbm.isOverrideList = attr.OverwriteList; } ProtoEnumAttribute pea = Attribute.GetCustomAttribute(mb, typeof(ProtoEnumAttribute)) as ProtoEnumAttribute; if (pea != null) { pbm.name = pea.Name; pbm.defaultVaule = pea.Value; } if (attr == null && pea == null) { continue; } Type memberType = null; switch (mb.MemberType) { case MemberTypes.Field: memberType = ((FieldInfo)mb).FieldType; break; case MemberTypes.Property: memberType = ((PropertyInfo)mb).PropertyType; break; default: throw new NotSupportedException(mb.MemberType.ToString()); } pbm.valueType = memberType; addMember(pbm); } }
public ProtoJsonPropertyAccessor(PropertyInfo p) : base(p) { TypeInfo ti = p.PropertyType.GetTypeInfo(); IsList = p.PropertyType != typeof(string) && typeof(IEnumerable).GetTypeInfo().IsAssignableFrom(ti); ProtoMemberAttribute attribute = p.GetCustomAttribute <ProtoMemberAttribute>(); IsOptional = attribute.Optional; Position = attribute.Position; if (IsList) { UnderlyingType = ti.GenericTypeArguments.FirstOrDefault(); ti = UnderlyingType.GetTypeInfo(); } IsProtoContract = ti.IsDefined(typeof(ProtoContractAttribute), false); IsEnum = ti.IsEnum; }
public ProtoJsonPropertyAccessor(PropertyInfo p) : base(p) { // after base is initialized GenericType contains TypeInfo ti = GenericType.GetTypeInfo(); ProtoMemberAttribute attribute = p.GetCustomAttribute <ProtoMemberAttribute>(); if (attribute != null) { IsOptional = attribute.Optional; Position = attribute.Position; } ProtoJsonType = AttributeTypeEnum.Value; if (IsEnum) { ProtoJsonType = AttributeTypeEnum.Enum; } else if (ti.IsDefined(typeof(ProtoContractAttribute), false)) { ProtoJsonType = AttributeTypeEnum.ProtoContract; } }
private static string GenDeserializeScript(Type type) { string deserCode = DESERIALIZE_FUNC_TEMP; deserCode = deserCode.Replace("$CreateInstance$", type.IsAbstract ? "" : INSTANCE_TEMP); deserCode = deserCode.Replace("$Type$", GetTypeFullName(type)); StringBuilder stringBuilder = new StringBuilder(); /* 多态 */ ProtoIncludeAttribute[] includes = type.GetAttributes <ProtoIncludeAttribute>(); foreach (var include in includes) { string includeCode = DYNAMIC_TEMP; includeCode = includeCode.Replace("$CaseNum$", include.Tag.ToString()); includeCode = includeCode.Replace("$DerivedName$", include.KnownType.Name); includeCode = includeCode.Replace("$DerivedType$", GetTypeFullName(include.KnownType)); stringBuilder.Append(includeCode); } /* 成员 */ MemberInfo[] memberInfos = type.GetMembers(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public); foreach (MemberInfo memberInfo in memberInfos) { if (memberInfo.DeclaringType != type) { continue; } if (memberInfo.IsDefined(typeof(ProtoIgnoreAttribute), true)) { continue; } ProtoMemberAttribute memberAttr = memberInfo.GetAttribute <ProtoMemberAttribute>(); if (memberAttr == null) { continue; } PropertyInfo propertyInfo; FieldInfo fieldInfo; Type memberType = null; if ((propertyInfo = memberInfo as PropertyInfo) != null) { memberType = propertyInfo.PropertyType; } else if ((fieldInfo = memberInfo as FieldInfo) != null) { memberType = fieldInfo.FieldType; } if (memberType == null) { continue; } string caseCode = CASE_TEMP; caseCode = caseCode.Replace("$CaseNum$", memberAttr.Tag.ToString()); ProtoSupportSetAttribute supportSetAttribute = memberInfo.GetAttribute <ProtoSupportSetAttribute>(); if (supportSetAttribute != null) { caseCode = caseCode.Replace("$WriteField$", WRITE_BYFUN_TEMP); caseCode = caseCode.Replace("$Value$", supportSetAttribute.FunctionParam); caseCode = caseCode.Replace("$MemberName$", supportSetAttribute.FunctionName); caseCode = caseCode.Replace("$Param$", VALUE_TEMP); caseCode = caseCode.Replace("$ValueType$", GetTypeFullName(memberType)); } else { caseCode = caseCode.Replace("$WriteField$", WRITE_BYFIELD_TEMP); caseCode = caseCode.Replace("$Value$", VALUE_TEMP); caseCode = caseCode.Replace("$MemberName$", memberInfo.Name); caseCode = caseCode.Replace("$ValueType$", GetTypeFullName(memberType)); } string handleCode = GenTypeReadCode(memberInfo, memberType, memberInfo.Name, memberAttr.Tag); if (!string.IsNullOrEmpty(handleCode)) { if (!type.IsValueType && !type.IsAbstract) { handleCode = CREATE_OBJ + handleCode; handleCode = handleCode.Replace("$ObjValue$", GetTypeFullName(type)); } stringBuilder.Append(caseCode.Replace("$CaseHandle$", handleCode)); } } return(deserCode.Replace("$CaseContent$", stringBuilder.ToString())); }
private ValueMember ApplyDefaultBehaviour(bool isEnum, ProtoMemberAttribute normalizedAttribute) { MemberInfo member; if (normalizedAttribute == null || (member = normalizedAttribute.Member) == null) 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 } Type itemType = null; Type defaultType = null; ResolveListTypes(effectiveType, ref itemType, ref defaultType); object[] attribs = member.GetCustomAttributes(true); Attribute attrib; object defaultValue = null; // implicit zero default if (model.UseImplicitZeroDefaults) { 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; } } if ((attrib = GetAttribute(attribs, "System.ComponentModel.DefaultValueAttribute")) != null) { defaultValue = GetMemberValue(attrib, "Value"); } ValueMember vm = ((isEnum || normalizedAttribute.Tag > 0)) ? new ValueMember(model, type, normalizedAttribute.Tag, member, effectiveType, itemType, defaultType, normalizedAttribute.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(normalizedAttribute.Name)) vm.SetName(normalizedAttribute.Name); vm.IsPacked = normalizedAttribute.IsPacked; vm.IsRequired = normalizedAttribute.IsRequired; vm.OverwriteList = normalizedAttribute.OverwriteList; vm.AsReference = normalizedAttribute.AsReference; vm.DynamicType = normalizedAttribute.DynamicType; } return vm; }
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; }
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; Type knownType = pia.ResolveKnownType(type.Assembly); if (knownType == null) { throw new InvalidOperationException("Unable to resolve sub-type: " + pia.KnownTypeName); } AddSubType(pia.Tag, 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)); } }
private ValueMember ApplyDefaultBehaviour(bool isEnum, ProtoMemberAttribute normalizedAttribute) { MemberInfo member; if (normalizedAttribute == null || (member = normalizedAttribute.Member) == null) { 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 } Type itemType = null; Type defaultType = null; ResolveListTypes(effectiveType, ref itemType, ref defaultType); object[] attribs = member.GetCustomAttributes(true); Attribute attrib; 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; } if ((attrib = GetAttribute(attribs, "System.ComponentModel.DefaultValueAttribute")) != null) { defaultValue = GetMemberValue(attrib, "Value"); } ValueMember vm = ((isEnum || normalizedAttribute.Tag > 0)) ? new ValueMember(model, type, normalizedAttribute.Tag, member, effectiveType, itemType, defaultType, normalizedAttribute.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(normalizedAttribute.Name)) { vm.SetName(normalizedAttribute.Name); } vm.IsPacked = normalizedAttribute.IsPacked; vm.IsRequired = normalizedAttribute.IsRequired; vm.OverwriteList = normalizedAttribute.OverwriteList; vm.AsReference = normalizedAttribute.AsReference; vm.DynamicType = normalizedAttribute.DynamicType; } return(vm); }
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); }
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)); } }
/// <summary> /// 增加一个类型,使protobuf支持该类型的父类(仅带有ProtoContract的父类)中所有需要序列化的属性 /// </summary> /// <param name="type">需要被支持继承的类</param> public static void AddType(Type type) { if (type == null) { return; } if (!type.IsDefined(type_proto_contract, false)) { return; } if (added_types.ContainsKey(type)) { return; } added_types.Add(type, (byte)0); Type bt = type; RuntimeTypeModel model = RuntimeTypeModel.Default; MemberInfo[] ms = bt.GetMembers(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); for (int i = 0, imax = ms.Length; i < imax; i++) { MemberInfo mi = ms[i]; if (!Attribute.IsDefined(mi, typeof(ProtoMemberAttribute))) { continue; } Type mt = null; switch (mi.MemberType) { case MemberTypes.Field: mt = (mi as FieldInfo).FieldType; break; case MemberTypes.Property: mt = (mi as PropertyInfo).PropertyType; break; } if (mt == null) { continue; } if (mt.IsGenericType) { Type[] gt = mt.GetGenericArguments(); for (int j = 0, jmax = gt.Length; j < jmax; j++) { AddType(gt[j]); } } if (mt.IsArray) { AddType(mt.GetElementType()); } AddType(mt); } while (true) { bt = bt.BaseType; if (bt == null || bt == type_obj) { break; } if (!bt.IsDefined(type_proto_contract, false)) { continue; } ms = bt.GetMembers(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly); for (int i = 0, imax = ms.Length; i < imax; i++) { MemberInfo mi = ms[i]; //if (mi.DeclaringType != bt) { continue; } ProtoMemberAttribute pm = Attribute.GetCustomAttribute(mi, typeof(ProtoMemberAttribute)) as ProtoMemberAttribute; if (pm == null) { continue; } try { model[type].Add(pm.Tag, mi.Name); } catch { } //UnityEngine.Debug.LogWarning(type + " " + pm.Tag + " " +mi.Name); } } }
public void FillFromAttribute(ProtoMemberAttribute pma) { Tag = pma.Tag; Options = pma.Options; }