MongoDB序列化字典〈MyEnum,object>

ni65a41a  于 2022-12-12  发布在  Go
关注(0)|答案(4)|浏览(205)

我有一个带有Dictionary<MyEnum, object>的模型。当我试图用C#驱动程序插入mongoDB时,出现了一个异常,并显示以下消息:
使用DictionaryRepresentation时.文档键值必须序列化为字符串.
当然,我可以添加属性[BsonDictionaryOptions(DictionaryRepresentation.ArrayOfArrays)],它也可以工作,但是我希望能够将枚举作为字符串持久化。

public MyEnum {
  A,
  B
}

[BsonDictionaryOptions(DictionaryRepresentation.Document)]
public Dictionary<MyEnum, object> MyData { get; set; }

我想在蒙戈有类似的东西,原因各不相同.

{
   "MyData": {
      "B": "xxxx",
      "A": "xxxx"
   }
}

对于单个枚举,我可以使用[BsonRepresentation(BsonType.String)]属性,但是如何告诉字典的驱动程序将枚举键序列化为字符串呢?

zqdjd7g9

zqdjd7g91#

问题是字典序列化程序不强制键为字符串类型。若要解决此问题,请创建您自己的序列化程序,并使用BsonSerializer属性选择它。

public class EnumDictionarySerializer<TKey, TDictionary> : DictionarySerializerBase<TDictionary> 
    where TKey : struct, Enum
    where TDictionary : class, IDictionary, new()
{
    public EnumDictionarySerializer():base(DictionaryRepresentation.Document, new EnumSerializer<TKey>(BsonType.String), new ObjectSerializer())
    {

    }

    protected override TDictionary CreateInstance()
    {
        return new TDictionary();
    }
}
wmtdaxz3

wmtdaxz32#

基于@Hugh.沃尔什的答案,我创建了一个灵活的DictionarySerializer,它可以使用键和值的序列化程序进行配置。

public class DictionarySerializer<TDictionary, KeySerializer, ValueSerializer> : DictionarySerializerBase<TDictionary>
    where TDictionary : class, IDictionary, new()
    where KeySerializer : IBsonSerializer, new()
    where ValueSerializer : IBsonSerializer, new()
{
    public DictionarySerializer() : base(DictionaryRepresentation.Document, new KeySerializer(), new ValueSerializer())
    {
    }

    protected override TDictionary CreateInstance()
    {
        return new TDictionary();
    }
}

public class EnumStringSerializer<TEnum> : EnumSerializer<TEnum>
    where TEnum : struct
{
    public EnumStringSerializer() : base(BsonType.String) { }
}

用法如下,其中key和value都是枚举类型,但可以是任何类型:

[BsonSerializer(typeof(DictionarySerializer<
        Dictionary<MyEnumA, MyEnumB>, 
        EnumStringSerializer<MyEnumA>,
        EnumStringSerializer<MyEnumB>>))]
    public Dictionary<MyEnumA, MyEnumB> FeatureSettings { get; set; }
ibrsph3r

ibrsph3r3#

此答案对于注解来说太长,但它引用了注解。
这将需要在程序运行时反射来更改此对象的类型。首先,这是一个非常糟糕的主意,其次,这将非常缓慢。
我建议您使用字典实现来实现此目的,或者使用扩展类:
第一个

0tdrvxhp

0tdrvxhp4#

在Hugh.沃尔什回答的基础上,我在这里尝试获得一个要序列化的Dictionary<MyEnum, string>字段...

[BsonSerializer(typeof(FiltersSerializer))]
public Dictionary<MyEnum, string> Filters { get; set; } = new ();

...

public class FiltersSerializer: DictionarySerializerBase<Dictionary<MyEnum, string>>
{
    public FiltersSerializer(): base(DictionaryRepresentation.Document, new EnumSerializer<MyEnum>(BsonType.String), new StringSerializer())
    {
    }
 
    protected override Dictionary<MyEnum, string> CreateInstance()
    {
        return new Dictionary<MyEnum, string>();
    }
}

**EDIT:**但我也刚刚了解到,在初始化时使用此调用可以实现相同得结果...

MongoDB.Bson.Serialization.BsonSerializer.RegisterSerializer(
                    new EnumSerializer<MyEnum>(MongoDB.Bson.BsonType.String));

相关问题