Comments (8)
@dstelljes good questions!
After giving it some more thought, I don't think I'm going the polymorphism route.
It would work for in C#, but it would be really hard to get this going in say KSQL.
I'm now going to split up every concrete class in its own event. Much simpler and more supported. Feel free to continue on my fork if you want.
from dotnet-avro.
We’ve discussed this internally, and it’s definitely something we eventually want to support.
One option we considered was the “official” KnownType
attribute; the data contract resolver already analyzes DataContract
and DataMember
. My sense is that KnownType
may not be a good fit, but I haven’t dug into it enough to know for sure. I’ll try to carve out some time next week to put together a solid proposal.
from dotnet-avro.
The 'official' KnownType
attribute is ok, but it doesn't allow interfaces. I've currently added a new Attribute which does allow it.
I've also added an InterfaceResolution
for interfaces together with an InterfaceResolverCase
. The InterfaceResolution
has a KnownTypes
of Type[]
.
Furthermore, I've added an InterfaceSchemaBuilderCase
which does something like this:
var innerSchemas = interfaceResolution.KnownTypes
.Select(x => SchemaBuilder.BuildSchema(x, cache))
.ToArray();
var schema = new UnionSchema(innerSchemas);
The schema building seem to work!
I'm now in the process of adding two SerializerBuilderCase
s. One for the interface and one for the concrete classes.
The interface one has an InterfaceResolution
and an UnionSchema
. The concrete class one also has an InterfaceResolution
, but a RecordSchema
instead of UnionSchema
.
The biggest challenge is creating the expression, that should dynamically switch to the correct type.
from dotnet-avro.
@dstelljes see #19 for initial wip
from dotnet-avro.
Thanks for posting your WIP; that’s helpful. Still mulling over a few questions:
-
How would Chr.Avro determine which record in a union is mapped to which known type? Given a schema
[null, "Cat", "Dog"]
whereCat
andDog
are records, and an interfaceIAnimal
with known implementing classesCat
andDog
, the serde builders have to make some kind of judgment—matching name? largest percentage of matching fields? function provided by some attribute? System.Runtime.Serialization seems to use equivalence. -
Would we ever want to support interfaces without known concrete classes? For instance, deserializing a record to some interface
IAnimal
, could the deserializer builder create and map to some runtime-generated class that implementedIAnimal
? This seems possible; not sure whether it‘s wise.
from dotnet-avro.
After talking it over with some people internally, we’re going to try to add support for KnownTypeAttribute
as it’s described in the WCF docs.
Here’s what I’m thinking: Given this type EventRecord
with some KnownType
attributes...
[KnownType(typeof(OrderCreation))]
[KnownType(typeof(OrderLineItemModification))]
[KnownType(typeof(OrderCancellation))]
class EventRecord
{
IEvent Event { get; set; }
DateTime Timestamp { get; set; }
}
interface IEvent
{
object Metadata { get; set; }
}
class OrderCreation : IEvent
{
public IEnumerable<OrderLineItem> LineItems { get; set; }
}
class OrderLineItemModification : IEvent
{
public int Index { get; set; }
public OrderLineItem LineItem { get; set; }
}
class OrderCancellation : IEvent
{
}
class OrderLineItem
{
Guid ProductId { get; set; }
int Quantity { get; set; }
}
-
Any known types on
EventRecord
that implementIEvent
will be included in the resolution for theEvent
field. -
Known types will cascade, so all of the known types on
EventRecord
will propagate as its fields are resolved. (All of the known types onEventRecord
will be included in the resolution for theMetadata
field since they extendobject
.) -
When a resolution contains multiple known types, the binary serde builders will attempt to build serdes for each known type and throw unless exactly one matches. A serializer for
EventRecord
will build successfully, but building a deserializer will throw—anOrderCancellation
record, since it has no fields, could be mapped to any of the known types.
Obviously, this has some drawbacks, but hopefully it’s enough to start collecting feedback.
from dotnet-avro.
One other thought: We could also demonstrate how to make this work by customizing the serde builders. For example, a custom case could resolve the ambiguity above:
public EventDeserializerBuilderCase : BinaryDeserializerBuilderCase
{
public override Delegate BuildDelegate(TypeResolution resolution, Schema schema, ConcurrentDictionary<(Type, Schema), Delegate> cache)
{
if (!(resolution is RecordResolution recordResolution) || recordResolution.Type !== typeof(IEvent))
{
throw new UnsupportedTypeException(type);
}
if (!(schema is UnionSchema unionSchema))
{
throw new UnsupportedSchemaException(schema);
}
// map each schema in the union to a concrete type and build a deserializer
}
}
We could maybe even provide some higher-level cases to streamline this a little.
from dotnet-avro.
Closing for #43, which is how I think we’re going to want to implement this.
from dotnet-avro.
Related Issues (20)
- Unable to generate a schema with default values HOT 2
- Default values support in codegen HOT 5
- `[EnumMember]` value should be used when serializing enum types to `"string"`
- Add support for NodaTime HOT 1
- Could not load file or assembly System.ServiceModel.Primitives.dll HOT 1
- Method not found exception HOT 1
- Union with null and multiple selected types throws exception when serializing null. HOT 1
- Exception serializing an anonymous object HOT 3
- No coercion operator is defined between types 'System.String' and 'System.Char[]'. on a simple string property HOT 8
- Exception when building a serializer for type with a missing field from the schema HOT 2
- Support C# records in codegen HOT 1
- Support DateOnly and TimeOnly types
- JSON test failures under NetCore 3.1
- `ArraySegment<T>` deserialization fails on .NET Framework
- Support for Nullable Uri HOT 1
- Support `IgnoreDataMember` attribute
- Support unsigned number as logical types in codegen from Avro HOT 9
- Change to ConstructValueSubjectName HOT 1
- System.Datetime is not handled consistently HOT 1
- Deserialize string to DateOnly fails on net6 HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from dotnet-avro.