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

namespace NewLife.Collections;

/// <summary>对象池接口</summary>
/// <remarks>
/// 文档 https://newlifex.com/core/object_pool
/// </remarks>
/// <typeparam name="T"></typeparam>
public interface IPool<T>
{
    /// <summary>对象池大小</summary>
    Int32 Max { get; set; }

    /// <summary>获取</summary>
    /// <returns></returns>
    T Get();

    /// <summary>异步获取</summary>
    /// <param name="cancellationToken"></param>
    /// <returns></returns>
    Task<T> GetAsync(CancellationToken cancellationToken = default);

    /// <summary>归还</summary>
    /// <param name="value"></param>
    [Obsolete("Please use Return from 2024-02-01")]
    Boolean Put(T value);

    /// <summary>归还</summary>
    /// <param name="value"></param>
    Boolean Return(T value);

    /// <summary>清空</summary>
    Int32 Clear();
}

/// <summary>对象池扩展</summary>
/// <remarks>
/// 文档 https://newlifex.com/core/object_pool
/// </remarks>
public static class Pool
{
    #region StringBuilder
    /// <summary>字符串构建器池</summary>
    public static IPool<StringBuilder> StringBuilder { get; set; } = new StringBuilderPool();

    /// <summary>归还一个字符串构建器到对象池</summary>
    /// <param name="sb">待归还实例</param>
    /// <param name="requireResult">是否返回结果字符串。true 将导致一次 <see cref="StringBuilder.ToString()"/> 分配</param>
    /// <returns>当 <paramref name="requireResult"/> 为 true 时返回构建结果,否则返回空字符串</returns>
    [Obsolete("Please use Return from 2024-02-01")]
    public static String Put(this StringBuilder sb, Boolean requireResult = false)
    {
        //if (sb == null) return null;

        var str = requireResult ? sb.ToString() : String.Empty;

        Pool.StringBuilder.Return(sb);

        return str;
    }

    /// <summary>归还一个字符串构建器到对象池</summary>
    /// <param name="sb">待归还实例</param>
    /// <param name="returnResult">是否返回结果字符串。true 将导致一次 <see cref="StringBuilder.ToString()"/> 分配</param>
    /// <returns>当 <paramref name="returnResult"/> 为 true 时返回构建结果,否则返回空字符串</returns>
    public static String Return(this StringBuilder sb, Boolean returnResult = true)
    {
        //if (sb == null) return null;

        var str = returnResult ? sb.ToString() : String.Empty;

        Pool.StringBuilder.Return(sb);

        return str;
    }

    /// <summary>字符串构建器池</summary>
    public class StringBuilderPool : Pool<StringBuilder>
    {
        /// <summary>初始容量。默认100个</summary>
        public Int32 InitialCapacity { get; set; } = 100;

        /// <summary>最大容量。超过该大小时不进入池内,默认4k</summary>
        public Int32 MaximumCapacity { get; set; } = 4 * 1024;

        /// <summary>实例化字符串构建器池。GC2时回收</summary>
        public StringBuilderPool() : base(0, true) { }

        /// <summary>创建</summary>
        /// <returns></returns>
        protected override StringBuilder OnCreate() => new(InitialCapacity);

        /// <summary>归还</summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public override Boolean Return(StringBuilder value)
        {
            if (value.Capacity > MaximumCapacity) return false;

            value.Clear();

            return base.Return(value);
        }
    }
    #endregion

    #region MemoryStream
    /// <summary>内存流池</summary>
    public static IPool<MemoryStream> MemoryStream { get; set; } = new MemoryStreamPool();

    /// <summary>归还一个内存流到对象池</summary>
    /// <param name="ms">待归还实例</param>
    /// <param name="requireResult">是否返回字节数组。true 将执行 <see cref="MemoryStream.ToArray()"/> 产生新数组</param>
    /// <returns>当 <paramref name="requireResult"/> 为 true 时返回当前内容的副本,否则返回空数组</returns>
    [Obsolete("Please use Return from 2024-02-01")]
    public static Byte[] Put(this MemoryStream ms, Boolean requireResult = false) => Return(ms, requireResult);

