in src/Serialization/AmqpContractSerializer.cs [422:506]
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,
static (o, t) => Convert.ChangeType(o, t),
static (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;
}