我发现在某些情况下仅应用 Ricardo Rodriguez' answer 不足以正确序列化枚举值以字符串到 MongoDb:
// Set up MongoDB conventions
var pack = new ConventionPack
{
new EnumRepresentationConvention(BsonType.String)
};
ConventionRegistry.Register("EnumStringConvention", pack, t => true);
如果您的数据结构涉及将枚举值装箱到对象中,则 MongoDb 序列化将不会使用集合 EnumRepresentationConvention 对其进行序列化。
确实,如果您查看 MongoDb 驱动程序的ObjectSerializer 的实现,它将解析装箱值的TypeCode(Int32 用于枚举值),并使用该类型将您的枚举值存储在数据库中.所以盒装的枚举值最终被序列化为int 值。它们在反序列化时也将保留为 int 值。
要改变这一点,可以编写一个自定义的ObjectSerializer,如果装箱的值是一个枚举,它将强制设置EnumRepresentationConvention。像这样的:
public class ObjectSerializer : MongoDB.Bson.Serialization.Serializers.ObjectSerializer
{
public override void Serialize(BsonSerializationContext context, BsonSerializationArgs args, object value)
{
var bsonWriter = context.Writer;
if (value != null && value.GetType().IsEnum)
{
var conventions = ConventionRegistry.Lookup(value.GetType());
var enumRepresentationConvention = (EnumRepresentationConvention) conventions.Conventions.FirstOrDefault(convention => convention is EnumRepresentationConvention);
if (enumRepresentationConvention != null)
{
switch (enumRepresentationConvention.Representation)
{
case BsonType.String:
value = value.ToString();
bsonWriter.WriteString(value.ToString());
return;
}
}
}
base.Serialize(context, args, value);
}
}
然后将自定义序列化程序设置为用于序列化对象的序列化程序:
BsonSerializer.RegisterSerializer(typeof(object), new ObjectSerializer());
这样做将确保装箱的枚举值将像未装箱的枚举值一样存储为字符串。
但请记住,在反序列化文档时,装箱的值将保持为字符串。它不会被转换回原来的枚举值。如果您需要将字符串转换回原始枚举值,则可能必须在文档中添加一个区分字段,以便序列化程序可以知道要反序列化的枚举类型是什么。
一种方法是存储一个 bson 文档而不仅仅是一个字符串,其中区分字段 (_t) 和值字段 (_v) 将用于存储枚举类型及其字符串值。