in src/Serialization/AmqpContractSerializer.cs [272:418]
SerializableType CompileType(Type type, bool describedOnly)
{
if (this.externalCompilers != null)
{
foreach (var compiler in this.externalCompilers)
{
SerializableType serializable = compiler(type);
if (serializable != null)
{
return serializable;
}
}
}
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.Composite baseType = null;
if (type.GetTypeInfo().BaseType != typeof(object))
{
var baseSerializableType = this.CompileType(type.GetTypeInfo().BaseType, true);
if (baseSerializableType != null)
{
if (baseSerializableType.AmqpType != AmqpType.Composite)
{
throw new SerializationException(AmqpResources.GetString(AmqpResources.AmqpInvalidType, baseType.GetType().Name));
}
baseType = (SerializableType.Composite)baseSerializableType;
if (baseType.EncodingType != contractAttribute.Encoding)
{
throw new SerializationException(AmqpResources.GetString(AmqpResources.AmqpEncodingTypeMismatch, type.Name, contractAttribute.Encoding, type.GetTypeInfo().BaseType.Name, baseType.EncodingType));
}
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 (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();
List<Type> knownTypes = new List<Type>();
foreach (object o in type.GetTypeInfo().GetCustomAttributes(typeof(KnownTypeAttribute), false))
{
KnownTypeAttribute knownAttribute = (KnownTypeAttribute)o;
if (knownAttribute.Type.GetTypeInfo().GetCustomAttributes(typeof(AmqpContractAttribute), false).Any())
{
// KnownType compilation is delayed and non-recursive to avoid circular references
knownTypes.Add(knownAttribute.Type);
}
}
if (contractAttribute.Encoding == EncodingType.List)
{
return new SerializableType.CompositeList(this, type, baseType, descriptorName,
descriptorCode, members, knownTypes, onDeserialized);
}
else if (contractAttribute.Encoding == EncodingType.Map)
{
return new SerializableType.CompositeMap(this, type, baseType, descriptorName,
descriptorCode, members, knownTypes, onDeserialized);
}
else
{
throw new NotSupportedException(contractAttribute.Encoding.ToString());
}
}