Alas this PR has been closed as won't fix. https://github.com/mongodb/mongo-csharp-driver/pull/305#issuecomment-731475503.
Good reasons are given for this, but it is the kind of thing that I think people want to do, so depending on your appetite for jumping through hoops you can try this (.NET 5):
using System;
using System.Collections.Generic;
using System.Reflection;
using MongoDB.Bson.Serialization;
using MongoDB.Bson.Serialization.Attributes;
public sealed class EnumWrapper<TEnum>
where TEnum : struct, Enum
{
[BsonConstructor]
public EnumWrapper(TEnum value) => this.Value = value;
public TEnum Value { get; }
public static readonly IBsonSerializer<EnumWrapper<TEnum>> Serializer = new BsonSerializerImpl();
public static implicit operator TEnum(EnumWrapper<TEnum> wrapper) => wrapper.Value;
public static implicit operator EnumWrapper<TEnum>(TEnum value) => new(value);
public override bool Equals(object obj) =>
obj is EnumWrapper<TEnum> wrapper
&& EqualityComparer<TEnum>.Default.Equals(this.Value, wrapper.Value);
public override int GetHashCode() => HashCode.Combine(this.Value);
public override string ToString() => this.Value.ToString();
private class BsonSerializerImpl : IBsonSerializer<EnumWrapper<TEnum>>
{
public Type ValueType => typeof(EnumWrapper<TEnum>);
public void Serialize(BsonSerializationContext context, BsonSerializationArgs args, EnumWrapper<TEnum> value) =>
context.Writer.WriteString(((TEnum)value).ToString());
public void Serialize(BsonSerializationContext context, BsonSerializationArgs args, object value) =>
this.Serialize(context, args, (EnumWrapper<TEnum>)value);
object IBsonSerializer.Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args) =>
this.Deserialize(context, args);
public EnumWrapper<TEnum> Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args) =>
Enum.Parse<TEnum>(context.Reader.ReadString());
}
}
public class EnumWrapperBsonSerializationProvider : IBsonSerializationProvider
{
public IBsonSerializer GetSerializer(Type type)
{
if (!type.IsGenericType)
{
return null;
}
var typeDefinition = type.GetGenericTypeDefinition();
if (typeDefinition != typeof(EnumWrapper<>))
{
return null;
}
var field = type.GetField(nameof(EnumWrapper<Hack>.Serializer), BindingFlags.Public | BindingFlags.Static);
return (IBsonSerializer)field.GetValue(null);
}
private enum Hack { }
}
Now you can use EnumWrapper<TEnum>
mostly wherever you would normally use TEnum
and it will do what you want. If you don't register the serialization provider it will serialize as nested objects, so before doing anything you should call this:
BsonSerializer.RegisterSerializationProvider(new EnumWrapperBsonSerializationProvider());