自定义 BSON 键值序列化器
Custom BSON Key Value Serializer
我 运行 在尝试将 class 转换为 BSON 文档时遇到了一些麻烦。
我有 Custom1
和 Custom2
,它们的行为应该有点不同。如何创建一个 "unfold" 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
}
如果您使用的是 2.0 或更高版本的驱动程序,您可以尝试将 class 变成 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();
并获得预期的格式。
对于如此复杂的序列化情况,您必须为您的 class.
实现自定义 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。
我 运行 在尝试将 class 转换为 BSON 文档时遇到了一些麻烦。
我有 Custom1
和 Custom2
,它们的行为应该有点不同。如何创建一个 "unfold" 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
}
如果您使用的是 2.0 或更高版本的驱动程序,您可以尝试将 class 变成 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();
并获得预期的格式。
对于如此复杂的序列化情况,您必须为您的 class.
实现自定义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。