Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

csharp marshaller : emulate legacy serializer via contextual API, or provide ability to specify legacy *and* contextual serializer #19470

Closed
mgravell opened this issue Jun 26, 2019 · 3 comments
Labels

Comments

@mgravell
Copy link
Contributor

mgravell commented Jun 26, 2019

Right now when creating a Marshaller<T>, you can only specify either the legacy or contextual serializer. If you use the contextual API, it creates intentionally broken delegates for the legacy API:

// gRPC only uses contextual serializer/deserializer internally, so emulating the legacy
// (de)serializer is not necessary.
this.serializer = (msg) => { throw new NotImplementedException(); };
this.deserializer = (payload) => { throw new NotImplementedException(); };

This is fine for Grpc.Core, but breaks if another host wants to use the legacy API (possibly to avoid the "experimental" API surface).

What would be ideal is if we had another constructor, to allow the configuring code to specify both a contextual and legacy API; if the legacy API is omitted, then sure: omit them. By which I mean:

public Marshaller(
    Action<T, SerializationContext> serializer,
    Func<DeserializationContext, T> deserializer)
        : this(serializer, deserializer, null, null) {}
public Marshaller(
    Action<T, SerializationContext> contextualSerializer,
    Func<DeserializationContext, T> contextualDeserializer,
    Action<T, SerializationContext> legacySerializer,
    Func<DeserializationContext, T> legacyDeserializer)
{
    this.contextualSerializer = GrpcPreconditions.CheckNotNull(contextualSerializer, nameof(contextualSerializer));
    this.contextualDeserializer = GrpcPreconditions.CheckNotNull(contextualDeserializer, nameof(contextualDeserializer));
    // gRPC only uses contextual serializer/deserializer internally, so emulating the legacy
    // (de)serializer (when they are not provided by the caller) is not necessary.
    this.serializer = legacySerializer ?? ((msg) => { throw new NotImplementedException(); });
    this.deserializer = legacyDeserializer ?? ((payload) => { throw new NotImplementedException(); });
}

This would allow callers to supply "best and fallback" implementations, so that it can at least work on all hosts, even if it doesn't get the full advantages if the host only consumes the legacy API.

Happy to do a PR if it is viable.

@mgravell
Copy link
Contributor Author

Another option of course being to emulate it with a spoof ctx; that should be pretty easy too - happy to help

mgravell added a commit to mgravell/grpc that referenced this issue Jun 26, 2019
…al API is used; also use sane default implementation of PayloadAsReadOnlySequence, as not all contexts might implement correctly
@mgravell
Copy link
Contributor Author

on reflection, I think emulation is the better option - then there's only one API for the caller to implement either way; added a PR

@mgravell mgravell changed the title csharp marshaller : ability to specify legacy *and* contextual serializer csharp marshaller : emulate legacy serializer via contextual API, or provide ability to specify legacy *and* contextual serializer Jun 27, 2019
@jtattermusch
Copy link
Contributor

I think the right solution is to switch grpc-dotnet to contextual serialization API which should solve the problems you're seeing
#19471 (comment)

@lock lock bot locked as resolved and limited conversation to collaborators Oct 2, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

No branches or pull requests

3 participants