Dem*_*nia 7 c# serialization dictionary mongodb
我有一些模型Dictionary<MyEnum, object>。当我尝试使用 C# 驱动程序插入 mongoDB 时,出现以下消息的异常:
使用 DictionaryRepresentation.Document 时,键值必须序列化为字符串。
当然,我可以添加属性[BsonDictionaryOptions(DictionaryRepresentation.ArrayOfArrays)]并且它可以工作,但我希望能够将枚举作为字符串持久化。
public MyEnum {
A,
B
}
[BsonDictionaryOptions(DictionaryRepresentation.Document)]
public Dictionary<MyEnum, object> MyData { get; set; }
Run Code Online (Sandbox Code Playgroud)
由于不同的原因,我想在 mongo 中拥有类似的东西。
{
"MyData": {
"B": "xxxx",
"A": "xxxx"
}
}
Run Code Online (Sandbox Code Playgroud)
对于单个枚举,我只能使用该[BsonRepresentation(BsonType.String)]属性,但是如何告诉驱动程序以获取字典将枚举键序列化为字符串?
小智 5
问题是字典序列化器不会强制键为字符串类型。要解决此问题,请创建您自己的序列化程序并使用 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();
}
}
Run Code Online (Sandbox Code Playgroud)
基于@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) { }
}
Run Code Online (Sandbox Code Playgroud)
像这样的用法,其中键和值都是枚举类型,但可以是任何类型:
[BsonSerializer(typeof(DictionarySerializer<
Dictionary<MyEnumA, MyEnumB>,
EnumStringSerializer<MyEnumA>,
EnumStringSerializer<MyEnumB>>))]
public Dictionary<MyEnumA, MyEnumB> FeatureSettings { get; set; }
Run Code Online (Sandbox Code Playgroud)
这个答案对于评论来说太长了,但它引用了一条评论。
这需要在程序运行时进行反射来更改该对象的类型。起初这是一个非常糟糕的主意,其次这会非常慢。
我建议您为此目的使用字典实现或使用扩展类:
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...
}
Run Code Online (Sandbox Code Playgroud)
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
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
4443 次 |
| 最近记录: |