Example #1
0
        /// <summary>
        /// Add an entry to the class cache.
        /// </summary>
        /// <param name="objType">Type of the C# class</param>
        /// <param name="s">Schema</param>
        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) && objType.IsClass)
                {
                    // 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)
                        {
                            LoadClassCache(objType, 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;
            }
        }
Example #2
0
        /// <summary>
        /// Add an entry to the class cache.
        /// </summary>
        /// <param name="objType">Type of the C# class</param>
        /// <param name="s">Schema</param>
        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)
                {
                    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;
            }
        }