处理 MongoDb 的可空类型和不可空类型的自定义序列化程序
Custom serializer that processes both nullable and not nullable types for MongoDb
我需要使用 IBsonSerializer 实现自定义序列化程序。
我就是这么做的:
internal class MyCustomDateTimeSerializer : IBsonSerializer
{
public object Deserialize(BsonDeserializationContext context,
BsonDeserializationArgs args)
{
// Deserialization logic
}
public void Serialize(BsonSerializationContext context,
BsonSerializationArgs args, object value)
{
// Serialization logic
}
public Type ValueType => typeof(DateTime);
}
然后在BsonSerializerAttribute中使用:
[BsonSerializer(typeof(MyCustomDateTimeSerializer))]
我的问题是我想 Serialize/Deserialize DateTime 和 Nullable DateTime。
我的 CustomSerializer 的 ValueType 设置为 typeof(DateTime),因此我得到如下异常:
Value type of serializer is System.DateTime and does not match member type System.Nullable`1[[System.DateTime..
我没有找到解决此问题的方法。
当然,我可以为 Nullable DateTime 和 DateTime 创建两个不同的 类,但也许还有其他选择?
如果您查看 MongoDB.Bson 库中 SetSerializer 方法的源代码,您会发现它对成员类型的检查非常简单:
if (serializer.ValueType != _memberType)
{
var message = string.Format("Value type of serializer is {0} and does not match member type {1}.", serializer.ValueType.FullName, _memberType.FullName);
throw new ArgumentException(message, "serializer");
}
代码检查类型相等性,没有办法欺骗它并认为 DateTime
和 Nullable<DateTime>
相等。
但是,您可以使用一种解决方案来拥有一个序列化程序 class 并避免重复代码。你可以让你的序列化器成为通用的 class 并强制它只接受 DateTime
或 Nullable<DateTime>
作为类型参数。
这是一个示例:
internal class MyCustomDateTimeSerializer<TDateTime> : IBsonSerializer
{
static MyCustomDateTimeSerializer()
{
if (typeof(TDateTime) != typeof(DateTime) && typeof(TDateTime) != typeof(DateTime?))
{
throw new InvalidOperationException($"MyCustomDateTimeSerializer could be used only with {nameof(DateTime)} or {nameof(Nullable<DateTime>)}");
}
}
public object Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args)
{
// Deserialization logic
}
public void Serialize(BsonSerializationContext context, BsonSerializationArgs args, object value)
{
// Serialization logic
}
public Type ValueType => typeof(TDateTime);
}
public class SomeDocument
{
// ...
[BsonSerializer(typeof(MyCustomDateTimeSerializer<DateTime>))]
public DateTime Date1 { get; set; }
[BsonSerializer(typeof(MyCustomDateTimeSerializer<DateTime?>))]
public DateTime? Date2 { get; set; }
}
我需要使用 IBsonSerializer 实现自定义序列化程序。
我就是这么做的:
internal class MyCustomDateTimeSerializer : IBsonSerializer
{
public object Deserialize(BsonDeserializationContext context,
BsonDeserializationArgs args)
{
// Deserialization logic
}
public void Serialize(BsonSerializationContext context,
BsonSerializationArgs args, object value)
{
// Serialization logic
}
public Type ValueType => typeof(DateTime);
}
然后在BsonSerializerAttribute中使用:
[BsonSerializer(typeof(MyCustomDateTimeSerializer))]
我的问题是我想 Serialize/Deserialize DateTime 和 Nullable DateTime。
我的 CustomSerializer 的 ValueType 设置为 typeof(DateTime),因此我得到如下异常:
Value type of serializer is System.DateTime and does not match member type System.Nullable`1[[System.DateTime..
我没有找到解决此问题的方法。 当然,我可以为 Nullable DateTime 和 DateTime 创建两个不同的 类,但也许还有其他选择?
如果您查看 MongoDB.Bson 库中 SetSerializer 方法的源代码,您会发现它对成员类型的检查非常简单:
if (serializer.ValueType != _memberType)
{
var message = string.Format("Value type of serializer is {0} and does not match member type {1}.", serializer.ValueType.FullName, _memberType.FullName);
throw new ArgumentException(message, "serializer");
}
代码检查类型相等性,没有办法欺骗它并认为 DateTime
和 Nullable<DateTime>
相等。
但是,您可以使用一种解决方案来拥有一个序列化程序 class 并避免重复代码。你可以让你的序列化器成为通用的 class 并强制它只接受 DateTime
或 Nullable<DateTime>
作为类型参数。
这是一个示例:
internal class MyCustomDateTimeSerializer<TDateTime> : IBsonSerializer
{
static MyCustomDateTimeSerializer()
{
if (typeof(TDateTime) != typeof(DateTime) && typeof(TDateTime) != typeof(DateTime?))
{
throw new InvalidOperationException($"MyCustomDateTimeSerializer could be used only with {nameof(DateTime)} or {nameof(Nullable<DateTime>)}");
}
}
public object Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args)
{
// Deserialization logic
}
public void Serialize(BsonSerializationContext context, BsonSerializationArgs args, object value)
{
// Serialization logic
}
public Type ValueType => typeof(TDateTime);
}
public class SomeDocument
{
// ...
[BsonSerializer(typeof(MyCustomDateTimeSerializer<DateTime>))]
public DateTime Date1 { get; set; }
[BsonSerializer(typeof(MyCustomDateTimeSerializer<DateTime?>))]
public DateTime? Date2 { get; set; }
}