protected override Expression BuildSerializerSafe(Expression encoder, Expression value) { // Indexing schemas according to their position. // according to avro spec http://avro.apache.org/docs/current/spec.html#Unions // Unions may not contain more than one schema with the same type, except for the named types record, fixed and enum. // For example, unions containing two array types or two map types are not permitted, but two types with different names are permitted int schemaIndex = 0; var schemas = new List <IndexedSchema>(this.itemSchemas.Count); foreach (var typeSchema in this.itemSchemas) { // use FirstOrDefault rather than SingleOrDefault because we need to add all schema to the list. var existingSchema = schemas.FirstOrDefault(s => UnionSchema.IsSameTypeAs(s.Schema, typeSchema)); var index = existingSchema != null ? existingSchema.Index : schemaIndex++; var indexSchema = new IndexedSchema { Schema = typeSchema, Index = index }; schemas.Add(indexSchema); } // Nullable schemas. if (schemas.Count == 2 && schemas.Select(s => s.Schema).OfType <NullSchema>().Any()) { return(this.BuildNullableSerializer(encoder, value, schemas)); } // Sort according to inheritance hierarchy - most specialized type goes first. schemas.Sort(this.MoreSpecializedTypesFirst); return(this.BuildUnionSerializer(encoder, value, schemas)); }
private int MoreSpecializedTypesFirst(IndexedSchema s1, IndexedSchema s2) { if (s1.Schema.RuntimeType.IsAssignableFrom(s2.Schema.RuntimeType)) { return(1); } if (s2.Schema.RuntimeType.IsAssignableFrom(s1.Schema.RuntimeType)) { return(-1); } return(s1.Index.CompareTo(s2.Index)); }