解决MySql布尔型新旧版本兼容问题,采用枚举来表示布尔型的数据表。由正向工程赋值
大石头 authored at 2018-05-15 21:21:05
3.04 KiB
X
#if NET5_0_OR_GREATER
using System.Diagnostics.CodeAnalysis;
using System.Text.Json;
using System.Text.Json.Serialization;
using NewLife.Collections;

namespace NewLife.Serialization;

/// <summary>IDictionarySource 接口的 System.Text.Json 序列化转换器</summary>
/// <remarks>
/// 实现 <see cref="IDictionarySource"/> 的对象在序列化时,调用 <see cref="IDictionarySource.ToDictionary"/>
/// 获取字典后写入,而非遍历对象公共属性。与 FastJson 中 <c>WriteObject</c> 对 IDictionarySource 的检测行为一致。
/// 反序列化不支持,因为 IDictionarySource 是单向(对象→字典)接口。
/// </remarks>
public class IDictionarySourceConverter : JsonConverter<Object>
{
    /// <summary>是否可转换。目标类型实现 IDictionarySource,且原值不是已为字典的类型</summary>
    /// <param name="typeToConvert"></param>
    /// <returns></returns>
    public override Boolean CanConvert(Type typeToConvert)
    {
        if (!typeof(IDictionarySource).IsAssignableFrom(typeToConvert)) return false;

        // 已是字典类型的不需要此转换器,避免双重序列化
        if (typeToConvert.IsGenericType)
        {
            var genericDef = typeToConvert.GetGenericTypeDefinition();
            if (genericDef == typeof(IDictionary<,>) || genericDef == typeof(Dictionary<,>))
                return false;
        }

        return true;
    }

    /// <summary>读取。不支持,IDictionarySource 是单向接口</summary>
    /// <param name="reader"></param>
    /// <param name="typeToConvert"></param>
    /// <param name="options"></param>
    /// <returns></returns>
    /// <exception cref="NotSupportedException"></exception>
    public override Object Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
        => throw new NotSupportedException($"IDictionarySource 接口不支持反序列化。目标类型:{typeToConvert.FullName}");

    /// <summary>写入。调用 ToDictionary() 获取字典后序列化</summary>
    /// <param name="writer"></param>
    /// <param name="value"></param>
    /// <param name="options"></param>
    [UnconditionalSuppressMessage("Trimming", "IL2026", Justification = "字典源对象与未命中转换器的回退均按运行时类型序列化,元数据无法静态表达;AOT 应用应通过 SystemJson 上下文透传声明类型元数据")]
    [UnconditionalSuppressMessage("AOT", "IL3050", Justification = "字典源对象与未命中转换器的回退均按运行时类型序列化,元数据无法静态表达;AOT 应用应通过 SystemJson 上下文透传声明类型元数据")]
    public override void Write(Utf8JsonWriter writer, Object value, JsonSerializerOptions options)
    {
        if (value is IDictionarySource source)
        {
            var dic = source.ToDictionary();
            JsonSerializer.Serialize(writer, dic, typeof(IDictionary<String, Object?>), options);
        }
        else
        {
            JsonSerializer.Serialize(writer, value, value.GetType(), options);
        }
    }
}
#endif