SerializableType CompileCollectionTypes(Type type, HashSet <Type> pendingTypes) { MemberAccessor keyAccessor = null; MemberAccessor valueAccessor = null; MethodAccessor addAccess = null; if (type.IsArray) { // array of custom types. encode it as list var itemType = type.GetElementType(); var listType = this.GetOrCompileType(typeof(List <>).MakeGenericType(itemType), false, pendingTypes); return(SerializableType.CreateArrayType(this, type, itemType, listType)); } foreach (Type it in type.GetInterfaces()) { if (it.IsGenericType()) { Type genericTypeDef = it.GetGenericTypeDefinition(); if (genericTypeDef == typeof(IDictionary <,>)) { Type[] argTypes = it.GetGenericArguments(); var itemType = typeof(KeyValuePair <,>).MakeGenericType(argTypes); keyAccessor = MemberAccessor.Create(itemType.GetProperty("Key"), false); valueAccessor = MemberAccessor.Create(itemType.GetProperty("Value"), false); addAccess = MethodAccessor.Create(type.GetMethod("Add", argTypes)); var keyType = this.GetOrCompileType(keyAccessor.Type, false, pendingTypes); var valueType = this.GetOrCompileType(valueAccessor.Type, false, pendingTypes); return(SerializableType.CreateGenericMapType(this, type, keyType, valueType, keyAccessor, valueAccessor, addAccess)); } else if (genericTypeDef == typeof(IList <>)) { Type[] argTypes = it.GetGenericArguments(); var itemType = this.GetOrCompileType(argTypes[0], false, pendingTypes); addAccess = MethodAccessor.Create(type.GetMethod("Add", argTypes)); return(SerializableType.CreateGenericListType(this, type, itemType, addAccess)); } } } return(null); }
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 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 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); }
public GenericMapType(AmqpSerializer serializer, Type type, MemberAccessor keyAccessor, MemberAccessor valueAccessor, MethodAccessor addAccessor) : base(serializer, type) { this.keyType = this.serializer.GetType(keyAccessor.Type); this.valueType = this.serializer.GetType(valueAccessor.Type); this.keyAccessor = keyAccessor; this.valueAccessor = valueAccessor; this.addMethodAccessor = addAccessor; }
public static SerializableType CreateGenericMapType( AmqpSerializer serializer, Type type, MemberAccessor keyAccessor, MemberAccessor valueAccessor, MethodAccessor addAccessor) { return new GenericMapType(serializer, type, keyAccessor, valueAccessor, addAccessor); }
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()); } }