    /// <summary>归还一个内存流到对象池</summary>
    /// <param name="ms">待归还实例</param>
    /// <param name="returnResult">是否返回字节数组。true 将执行 <see cref="MemoryStream.ToArray()"/> 产生新数组</param>
    /// <returns>当 <paramref name="returnResult"/> 为 true 时返回当前内容的副本,否则返回空数组</returns>
    public static Byte[] Return(this MemoryStream ms, Boolean returnResult = true)
    {
        //if (ms == null) return null;

        var buf = returnResult ? ms.ToArray() : Empty;

        Pool.MemoryStream.Return(ms);

        return buf;
    }

    /// <summary>内存流池</summary>
    public class MemoryStreamPool : Pool<MemoryStream>
    {
        /// <summary>初始容量。默认1024个</summary>
        public Int32 InitialCapacity { get; set; } = 1024;

        /// <summary>最大容量。超过该大小时不进入池内,默认64k</summary>
        public Int32 MaximumCapacity { get; set; } = 64 * 1024;

        /// <summary>实例化内存流池。GC2时回收</summary>
        public MemoryStreamPool() : base(0, true) { }

        /// <summary>创建</summary>
        /// <returns></returns>
        protected override MemoryStream OnCreate() => new(InitialCapacity);

        /// <summary>归还</summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public override Boolean Return(MemoryStream value)
        {
            if (value.Capacity > MaximumCapacity) return false;

            value.Position = 0;
            value.SetLength(0);

            return base.Return(value);
        }
    }
    #endregion

    #region ByteArray
    /// <summary>字节数组共享存储</summary>
    public static ArrayPool<Byte> Shared { get; set; } = ArrayPool<Byte>.Shared;

    /// <summary>空数组</summary>
    public static Byte[] Empty { get; } = [];

    /// <summary>从共享数组池借出缓冲区,返回的句柄在 using 作用域结束时自动归还</summary>
    /// <remarks>
    /// <para>等价于 <c>var buffer = Pool.Shared.Rent(size); try { ... } finally { Pool.Shared.Return(buffer); }</c>,但不产生堆分配,也不需要手写 finally。</para>
    /// <para>返回的 <see cref="PoolBuffer{T}"/> 为栈上类型,不能跨 await 持有;async 方法内借出缓冲请继续使用 try/finally。</para>
    /// <para><b>大小分界</b>:长度有界(几字节到几百字节)且全链路只用 Span 的临时缓冲直接 <c>stackalloc</c>,不必借池;
    /// 长度动态/无界,或下游 API 只接受数组(旧框架的 Stream.Read/Write、Socket.SendTo/ReceiveFrom、IOControl、crypto 变换等)时才用本方法。</para>
    /// </remarks>
    /// <example>
    /// <code>
    /// using var buffer = Pool.Rent(1472);
    /// var count = stream.Read(buffer, 0, buffer.Length);
    /// </code>
    /// </example>
    /// <param name="size">请求的元素数量。池实际返回的数组可能更长,句柄的 Length/Span 只覆盖请求长度,Buffer 才是实际数组</param>
    /// <returns>缓冲句柄,用 using 包裹即可</returns>
    public static PoolBuffer<Byte> Rent(Int32 size)
    {
        var pool = Shared;

        return new PoolBuffer<Byte>(pool, pool.Rent(size), size);
    }

    /// <summary>从数组池借出缓冲区。<see cref="ArrayPool{T}.Shared"/> 为池来源,供库内非 Byte 场景使用</summary>
    /// <typeparam name="T">元素类型</typeparam>
    /// <param name="size">请求的元素数量</param>
    /// <returns>缓冲句柄,用 using 包裹即可</returns>
    internal static PoolBuffer<T> Rent<T>(Int32 size)
    {
        var pool = ArrayPool<T>.Shared;

        return new PoolBuffer<T>(pool, pool.Rent(size), size);
    }
    #endregion
}