SerializableType CompileType(Type type, bool describedOnly) { AmqpContract contract = this.contractResolver.Resolve(type); if (contract != null) { return(this.CreateContractType(contract)); } return(this.CompileNonContractTypes(type)); }
SerializableType CompileType(Type type, bool describedOnly, HashSet <Type> pendingTypes) { AmqpContract contract = this.contractResolver.Resolve(type); if (contract != null) { return(this.CreateContractType(contract, pendingTypes)); } return(this.CompileNonContractTypes(type, pendingTypes)); }
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()); } }
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); }
/// <summary> /// Called when a type is successully resolved. Derived class can /// override this method to update the contract if necessary. /// </summary> /// <param name="contract">The serialization contract.</param> protected virtual void OnResolved(AmqpContract contract) { }
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); }