public Map(AmqpContractSerializer serializer, Type type, MemberAccessor keyAccessor, MemberAccessor valueAccessor, MethodAccessor addAccessor) : base(serializer, type) { this.AmqpType = AmqpType.Primitive; this.keyType = this.serializer.GetType(keyAccessor.Type); this.valueType = this.serializer.GetType(valueAccessor.Type); this.keyAccessor = keyAccessor; this.valueAccessor = valueAccessor; this.addMethodAccessor = addAccessor; }
SerializableType CompileType(Type type, bool describedOnly) { var typeAttributes = type.GetTypeInfo().GetCustomAttributes(typeof(AmqpContractAttribute), false); if (!typeAttributes.Any()) { if (describedOnly) { return(null); } else { return(CompileNonContractTypes(type)); } } AmqpContractAttribute contractAttribute = (AmqpContractAttribute)typeAttributes.First(); SerializableType baseType = null; if (type.GetTypeInfo().BaseType != typeof(object)) { baseType = this.CompileType(type.GetTypeInfo().BaseType, true); if (baseType != null) { if (baseType.Encoding != contractAttribute.Encoding) { throw new SerializationException(AmqpResources.GetString(AmqpResources.AmqpEncodingTypeMismatch, type.Name, contractAttribute.Encoding, type.GetTypeInfo().BaseType.Name, baseType.Encoding)); } this.customTypeCache.TryAdd(type.GetTypeInfo().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 is FieldInfo || memberInfo is PropertyInfo) { var memberAttributes = memberInfo.GetCustomAttributes(typeof(AmqpMemberAttribute), true); if (memberAttributes.Count() != 1) { continue; } AmqpMemberAttribute attribute = (AmqpMemberAttribute)memberAttributes.First(); SerialiableMember member = new SerialiableMember(); member.Name = attribute.Name ?? memberInfo.Name; member.Order = attribute.InternalOrder ?? lastOrder++; member.Mandatory = attribute.Mandatory; 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) { var memberAttributes = memberInfo.GetCustomAttributes(typeof(OnDeserializedAttribute), false); if (memberAttributes.Count() == 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(AmqpResources.GetString(AmqpResources.AmqpDuplicateMemberOrder, order, type.Name)); } order = member.Order; } } SerialiableMember[] members = memberList.ToArray(); Dictionary <Type, SerializableType> knownTypes = null; foreach (object o in type.GetTypeInfo().GetCustomAttributes(typeof(KnownTypeAttribute), false)) { KnownTypeAttribute knownAttribute = (KnownTypeAttribute)o; if (knownAttribute.Type.GetTypeInfo().GetCustomAttributes(typeof(AmqpContractAttribute), false).Any()) { 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()); } }
SerializableType CompileNonContractTypes(Type type) { if (type.GetTypeInfo().IsGenericType&& type.GetGenericTypeDefinition() == typeof(Nullable <>)) { Type[] argTypes = type.GetGenericArguments(); Fx.Assert(argTypes.Length == 1, "Nullable type must have one argument"); return(this.GetType(argTypes[0])); } if (type.GetTypeInfo().IsInterface) { if (typeof(IEnumerable).GetTypeInfo().IsAssignableFrom(type.GetTypeInfo())) { // if a member is defined as enumerable interface, we have to change it // to list, otherwise the decoder cannot initialize an object of an interface Type itemType = typeof(object); Type listType = typeof(List <object>); if (type.GetTypeInfo().IsGenericType) { Type[] argTypes = type.GetGenericArguments(); Fx.Assert(argTypes.Length == 1, "IEnumerable type must have one argument"); itemType = argTypes[0]; listType = typeof(List <>).MakeGenericType(argTypes); } MethodAccessor addAccess = MethodAccessor.Create(listType.GetMethod("Add", new Type[] { itemType })); return(new SerializableType.List(this, listType, itemType, addAccess) { Final = true }); } return(null); } if (type.GetTypeInfo().IsEnum) { Type underlyingType = Enum.GetUnderlyingType(type); return(new SerializableType.Converted( AmqpType.Converted, type, underlyingType, (o, t) => Convert.ChangeType(o, t), (o, t) => Enum.ToObject(t, o))); } if (type.GetInterfaces().Any(it => it == typeof(IAmqpSerializable))) { return(new SerializableType.Serializable(this, type)); } if (type.IsArray) { // validate item type to be AMQP types only AmqpEncoding.GetEncoding(type.GetElementType()); return(SerializableType.CreatePrimitiveType(type)); } foreach (Type it in type.GetInterfaces()) { if (it.GetTypeInfo().IsGenericType) { Type genericTypeDef = it.GetGenericTypeDefinition(); if (genericTypeDef == typeof(IDictionary <,>)) { Type[] argTypes = it.GetGenericArguments(); Type itemType = typeof(KeyValuePair <,>).MakeGenericType(argTypes); MemberAccessor keyAccessor = MemberAccessor.Create(itemType.GetProperty("Key"), false); MemberAccessor valueAccessor = MemberAccessor.Create(itemType.GetProperty("Value"), false); MethodAccessor addAccess = MethodAccessor.Create(type.GetMethod("Add", argTypes)); return(new SerializableType.Map(this, type, keyAccessor, valueAccessor, addAccess)); } if (genericTypeDef == typeof(ICollection <>)) { Type[] argTypes = it.GetGenericArguments(); Type itemType = argTypes[0]; MethodAccessor addAccess = MethodAccessor.Create(type.GetMethod("Add", argTypes)); return(new SerializableType.List(this, type, itemType, addAccess)); } } } return(null); }