很遗憾,这个PR已被关闭,不会进行修复。 https://github.com/mongodb/mongo-csharp-driver/pull/305#issuecomment-731475503。
虽然给出了好的理由,但我认为人们希望做这样的事情,所以,根据你跳过障碍的意愿不同,你可以尝试(.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 { }
}
现在你可以在大多数原本需要使用 TEnum
的地方使用 EnumWrapper<TEnum>
,它会按照你的期望工作。如果不注册序列化提供程序,它将会序列化为嵌套对象,因此在进行任何操作之前,你应该调用以下内容:
BsonSerializer.RegisterSerializationProvider(new EnumWrapperBsonSerializationProvider())