in lang/csharp/src/apache/main/Reflect/ClassCache.cs [196:302]
public void LoadClassCache(Type objType, Schema s)
{
switch (s)
{
case RecordSchema rs:
if (!objType.IsClass)
{
throw new AvroException($"Cant map scalar type {objType.Name} to record {rs.Fullname}");
}
if (typeof(byte[]).IsAssignableFrom(objType)
|| typeof(string).IsAssignableFrom(objType)
|| typeof(IEnumerable).IsAssignableFrom(objType)
|| typeof(IDictionary).IsAssignableFrom(objType))
{
throw new AvroException($"Cant map type {objType.Name} to record {rs.Fullname}");
}
AddClassNameMapItem(rs, objType);
var c = GetClass(rs);
foreach (var f in rs.Fields)
{
/*
//.StackOverflowException
var t = c.GetPropertyType(f);
LoadClassCache(t, f.Schema);
*/
if (_previousFields.TryAdd(f.Name, f.Schema))
{
var t = c.GetPropertyType(f);
LoadClassCache(t, f.Schema);
}
}
break;
case ArraySchema ars:
if (!typeof(IEnumerable).IsAssignableFrom(objType))
{
throw new AvroException($"Cant map type {objType.Name} to array {ars.Name}");
}
if (!objType.IsGenericType)
{
throw new AvroException($"{objType.Name} needs to be a generic type");
}
LoadClassCache(objType.GenericTypeArguments[0], ars.ItemSchema);
break;
case MapSchema ms:
if (!typeof(IDictionary).IsAssignableFrom(objType))
{
throw new AvroException($"Cant map type {objType.Name} to map {ms.Name}");
}
if (!objType.IsGenericType)
{
throw new AvroException($"Cant map non-generic type {objType.Name} to map {ms.Name}");
}
if (!typeof(string).IsAssignableFrom(objType.GenericTypeArguments[0]))
{
throw new AvroException($"First type parameter of {objType.Name} must be assignable to string");
}
LoadClassCache(objType.GenericTypeArguments[1], ms.ValueSchema);
break;
case NamedSchema ns:
EnumCache.AddEnumNameMapItem(ns, objType);
break;
case UnionSchema us:
if (us.Schemas.Count == 2 && (us.Schemas[0].Tag == Schema.Type.Null || us.Schemas[1].Tag == Schema.Type.Null))
{
// in this case objType will match the non null type in the union
foreach (var o in us.Schemas)
{
if (o.Tag == Schema.Type.Null)
{
continue;
}
if (objType.IsClass)
{
LoadClassCache(objType, o);
}
var innerType = Nullable.GetUnderlyingType(objType);
if (innerType != null && innerType.IsEnum)
{
LoadClassCache(innerType, o);
}
}
}
else
{
// check the schema types are registered
foreach (var o in us.Schemas)
{
if (o.Tag == Schema.Type.Record && GetClass(o as RecordSchema) == null)
{
throw new AvroException($"Class for union record type {o.Fullname} is not registered. Create a ClassCache object and call LoadClassCache");
}
}
}
break;
}
}