in src/StreamJsonRpc/JsonMessageFormatter.cs [944:1002]
public override ArgumentMatchResult TryGetTypedArguments(ReadOnlySpan<ParameterInfo> parameters, Span<object?> typedArguments)
{
// Consider the attribute applied to the particular overload that we're considering right now.
this.ApplicableMethodAttribute = this.Method is not null ? this.formatter.rpc?.GetJsonRpcMethodAttribute(this.Method, parameters) : null;
try
{
if (parameters.Length == 1 && this.NamedArguments is not null)
{
// Special support for accepting a single JToken instead of all parameters individually.
if (parameters[0].ParameterType == typeof(JToken))
{
var obj = new JObject();
foreach (KeyValuePair<string, object?> property in this.NamedArguments)
{
obj.Add(new JProperty(property.Key, property.Value));
}
typedArguments[0] = obj;
return ArgumentMatchResult.Success;
}
// Support for opt-in to deserializing all named arguments into a single parameter.
if (this.Method is not null)
{
if (this.ApplicableMethodAttribute?.UseSingleObjectParameterDeserialization ?? false)
{
var obj = new JObject();
foreach (KeyValuePair<string, object?> property in this.NamedArguments)
{
obj.Add(new JProperty(property.Key, property.Value));
}
// Deserialization of messages should never occur concurrently for a single instance of a formatter.
Assumes.True(this.formatter.deserializingMessageWithId.IsEmpty);
this.formatter.deserializingMessageWithId = this.RequestId;
this.formatter.deserializingMessage = this;
try
{
typedArguments[0] = obj.ToObject(parameters[0].ParameterType, this.formatter.JsonSerializer);
}
finally
{
this.formatter.deserializingMessageWithId = default;
this.formatter.deserializingMessage = null;
}
return ArgumentMatchResult.Success;
}
}
}
return base.TryGetTypedArguments(parameters, typedArguments);
}
finally
{
// Clear this, because we might choose another overload with a different attribute, and we don't want to 'leak' an attribute that isn't on the overload that is ultimately picked.
this.ApplicableMethodAttribute = null;
}
}