MongoDb C#驱动程序-序列化列表<;enum>;作为字符串[]

MongoDb C#驱动程序-序列化列表<;enum>;作为字符串[],c#,mongodb,serialization,enums,C#,Mongodb,Serialization,Enums,我有一个类,其属性类型为List。大概是这样的: public enum MyEnum { A, B } public class MyClass { public string Id { get; set; } public List<MyEnum> Values { get; set; } } 不过,Values属性被序列化为int数组(简单的枚举属性被正确地处理为int)。似乎在列表序列化的上下文中没有使用约定 如何强制序列化程序编写字符串而不是in

我有一个类,其属性类型为
List
。大概是这样的:

public enum MyEnum
{
  A,
  B
}

public class MyClass
{
    public string Id { get; set; }
    public List<MyEnum> Values { get; set; }
}
不过,
Values
属性被序列化为int数组(简单的枚举属性被正确地处理为int)。似乎在列表序列化的上下文中没有使用约定


如何强制序列化程序编写字符串而不是int?

不要调用
ConventionRegistry.Register()
,而是将数据注释
[BsonRepresentation(BsonType.String)]
添加到MyClass的属性
值中

public class MyClass
{
    public string Id { get; set; }

    [BsonRepresentation(BsonType.String)] 
    public List<MyEnum> Values { get; set; }
}

唉,由于无法修复,此PR已关闭

对此给出了很好的理由,但我认为这是人们想要做的事情,因此,根据您对跳圈的兴趣,您可以尝试以下方法(.NET 5):


我刚刚在上为该主题创建了一个问题,同时也创建了一个相应的PR,提供了所需的修复/改进:你就是那个人!谢谢。不客气。让我们看看它是否被合并。它工作得完美无缺。感谢您的解决方案,等待@dnikless的PR投入生产。
public class MyClass
{
    public string Id { get; set; }

    [BsonRepresentation(BsonType.String)] 
    public List<MyEnum> Values { get; set; }
}
{
    "_id" : "1",
    "Values" : [ 
        "A", 
        "B"
    ]
}
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 { }
}
BsonSerializer.RegisterSerializationProvider(new EnumWrapperBsonSerializationProvider());