MongoDB序列化词典<myenum,object>

时间:2016-05-02 17:33:08

标签: c# mongodb dictionary serialization

我有一些[BsonDictionaryOptions(DictionaryRepresentation.ArrayOfArrays)]的模型。 当我尝试使用C#驱动程序插入mongoDB时,会出现异常,并显示以下消息:

  

使用DictionaryRepresentation.Document时,键值必须序列化为字符串。

当然,我可以添加属性public MyEnum { A, B } [BsonDictionaryOptions(DictionaryRepresentation.Document)] public Dictionary<MyEnum, object> MyData { get; set; } 并且它可以工作,但我希望能够将枚举作为字符串保存。

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

我想在mongo中出现类似的东西,原因不同。

[BsonRepresentation(BsonType.String)]

对于单个枚举,我只能使用#balloon-circle { width: 150px; height: 150px; background: rgb(255,100,100); -moz-border-radius: 150px; -webkit-border-radius: 150px; border-radius: 150px; top:5px; } 属性,但是如何告诉驱动程序字典将枚举密钥序列化为字符串?

3 个答案:

答案 0 :(得分:4)

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

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

    }

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

答案 1 :(得分:1)

这个答案对于评论来说太长了,但它引用了评论。

这需要反射来在程序运行时更改此对象的类型。起初这是一个非常糟糕的主意,第二,这将是非常缓慢的。

我建议您为此目的使用字典实现或使用扩展类:

public MyEnum {
  A,
  B
}

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

public class MyDictionary<T1,T2,T3> : IDictionary{
    Dictionary<T1, T3> Dict = new Dictionary<T1, T3>();
    //implement dictionary...
}
public static class ExtentionsDictionary<T1,T2>{
    public static T2 Get(this IDictionary dict, MyEnum enum){
    var key = enum.ToString();
    return dict[key];
    }
    //Rest of the implementation
}

答案 2 :(得分:1)

基于@ Hugh.walsh的答案,我创建了一个灵活的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) { }
}

这样的用法,其中键和值都是枚举类型,但是可以是任何类型:

    [BsonSerializer(typeof(DictionarySerializer<
        Dictionary<FeatureToggleTypeEnum, LicenseFeatureStateEnum>, 
        EnumStringSerializer<FeatureToggleTypeEnum>,
        EnumStringSerializer<LicenseFeatureStateEnum>>))]
    public Dictionary<FeatureToggleTypeEnum, LicenseFeatureStateEnum> FeatureSettings { get; set; }