Skip to content

CSHARP-5959: Replace switch by method name in SerializerFinderVisitMethodCall with lookup table with MethodInfo as a key#1961

Draft
sanych-sun wants to merge 4 commits intomongodb:mainfrom
sanych-sun:csharp5959
Draft

CSHARP-5959: Replace switch by method name in SerializerFinderVisitMethodCall with lookup table with MethodInfo as a key#1961
sanych-sun wants to merge 4 commits intomongodb:mainfrom
sanych-sun:csharp5959

Conversation

@sanych-sun
Copy link
Copy Markdown
Member

@sanych-sun sanych-sun commented Apr 22, 2026

The idea of the PR is to replace the switch by string method's name and checking of methodInfo, with the dictionary of deducers by method info. Most of the use-cases is covered by "static" registration, however there are number of use-cases where we duck-typing the method call (see CreateDynamicSerializerDeducer method), in such case we do dynamic registration as we go: so the next translation of the method will use "previously registered deducer" and do not need to go through all checks.

Copilot AI review requested due to automatic review settings April 22, 2026 21:09
@sanych-sun sanych-sun requested a review from a team as a code owner April 22, 2026 21:09
@sanych-sun sanych-sun requested a review from ajcvickers April 22, 2026 21:09
}
}

// TODO: merge this and next methods.
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll create a ticket for this, as these 2 methods looks like doing the same stuff.

@sanych-sun sanych-sun requested a review from adelinowona April 22, 2026 21:11
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR refactors LINQ3 serializer deduction for MethodCallExpression nodes by replacing a large name-based switch with a MethodInfo-keyed lookup table (plus a small dynamic fallback) to improve maintainability and correctness around overload resolution.

Changes:

  • Replaced switch (node.Method.Name) in SerializerFinderVisitor.VisitMethodCall with a MethodInfo -> deducer registry (including caching and generic-method normalization).
  • Added new StringMethod reflection entries for string.Equals instance/static variants and updated registrations accordingly.
  • Introduced EnumerableMethod.IsContainsMethod(MethodInfo) to support dynamic detection of Contains methods.

Reviewed changes

Copilot reviewed 4 out of 5 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
src/MongoDB.Driver/Linq/Linq3Implementation/SerializerFinders/SerializerFinderVisitMethodCall.cs Major refactor: method serializer deduction now uses a MethodInfo lookup table with dynamic fallback and caching.
src/MongoDB.Driver/Linq/Linq3Implementation/SerializerFinders/SerializerFinderHelperMethods.cs Adds a TODO comment around helper-method duplication.
src/MongoDB.Driver/Linq/Linq3Implementation/Reflection/StringMethod.cs Adds reflection MethodInfos for string.Equals (instance + static) and exposes them.
src/MongoDB.Driver/Linq/Linq3Implementation/Reflection/EnumerableOrQueryableMethod.cs Removes the AnyOverloads set (now uses Any/AnyWithPredicate sets directly).
src/MongoDB.Driver/Linq/Linq3Implementation/Reflection/EnumerableMethod.cs Adds IsContainsMethod(MethodInfo) to support dynamic Contains deduction.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +539 to +545
for (var i = 1; i <= expression.Arguments.Count; i++)
{
var argumentExpression = expression.Arguments[i];
if (visitor.IsNotKnown(argumentExpression))
{
var itemSerializer = tupleSerializer.GetItemSerializer(i);
if (i == 8)
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will investigate.

}

void DeduceCompareOrCompareToMethodSerializers()
// DeduceAddToSetMethodSerializers
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've left such comments so for now, for review purposes. So it would be easier to find where the implementation came from. I'll remove them before merging.


void DeduceCompareOrCompareToMethodSerializers()
// DeduceAddToSetMethodSerializers
private static void DeduceAddToSetMethodSerializers(SerializerFinderVisitor visitor, MethodCallExpression expression)
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've moved all deducers from local method to static-class level methods, because codecov is struggling to show the code coverage for local methods. As the result I can see which deducers are not covered by tests. Probably I need to create more test cases to improve code coverage.

var method = node.Method;
var arguments = node.Arguments;
var methodInfo = node.Method.IsGenericMethod && !node.Method.ContainsGenericParameters ? node.Method.GetGenericMethodDefinition() : node.Method;
var deducer = MethodCallSerializerDeducers.GetSerializerDeducer(methodInfo);
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've decided to move all deducers implementation into private static class simply to clear the "entry" point, to have this method on the very top and visible.

RegisterSerializerDeducers(EnumerableOrQueryableMethod.ElementAtOverloads, (visitor, expression) => visitor.DeduceItemAndCollectionSerializers(expression, expression.Arguments[0]));
RegisterSerializerDeducers(EnumerableOrQueryableMethod.Except, DeduceExceptMethodSerializers);
// TODO: Definitely wrong registration copy-pasted from prev code, investigate before merge to main
// RegisterSerializerResolver(EnumerableMethod.First, DeduceSetWindowFieldsMethodSerializers);
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm about to investigate this problem. Will fix or remove the registration before merging the PR.

@sanych-sun sanych-sun added the improvement Optimizations or refactoring (no new features or fixes). label Apr 22, 2026
@sanych-sun sanych-sun marked this pull request as draft April 22, 2026 22:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

improvement Optimizations or refactoring (no new features or fixes).

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants