我有一个带有一些Dictionary<MyEnum, object>
的模型。当我尝试用C#驱动程序插入mongoDB时,出现了一个异常,显示以下消息:
使用DictionaryRepresentation.Document键值必须序列化为字符串。
当然,我可以添加属性[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)]
属性,但如何告诉字典的驱动程序将枚举键序列化为字符串?
问题是字典序列化程序没有强制键为字符串类型。为了解决这个问题,创建一个自己的序列化程序,并使用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();
}
}
基于@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<MyEnumA, MyEnumB>,
EnumStringSerializer<MyEnumA>,
EnumStringSerializer<MyEnumB>>))]
public Dictionary<MyEnumA, MyEnumB> FeatureSettings { get; set; }
这个答案对于注释来说太长了,但它引用了一个注释。
这将需要在程序运行时进行反射以更改此对象的类型。一开始这是一个非常糟糕的主意,第二次这会非常缓慢。
我建议您将字典实现用于此目的,或者使用扩展类:
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
}
在Hugh.walsh答案的基础上,我试图获得一个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>();
}
}
编辑:但我也刚刚学会了在初始化时使用此调用可以获得相同的结果。。。
MongoDB.Bson.Serialization.BsonSerializer.RegisterSerializer(
new EnumSerializer<MyEnum>(MongoDB.Bson.BsonType.String));