我发现仅在某些情况下仅应用Ricardo Rodriguez的答案不足以正确地将枚举值序列化为String到MongoDb中:
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
)存储枚举类型及其字符串值。