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());