AmqpContract IContractResolver.Resolve(Type type) { AmqpContractAttribute contractAttribute = type.GetCustomAttribute <AmqpContractAttribute>(false); if (contractAttribute == null) { foreach (MemberInfo memberInfo in type.GetMembers(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)) { AmqpMemberAttribute attribute = memberInfo.GetCustomAttribute <AmqpMemberAttribute>(true); if (attribute != null) { throw new AmqpException(ErrorCode.NotAllowed, Fx.Format("{0} has AmqpMemberAttribute members without AmqpContractAttribute on class", type.Name)); } } return(null); } if (contractAttribute.Encoding == EncodingType.SimpleMap && type.GetCustomAttribute <AmqpProvidesAttribute>(false) != null) { throw new AmqpException(ErrorCode.NotAllowed, Fx.Format("{0}: SimpleMap encoding does not include descriptors so it does not support AmqpProvidesAttribute.", type.Name)); } if (contractAttribute.Encoding == EncodingType.SimpleList && type.GetCustomAttribute <AmqpProvidesAttribute>(false) != null) { throw new AmqpException(ErrorCode.NotAllowed, Fx.Format("{0}: SimpleList encoding does not include descriptors so it does not support AmqpProvidesAttribute.", type.Name)); } AmqpContract baseContract = null; if (type.BaseType() != typeof(object)) { baseContract = ((IContractResolver)this).Resolve(type.BaseType()); if (baseContract != null && baseContract.Attribute.Encoding != contractAttribute.Encoding) { throw new AmqpException(ErrorCode.NotAllowed, Fx.Format("{0}.Encoding ({1}) is different from {2}.Encoding ({3})", type.Name, contractAttribute.Encoding, type.BaseType().Name, baseContract.Attribute.Encoding)); } } string descriptorName = contractAttribute.Name; ulong? descriptorCode = contractAttribute.InternalCode; if (descriptorName == null && descriptorCode == null) { descriptorName = type.FullName; } var memberList = new List <AmqpMember>(); int lastOrder = 0; if (baseContract != null) { for (int i = 0; i < baseContract.Members.Length; i++) { memberList.Add(baseContract.Members[i]); lastOrder = Math.Max(lastOrder, baseContract.Members[i].Order); } } lastOrder++; MethodInfo serializing = null; MethodInfo serialized = null; MethodInfo deserializing = null; MethodInfo deserialized = null; MemberInfo[] memberInfos = type.GetMembers(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); foreach (MemberInfo memberInfo in memberInfos) { if (memberInfo.DeclaringType != type) { continue; } if (memberInfo is FieldInfo || memberInfo is PropertyInfo) { AmqpMemberAttribute attribute = memberInfo.GetCustomAttribute <AmqpMemberAttribute>(true); if (attribute == null) { continue; } memberList.Add(new AmqpMember() { Attribute = attribute, Info = memberInfo, Order = attribute.InternalOrder ?? lastOrder++ }); } else if (memberInfo is MethodInfo) { if (memberInfo.GetCustomAttribute <OnSerializingAttribute>(false) != null) { serializing = (MethodInfo)memberInfo; } else if (memberInfo.GetCustomAttribute <OnSerializedAttribute>(false) != null) { serialized = (MethodInfo)memberInfo; } else if (memberInfo.GetCustomAttribute <OnDeserializingAttribute>(false) != null) { deserializing = (MethodInfo)memberInfo; } else if (memberInfo.GetCustomAttribute <OnDeserializedAttribute>(false) != null) { deserialized = (MethodInfo)memberInfo; } } } if (contractAttribute.Encoding == EncodingType.List) { memberList.Sort(MemberOrderComparer.Instance); int order = -1; foreach (AmqpMember member in memberList) { if (order > 0 && member.Order == order) { throw new AmqpException(ErrorCode.NotAllowed, Fx.Format("Duplicate Order {0} detected in {1}", order, type.Name)); } order = member.Order; } } List <Type> knownTypes = new List <Type>(); var providesAttributes = type.GetCustomAttributes <AmqpProvidesAttribute>(false); foreach (object o in providesAttributes) { AmqpProvidesAttribute knownAttribute = (AmqpProvidesAttribute)o; if (knownAttribute.Type.GetCustomAttribute <AmqpContractAttribute>(false) != null) { knownTypes.Add(knownAttribute.Type); } } var contract = new AmqpContract(type) { Attribute = contractAttribute, Members = memberList.ToArray(), Provides = knownTypes.ToArray(), Serializing = serializing, Serialized = serialized, Deserializing = deserializing, Deserialized = deserialized, BaseContract = baseContract }; this.OnResolved(contract); return(contract); }
SerializableType CompileType(Type type, bool describedOnly) { AmqpContractAttribute contractAttribute = type.GetCustomAttribute <AmqpContractAttribute>(false); if (contractAttribute == null) { if (describedOnly) { return(null); } else { return(CompileNonContractTypes(type)); } } SerializableType baseType = null; if (type.BaseType() != typeof(object)) { baseType = this.CompileType(type.BaseType(), true); if (baseType != null) { if (baseType.Encoding != contractAttribute.Encoding) { throw new SerializationException( Fx.Format("{0}.Encoding ({1}) is different from {2}.Encoding ({3})", type.Name, contractAttribute.Encoding, type.BaseType().Name, baseType.Encoding)); } baseType = this.typeCache.GetOrAdd(type.BaseType(), baseType); } } string descriptorName = contractAttribute.Name; ulong? descriptorCode = contractAttribute.InternalCode; if (descriptorName == null && descriptorCode == null) { descriptorName = type.FullName; } List <SerialiableMember> memberList = new List <SerialiableMember>(); if (baseType != null) { memberList.AddRange(baseType.Members); } int lastOrder = memberList.Count + 1; MemberInfo[] memberInfos = type.GetMembers(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); MethodAccessor[] serializationCallbacks = new MethodAccessor[SerializationCallback.Size]; foreach (MemberInfo memberInfo in memberInfos) { if (memberInfo.DeclaringType != type) { continue; } if (memberInfo is FieldInfo || memberInfo is PropertyInfo) { AmqpMemberAttribute attribute = memberInfo.GetCustomAttribute <AmqpMemberAttribute>(true); if (attribute == null) { continue; } SerialiableMember member = new SerialiableMember(); member.Name = attribute.Name ?? memberInfo.Name; member.Order = attribute.InternalOrder ?? lastOrder++; member.Accessor = MemberAccessor.Create(memberInfo, true); // This will recursively resolve member types Type memberType = memberInfo is FieldInfo ? ((FieldInfo)memberInfo).FieldType : ((PropertyInfo)memberInfo).PropertyType; member.Type = GetType(memberType); memberList.Add(member); } else if (memberInfo is MethodInfo) { MethodInfo methodInfo = (MethodInfo)memberInfo; MethodAccessor methodAccessor; if (this.TryCreateMethodAccessor <OnSerializingAttribute>(methodInfo, out methodAccessor)) { serializationCallbacks[SerializationCallback.OnSerializing] = methodAccessor; } else if (this.TryCreateMethodAccessor <OnSerializedAttribute>(methodInfo, out methodAccessor)) { serializationCallbacks[SerializationCallback.OnSerialized] = methodAccessor; } else if (this.TryCreateMethodAccessor <OnDeserializingAttribute>(methodInfo, out methodAccessor)) { serializationCallbacks[SerializationCallback.OnDeserializing] = methodAccessor; } else if (this.TryCreateMethodAccessor <OnDeserializedAttribute>(methodInfo, out methodAccessor)) { serializationCallbacks[SerializationCallback.OnDeserialized] = methodAccessor; } } } if (contractAttribute.Encoding == EncodingType.List) { memberList.Sort(MemberOrderComparer.Instance); int order = -1; foreach (SerialiableMember member in memberList) { if (order > 0 && member.Order == order) { throw new SerializationException(Fx.Format("Duplicate Order {0} detected in {1}", order, type.Name)); } order = member.Order; } } SerialiableMember[] members = memberList.ToArray(); if (contractAttribute.Encoding == EncodingType.SimpleMap && type.GetCustomAttribute <AmqpProvidesAttribute>(false) != null) { throw new SerializationException( Fx.Format("{0}: SimpleMap encoding does not include descriptors so it does not support AmqpProvidesAttribute.", type.Name)); } Dictionary <Type, SerializableType> knownTypes = null; var providesAttributes = type.GetCustomAttributes <AmqpProvidesAttribute>(false); foreach (object o in providesAttributes) { AmqpProvidesAttribute knownAttribute = (AmqpProvidesAttribute)o; if (knownAttribute.Type.GetCustomAttribute <AmqpContractAttribute>(false) != null) { if (knownTypes == null) { knownTypes = new Dictionary <Type, SerializableType>(); } // KnownType compilation is delayed and non-recursive to avoid circular references knownTypes.Add(knownAttribute.Type, null); } } if (contractAttribute.Encoding == EncodingType.List) { return(SerializableType.CreateDescribedListType(this, type, baseType, descriptorName, descriptorCode, members, knownTypes, serializationCallbacks)); } else if (contractAttribute.Encoding == EncodingType.Map) { return(SerializableType.CreateDescribedMapType(this, type, baseType, descriptorName, descriptorCode, members, knownTypes, serializationCallbacks)); } else if (contractAttribute.Encoding == EncodingType.SimpleMap) { return(SerializableType.CreateDescribedSimpleMapType(this, type, baseType, members, serializationCallbacks)); } else { throw new NotSupportedException(contractAttribute.Encoding.ToString()); } }
SerializableType CompileType(Type type, bool describedOnly) { object[] typeAttributes = type.GetCustomAttributes(typeof(AmqpContractAttribute), false); if (typeAttributes.Length == 0) { if (describedOnly) { return(null); } else { return(CompileNonContractTypes(type)); } } AmqpContractAttribute contractAttribute = (AmqpContractAttribute)typeAttributes[0]; SerializableType baseType = null; if (type.BaseType != typeof(object)) { baseType = this.CompileType(type.BaseType, true); if (baseType != null) { if (baseType.Encoding != contractAttribute.Encoding) { throw new SerializationException( Fx.Format("{0}.Encoding ({1}) is different from {2}.Encoding ({3})", type.Name, contractAttribute.Encoding, type.BaseType.Name, baseType.Encoding)); } this.typeCache[type.BaseType] = baseType; } } string descriptorName = contractAttribute.Name; ulong? descriptorCode = contractAttribute.InternalCode; if (descriptorName == null && descriptorCode == null) { descriptorName = type.FullName; } List <SerialiableMember> memberList = new List <SerialiableMember>(); if (contractAttribute.Encoding == EncodingType.List && baseType != null) { memberList.AddRange(baseType.Members); } int lastOrder = memberList.Count + 1; MemberInfo[] memberInfos = type.GetMembers(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); MethodAccessor onDeserialized = null; foreach (MemberInfo memberInfo in memberInfos) { if (memberInfo.DeclaringType != type) { continue; } if (memberInfo.MemberType == MemberTypes.Field || memberInfo.MemberType == MemberTypes.Property) { object[] memberAttributes = memberInfo.GetCustomAttributes(typeof(AmqpMemberAttribute), true); if (memberAttributes.Length != 1) { continue; } AmqpMemberAttribute attribute = (AmqpMemberAttribute)memberAttributes[0]; SerialiableMember member = new SerialiableMember(); member.Name = attribute.Name ?? memberInfo.Name; member.Order = attribute.InternalOrder ?? lastOrder++; member.Accessor = MemberAccessor.Create(memberInfo, true); // This will recursively resolve member types Type memberType = memberInfo.MemberType == MemberTypes.Field ? ((FieldInfo)memberInfo).FieldType : ((PropertyInfo)memberInfo).PropertyType; member.Type = GetType(memberType); memberList.Add(member); } else if (memberInfo.MemberType == MemberTypes.Method) { object[] memberAttributes = memberInfo.GetCustomAttributes(typeof(OnDeserializedAttribute), false); if (memberAttributes.Length == 1) { onDeserialized = MethodAccessor.Create((MethodInfo)memberInfo); } } } if (contractAttribute.Encoding == EncodingType.List) { memberList.Sort(MemberOrderComparer.Instance); int order = -1; foreach (SerialiableMember member in memberList) { if (order > 0 && member.Order == order) { throw new SerializationException(Fx.Format("Duplicate Order {0} detected in {1}", order, type.Name)); } order = member.Order; } } SerialiableMember[] members = memberList.ToArray(); Dictionary <Type, SerializableType> knownTypes = null; foreach (object o in type.GetCustomAttributes(typeof(AmqpProvidesAttribute), false)) { AmqpProvidesAttribute knownAttribute = (AmqpProvidesAttribute)o; if (knownAttribute.Type.GetCustomAttributes(typeof(AmqpContractAttribute), false).Length > 0) { if (knownTypes == null) { knownTypes = new Dictionary <Type, SerializableType>(); } // KnownType compilation is delayed and non-recursive to avoid circular references knownTypes.Add(knownAttribute.Type, null); } } if (contractAttribute.Encoding == EncodingType.List) { return(SerializableType.CreateDescribedListType(this, type, baseType, descriptorName, descriptorCode, members, knownTypes, onDeserialized)); } else if (contractAttribute.Encoding == EncodingType.Map) { return(SerializableType.CreateDescribedMapType(this, type, baseType, descriptorName, descriptorCode, members, knownTypes, onDeserialized)); } else { throw new NotSupportedException(contractAttribute.Encoding.ToString()); } }