asynkron / Wire

Binary serializer for POCO objects
Apache License 2.0
376 stars 63 forks source link

Invalid code generation on fields of interface type #127

Closed rogeralsing closed 3 years ago

rogeralsing commented 7 years ago

If a field is of an interface type, Wire currently tries to fetch the fields of that type, which is invalid. interface types should just act as an object field and let the concrete content of the field decide how to serialize the data.

https://github.com/akkadotnet/akka.net/issues/2365

kantora commented 7 years ago

And what is wrong always work only with contents end-types (not declared field/property types)?

rogeralsing commented 7 years ago

It uses both the field type and the content type.

the problem currently with the interfaces in the fields, is that the code generator tries to do things that are not possible on an interface type.

rogeralsing commented 7 years ago

I have added tests for this, The tests however pass and the interface field is serialized just fine. I need to create tests for the specific messages in Akka.NET that uses interface fields to see why that fails.

kantora commented 7 years ago

Maybe this can help. I've made some local modification in Wire to make exceptions give more data and managed to trace the problem.

Akka.Cluster.Tools.PublishSubscribe.Internal.Bucket has the field public readonly IImmutableDictionary<string, ValueHolder> Content.

The problem is in the Wire.SerializerFactories.ImmutableCollectionsSerializerFactory.BuildSerializer.

            var typeName = type.Name;
            var genericSufixIdx = typeName.IndexOf('`');
            typeName = genericSufixIdx != -1 ? typeName.Substring(0, genericSufixIdx) : typeName;
            var creatorType =
                Type.GetType(
                    ImmutableCollectionsNamespace + "." + typeName + ", " + ImmutableCollectionsAssembly, true);

For this field creatorType tries to load type System.Collections.Immutable.IImmutableDictionary, System.Collections.Immutable and there is no such type (Type load exception).

Unfortunately, I don't have enough understanding of the code to get the meaning of such type name conversion (as you are not guaranteed to have a type with the same name as generic, but without generic parameters).

rogeralsing commented 7 years ago

I will continue to dig in this. It could be that Wire incorrectly encodes the type of the payload as the interface type, and once it tries to deserialize, it might try to create an instance of the interface. Which is ofcourse not possible.

I will keep updating here.