SerializableType CreateContractType(AmqpContract contract) { Type type = contract.Type; string descriptorName = contract.Attribute.Name; ulong? descriptorCode = contract.Attribute.InternalCode; if (descriptorName == null && descriptorCode == null) { descriptorName = type.FullName; } SerializableMember[] members = new SerializableMember[contract.Members.Length]; for (int i = 0; i < contract.Members.Length; i++) { SerializableMember member = new SerializableMember(); members[i] = member; AmqpMember amqpMember = contract.Members[i]; member.Name = amqpMember.Name; member.Order = amqpMember.Order; member.Accessor = MemberAccessor.Create(amqpMember.Info, true); // This will recursively resolve member types Type memberType = amqpMember.Info is FieldInfo ? ((FieldInfo)amqpMember.Info).FieldType : ((PropertyInfo)amqpMember.Info).PropertyType; member.Type = GetType(memberType); } MethodAccessor[] serializationCallbacks = new MethodAccessor[] { contract.Serializing == null ? null : MethodAccessor.Create(contract.Serializing), contract.Serialized == null ? null : MethodAccessor.Create(contract.Serialized), contract.Deserializing == null ? null : MethodAccessor.Create(contract.Deserializing), contract.Deserialized == null ? null : MethodAccessor.Create(contract.Deserialized) }; SerializableType baseType = null; if (contract.BaseContract != null) { baseType = this.CreateContractType(contract.BaseContract); } Dictionary <Type, SerializableType> knownTypes = null; if (contract.Provides != null) { knownTypes = new Dictionary <Type, SerializableType>(); for (int i = 0; i < contract.Provides.Length; i++) { // KnownType compilation is delayed and non-recursive to avoid circular references knownTypes.Add(contract.Provides[i], null); } } if (contract.Attribute.Encoding == EncodingType.List) { return(SerializableType.CreateDescribedListType(this, type, baseType, descriptorName, descriptorCode, members, knownTypes, serializationCallbacks)); } else if (contract.Attribute.Encoding == EncodingType.Map) { return(SerializableType.CreateDescribedMapType(this, type, baseType, descriptorName, descriptorCode, members, knownTypes, serializationCallbacks)); } else if (contract.Attribute.Encoding == EncodingType.SimpleMap) { return(SerializableType.CreateDescribedSimpleMapType(this, type, baseType, members, serializationCallbacks)); } else if (contract.Attribute.Encoding == EncodingType.SimpleList) { return(SerializableType.CreateDescribedSimpleListType(this, type, baseType, members, serializationCallbacks)); } else { throw new NotSupportedException(contract.Attribute.Encoding.ToString()); } }
SerializableType CreateContractType(AmqpContract contract, HashSet <Type> pendingTypes) { Type type = contract.Type; if (pendingTypes.Contains(type)) { return(SerializableType.CreateDelegatingType(this, type)); } pendingTypes.Add(type); string descriptorName = contract.Attribute.Name; ulong? descriptorCode = contract.Attribute.InternalCode; if (descriptorName == null && descriptorCode == null) { descriptorName = type.FullName; } SerializableMember[] members = new SerializableMember[contract.Members.Length]; for (int i = 0; i < contract.Members.Length; i++) { SerializableMember member = new SerializableMember(); members[i] = member; AmqpMember amqpMember = contract.Members[i]; member.Name = amqpMember.Name; member.Order = amqpMember.Order; member.Accessor = MemberAccessor.Create(amqpMember.Info, true); // This will recursively resolve member types Type memberType = amqpMember.Info is FieldInfo ? ((FieldInfo)amqpMember.Info).FieldType : ((PropertyInfo)amqpMember.Info).PropertyType; member.Type = GetOrCompileType(memberType, false, pendingTypes); } MethodAccessor[] serializationCallbacks = new MethodAccessor[] { contract.Serializing == null ? null : MethodAccessor.Create(contract.Serializing), contract.Serialized == null ? null : MethodAccessor.Create(contract.Serialized), contract.Deserializing == null ? null : MethodAccessor.Create(contract.Deserializing), contract.Deserialized == null ? null : MethodAccessor.Create(contract.Deserialized) }; SerializableType baseType = null; if (contract.BaseContract != null) { baseType = this.CreateContractType(contract.BaseContract, pendingTypes); } SerializableType[] knownTypes = null; if (contract.Provides != null) { knownTypes = new SerializableType[contract.Provides.Length]; for (int i = 0; i < contract.Provides.Length; i++) { knownTypes[i] = this.GetOrCompileType(contract.Provides[i], true, pendingTypes); } } SerializableType result; if (contract.Attribute.Encoding == EncodingType.List) { result = SerializableType.CreateDescribedListType(this, type, baseType, descriptorName, descriptorCode, members, knownTypes, serializationCallbacks); } else if (contract.Attribute.Encoding == EncodingType.Map) { result = SerializableType.CreateDescribedMapType(this, type, baseType, descriptorName, descriptorCode, members, knownTypes, serializationCallbacks); } else if (contract.Attribute.Encoding == EncodingType.SimpleMap) { result = SerializableType.CreateDescribedSimpleMapType(this, type, baseType, members, serializationCallbacks); } else if (contract.Attribute.Encoding == EncodingType.SimpleList) { result = SerializableType.CreateDescribedSimpleListType(this, type, baseType, members, serializationCallbacks); } else { throw new NotSupportedException(contract.Attribute.Encoding.ToString()); } pendingTypes.Remove(type); return(result); }
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()); } }