我在尝试将类转换为BSON文档时遇到了一些麻烦。
我的Custom1
和Custom2
应该有所不同。如何创建一个“展开”KeyValuePair
的自定义序列化程序,以便生成预期结果(见下文)?您可以在下面看到代码示例以及预期结果。
此外,我正在使用Mongo BSON库来序列化对象。
public class UserData
{
public UserData()
{
Id = 100;
Name = "Superuser";
Custom1 = new KeyValuePair<string, double>("HelloWorld1", 1);
Custom2 = new KeyValuePair<string, double>("HelloWorld2", 2);
}
public int Id { get; set; }
public string Name { get; set; }
public KeyValuePair<string, double> Custom1 { get; set; }
public KeyValuePair<string, double> Custom2 { get; set; }
}
执行测试代码:
var userdata = new UserData();
var doc = userdata.ToBsonDocument();
目前的结果:
{
"Id": 100,
"Name": "Superuser",
"Custom1": {
"Key": "HelloWorld1",
"Value": 1
},
"Custom2": {
"Key": "HelloWorld2",
"Value": 2
}
}
预期结果:
{
"Id": 100,
"Name": "Superuser",
"HelloWorld1": 1,
"HelloWorld2": 2
}
答案 0 :(得分:2)
对于这种复杂的序列化案例,您必须为您的班级实现自定义IBsonSerializer
转换器。
以下是工作示例:
public class UserDataSerializer : SerializerBase<UserData>
{
public override void Serialize(BsonSerializationContext context, BsonSerializationArgs args, UserData value)
{
context.Writer.WriteStartDocument();
context.Writer.WriteName("Id");
context.Writer.WriteInt32(value.Id);
context.Writer.WriteName("Name");
context.Writer.WriteString(value.Name);
WriteKeyValue(context.Writer, value.Custom1);
WriteKeyValue(context.Writer, value.Custom2);
context.Writer.WriteEndDocument();
}
private void WriteKeyValue(IBsonWriter writer, KeyValuePair<string, double> kv)
{
writer.WriteName(kv.Key);
writer.WriteDouble(kv.Value);
}
public override UserData Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args)
{
//TODO: implement data deserialization using context.Reader
throw new NotImplementedException();
}
}
为了使它工作,你还需要以某种方式注册我们的UserDataSerializer
。 IBsonSerializationProvider
是实现这一目标的最简单方法。
public class UserDataSerializationProvider : IBsonSerializationProvider
{
public IBsonSerializer GetSerializer(Type type)
{
if (type == typeof(UserData)) return new UserDataSerializer();
return null;
}
}
最后我们可以使用它。
//register our serialization provider
BsonSerializer.RegisterSerializationProvider(new UserDataSerializationProvider());
var userdata = new UserData();
var doc = userdata.ToBsonDocument();
结果如下:
{ "Id" : 100, "Name" : "Superuser", "HelloWorld1" : 1.0, "HelloWorld2" : 2.0 }
您可能还想实施UserDataSerializer.Deserialize()
方法以提供向后转换。可以使用context.Reader
以相同的方式完成。
有关自定义序列化过程的详细信息,请参见here。
答案 1 :(得分:0)
如果您使用的是2.0或更高版本的驱动程序,您可以尝试将您的类变为DynamicObject,如下所示:
public class UserData : DynamicObject
{
public UserData()
{
Id = 100;
Name = "Superuser";
Custom1 = new KeyValuePair<string, double>("HelloWorld1", 1);
Custom2 = new KeyValuePair<string, double>("HelloWorld2", 2);
}
public id Id { get; set; }
public string Name { get; set; }
public KeyValuePair<string, double> Custom1 { get; set; }
public KeyValuePair<string, double> Custom2 { get; set; }
public override bool TryGetMember(
GetMemberBinder binder, out object result)
{
string name = binder.Name;
result = null;
if(name.Equals(Custom1.Key))
result = Custom1.Value;
else if(name.Equals(Custom2.Key))
result = Custom2.Value;
return result != null;
}
public override bool TrySetMember(
SetMemberBinder binder, object value)
{
string name = binder.Name;
if(name.Equals(Custom1.Key))
Custom1.Value = value;
else if(name.Equals(Custom2.Key))
Custom2.Value = value;
return name.Equals(Custom1.Key) ||
name.Equals(Custom2.Key);
}
}
根据发布文档,您应该能够这样做:
var userdata = new UserData();
var doc = ((dynamic) userdata).ToBsonDocument();
获得预期的格式。