Explicit Type Conversion Not Supported in LinqProvider.V3?

Hi!

While migrating from LinqProvider.V2 to LinqProvider.V3, I encountered the following issue. I have a custom value type UserId, which includes explicit conversion operators for Guid. The following query worked fine in LinqProvider.V2, but after switching to LinqProvider.V3, it throws an exception:

var user = await collection.Find(Builders<User>.Filter.In(x => (Guid)x.ExternalId, new[] { guid }))
    .FirstOrDefaultAsync();

Exception:

MongoDB.Driver.Linq.ExpressionNotSupportedException : Expression not supported: Convert(x.ExternalId, Guid).

Are there any workarounds for this issue in LinqProvider.V3?
Any suggestions would be appreciated!


Full Reproduction Code:

using System;
using System.Threading.Tasks;
using MongoDB.Bson;
using MongoDB.Bson.Serialization;
using MongoDB.Bson.Serialization.Attributes;
using MongoDB.Bson.Serialization.Serializers;
using MongoDB.Driver;
using MongoDB.Driver.Linq;
using NUnit.Framework;

namespace MongoCases
{
    [TestFixture]
    public class MongoCases_Linq3_ExplicitConversion : Mongo2GoFixture
    {
        [Test]
        public async Task Test()
        {
            BsonSerializer.RegisterSerializer(new UserIdBsonSerializer());

            var mongoClientSettings = MongoClientSettings.FromConnectionString(ConnectionString);
            mongoClientSettings.LinqProvider = LinqProvider.V3;

            var mongoClient = new MongoClient(mongoClientSettings);

            var db = mongoClient.GetDatabase(Guid.NewGuid().ToString()[..8]);

            var collection = db.GetCollection<User>("users");

            var guid = Guid.NewGuid();

            await collection.InsertOneAsync(new User { ExternalId = (UserId)guid });

            var user = await collection.Find(Builders<User>.Filter.In(x => (Guid)x.ExternalId, new[] { guid }))
                .FirstOrDefaultAsync();

            // MongoDB.Driver.Linq.ExpressionNotSupportedException : Expression not supported: Convert(x.ExternalId, Guid).

            Assert.That(user, Is.Not.Null);
        }

        private class User
        {
            [BsonId]
            public ObjectId Id { get; set; }

            [BsonElement("externalId")]
            public UserId ExternalId { get; set; }
        }

        private readonly struct UserId
        {
            private readonly Guid _id;

            public UserId(Guid id)
            {
                _id = id;
            }

            public static explicit operator Guid(UserId source) => source._id;
            public static explicit operator UserId(Guid id) => new UserId(id);
        }

        private class UserIdBsonSerializer : StructSerializerBase<UserId>
        {
            private readonly GuidSerializer _guidSerializer = new GuidSerializer();

            public override UserId Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args) =>
                new UserId(_guidSerializer.Deserialize(context, args));

            public override void Serialize(BsonSerializationContext context, BsonSerializationArgs args,
                UserId value) =>
                _guidSerializer.Serialize(context, args, (Guid)value);
        }
    }
}

I know that I can slightly rewrite the query like this:

var user = await collection.Find(Builders<User>.Filter.In(x => x.ExternalId, new[] { guid }.Select(x => (UserId)guid))).FirstOrDefaultAsync();

However, there are many similar queries across different projects, so I’d prefer not to rewrite all of them.

Is there a way to globally allow explicit casting for certain types in LinqProvider.V3?