C# Mongodb.Driver 自定义反序列化

本文介绍了如何在使用MongoDB.Driver查询数据时,通过实现IBsonMemberMapAttribute特性和自定义BsonSerializer,对特定字段进行类型转换和值运算,以适应数据结构变化的场景。
摘要由CSDN通过智能技术生成

目的,实现使用Mongodb.Driver查询获取数据时,实现字段的自定义(类型转换,值运算等)

实现方式

实现 IBsonMemberMapAttribute 特性类,在实现类中Apply 方法中设置自定义 IBsonSerializer 实现。然后在数据接收类中,给需要自定义反序列化方式的字段上添加实现的IBsonMemberMapAttribute特性。


一、示例代码

1.实现IBsonMemberMapAttribute

代码如下(示例):

using System;
using log4net;
using MongoDB.Bson;
using MongoDB.Bson.Serialization;

namespace Test.Entity.Attribute

{

  //自定义mogndb bson 字段特性类

  public class BsonFieldConverterAttribute : System.Attribute, IBsonMemberMapAttribute

  {

    public void Apply(BsonMemberMap memberMap)

    {

      memberMap.SetSerializer(new MileageBsonSerializer());

    }

  }

  

  /// <summary>

  /// 自定义mongdob bson 序列化解析器类

  /// mongodb 序列化 兼容处理

  /// </summary>

  public class MileageBsonSerializer : IBsonSerializer

  {

    private static readonly ILog log = LogManager.GetLogger(nameof(MileageBsonSerializer));

    public Type ValueType => typeof(double?);

    public object Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args)

    {

      IBsonReader reader = context.Reader;

      BsonType currentBsonType = reader.GetCurrentBsonType();

      switch (currentBsonType)

      {

        case BsonType.String:

          string value = reader.ReadString();

          return GetValue(value);

        case BsonType.Double:

          return reader.ReadDouble();

        case BsonType.Null:

          reader.SkipValue();// 缺少 解析数据时会报错

          return -1d;

        default:

          log.Error("MileageBsonSerializer 反序列化不包含类型:" + currentBsonType.ToString());

          reader.SkipValue();// 缺少 解析数据时会报错

          return -1d;

      }

      throw CreateCannotDeserializeFromBsonTypeException(currentBsonType);

    }

    protected Exception CreateCannotDeserializeFromBsonTypeException(BsonType bsonType)

    {

      return new FormatException($"Cannot deserialize a '{BsonUtils.GetFriendlyTypeName(ValueType)}' from BsonType '{bsonType}'.");

    }

    private double GetValue(string value)

    {

      if (value != null & value is string

        && !string.IsNullOrWhiteSpace(value)

        && (value).Contains("Km")

        && (value).Contains("-")

        )

      {

        string[] arr = (value).Replace("Km", "").Split('-');

        if (arr.Length > 1

          && double.TryParse(arr[0], out double start)

          && double.TryParse(arr[1], out double end))

        {

          return (start + end) / 2;

        }

      }

      return -1;

    }

    public void Serialize(BsonSerializationContext context, BsonSerializationArgs args, object value)

    {

      IBsonWriter writer = context.Writer;

      if (value != null)

        writer.WriteDouble((value as Nullable<double>) ?? -1);

      else

        writer.WriteNull();

    }

  }

2.实现IBsonSerializer

代码如下(示例):

/// <summary>

/// 自定义mongdob bson 序列化解析器类

/// mongodb 序列化 兼容处理

/// </summary>

public class MileageBsonSerializer : IBsonSerializer

{

  private static readonly ILog log = LogManager.GetLogger(nameof(MileageBsonSerializer));

  public Type ValueType => typeof(double?);

  public object Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args)

  {

    IBsonReader reader = context.Reader;

    BsonType currentBsonType = reader.GetCurrentBsonType();

    switch (currentBsonType)

    {

      case BsonType.String:

        string value = reader.ReadString();

        return GetValue(value);

      case BsonType.Double:

        return reader.ReadDouble();

      case BsonType.Null:

        reader.SkipValue();// 缺少 解析数据时会报错

        return -1d;

      default:

        log.Error("MileageBsonSerializer 反序列化不包含类型:" + currentBsonType.ToString());

        reader.SkipValue();// 缺少 解析数据时会报错

        return -1d;

    }

    throw CreateCannotDeserializeFromBsonTypeException(currentBsonType);

  }

  protected Exception CreateCannotDeserializeFromBsonTypeException(BsonType bsonType)

  {

    return new FormatException($"Cannot deserialize a '{BsonUtils.GetFriendlyTypeName(ValueType)}' from BsonType '{bsonType}'.");

  }

  private double GetValue(string value)

  {

    if (value != null & value is string

      && !string.IsNullOrWhiteSpace(value)

      && (value).Contains("Km")

      && (value).Contains("-")

      )

    {

      string[] arr = (value).Replace("Km", "").Split('-');

      if (arr.Length > 1

        && double.TryParse(arr[0], out double start)

        && double.TryParse(arr[1], out double end))

      {

        return (start + end) / 2;

      }

    }

    return -1;

  }

  public void Serialize(BsonSerializationContext context, BsonSerializationArgs args, object value)

  {

    IBsonWriter writer = context.Writer;

    if (value != null)

      writer.WriteDouble((value as Nullable<double>) ?? -1);

    else

      writer.WriteNull();

  }



}

}

该类命名空间与上一步相同


3.接收数据代码实体类

代码如下:

using Test.Entity.Attribute;
using MongoDB.Bson;

public class MilegaeModel

{
  public ObjectId _id {set;get;}

  [BsonFieldConverterAttribute]
  public double? mileage {set;get;}
}

4.mongodb数据库中数据存储格式

{
  "_id" : ObjectId("6596881f090dda00396d4ae3"),
  "mileage" : "337.5-393.8Km",
}

总结

本文中方法主要应用场景为,mongodb 中数据字段名称没变但字段类型发生变化后,需要考虑兼容的场景下。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值