有没有一种方法可以将Enum存储为字符串名称而不是序号值?
示例如下:
假设我有这个枚举:
public enum Gender
{
Female,
Male
}
字符串
现在,如果某个虚构的用户存在
...
Gender gender = Gender.Male;
...
型
它将被存储在MongoDb数据库中为{...“性别”:1...}
但我更喜欢这样的东西{...“性别”:“男”……}
这可能吗?自定义Map,反射技巧,无论什么。
我的上下文:我在POCO上使用强类型集合(好吧,我标记AR并偶尔使用多态性)。我有一个工作单元形式的瘦数据访问抽象层。所以我没有序列化/反序列化每个对象,但我可以(并且确实)定义一些ClassMap。我使用官方的MongoDb驱动程序+ fluent-mongodb。
9条答案
按热度按时间bttbmeg01#
字符串
p8ekf7hl2#
MongoDB .NET驱动程序lets you apply conventions,用于确定如何处理CLR类型和数据库元素之间的某些Map。
如果你想将其应用于所有枚举,你只需要为每个AppDomain设置一次约定(通常在启动应用程序时),而不是将属性添加到所有类型或手动Map每个类型:
字符串
rkue9o1l3#
可以为包含枚举的类自定义类Map,并指定成员由字符串表示。这将处理枚举的序列化和反序列化。
字符串
我仍然在寻找一种方法来指定枚举全局表示为字符串,但这是我目前使用的方法。
uujelgoq4#
我发现在某些情况下,仅仅应用Ricardo Rodriguez' answer不足以将枚举值正确序列化到MongoDb中:
字符串
如果你的数据结构涉及到将枚举值装箱到对象中,MongoDb序列化将不会使用集合
EnumRepresentationConvention
来序列化它。事实上,如果你看一下MongoDb驱动程序的ObjectSerializer的实现,它会解析装箱值的
TypeCode
(Int32
用于枚举值),并使用该类型将枚举值存储在数据库中。因此,装箱的枚举值最终被序列化为int
值。在反序列化时,它们也将保持为int
值。要改变这一点,可以编写一个自定义的
ObjectSerializer
,如果装箱的值是一个枚举,它将强制设置EnumRepresentationConvention
。大概是这样的:型
然后将自定义序列化程序设置为用于序列化对象的序列化程序:
型
这样做将确保装箱的枚举值将像未装箱的枚举值一样存储为字符串。
但是请记住,在反序列化文档时,装箱的值将保持为字符串。它不会被转换回原始枚举值。如果需要将字符串转换回原始枚举值,则可能必须在文档中添加一个判别字段,以便序列化程序可以知道要反序列化的枚举类型是什么。
一种方法是存储一个bson文档而不仅仅是一个字符串,其中的识别字段(
_t
)和值字段(_v
)将用于存储枚举类型及其字符串值。cigdeys35#
在驱动程序2.x中,我使用特定的串行器解决了这个问题:
字符串
6jygbczu6#
使用MemberSerializationOptionsConvention定义枚举保存的约定。
字符串
gwbalxhn7#
如果您使用的是.NET Core 3.1及更高版本,请使用Microsoft最新的超快Json Serializer/Deserializer,System.Text.Json(https://www.nuget.org/packages/System.Text.Json)。
请参阅https://medium.com/@samichkhachkhi/system-text-json-vs-newtonsoft-json-d01935068143上的指标比较
字符串
68bkxrlz8#
这里给出的答案适用于
TEnum
和TEnum[]
,但不适用于Dictionary<TEnum, object>
。您可以在使用代码初始化序列化程序时实现这一点,但我想通过属性来实现这一点。我已经创建了一个灵活的DictionarySerializer
,可以使用键和值的序列化器对其进行配置。字符串
像这样的用法,其中键和值都是枚举类型,但可以是序列化器的任何组合:
型
bejyjqdl9#
.NET 7.0
改进@sboisse非常好的答案,我已经找到了一种满足我所有用例的方法。
通用枚举序列化器
个字符
注册assembly中的每个enum
型
备注: