发布:4.0.1

This commit is contained in:
若汝棋茗
2025-11-30 22:17:58 +08:00
parent a144a8dbfe
commit c5011074a9
20 changed files with 467 additions and 328 deletions

View File

@@ -1,7 +1,7 @@
<Project>
<PropertyGroup>
<BaseVersion>4.0.0</BaseVersion>
<BaseVersion>4.0.1</BaseVersion>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)'=='Release'">

View File

@@ -15,17 +15,18 @@ using TouchSocket.Core.AspNetCore;
namespace TouchSocket.Core;
/// <summary>
/// AspNetCoreConfigExtension
/// 提供AspNetCore容器扩展方法。
/// </summary>
public static class AspNetCoreConfigExtension
{
/// <summary>
/// 使用<see cref="AspNetCoreContainer"/>作为容器。
/// </summary>
/// <param name="config"></param>
/// <param name="services"></param>
/// <returns></returns>
/// <param name="config">配置对象</param>
/// <param name="services">服务集合</param>
/// <returns>配置对象</returns>
public static TouchSocketConfig UseAspNetCoreContainer(this TouchSocketConfig config, IServiceCollection services)
{
config.SetRegistrator(new AspNetCoreContainer(services));
@@ -35,13 +36,102 @@ public static class AspNetCoreConfigExtension
/// <summary>
/// 配置容器。
/// </summary>
/// <param name="services"></param>
/// <param name="action"></param>
/// <returns></returns>
/// <param name="services">服务集合</param>
/// <param name="action">配置操作</param>
/// <returns>服务集合</returns>
public static IServiceCollection ConfigureContainer(this IServiceCollection services, Action<IRegistrator> action)
{
var container = new AspNetCoreContainer(services);
action.Invoke(container);
return services;
}
/// <summary>
/// 设置解析器。
/// </summary>
/// <param name="config">配置对象</param>
/// <param name="provider">服务提供者</param>
public static void SetResolver(this TouchSocketConfig config, IServiceProvider provider)
{
config.SetValue(TouchSocketCoreConfigExtension.ResolverProperty, new InternalResolver(provider));
}
#region InternalResolver
/// <summary>
/// 内部解析器。
/// </summary>
internal class InternalResolver : IResolver
{
private readonly IServiceProvider m_serviceProvider;
private readonly IKeyedServiceProvider m_keyedServiceProvider;
/// <summary>
/// 初始化<see cref="InternalResolver"/>的新实例。
/// </summary>
/// <param name="serviceProvider">服务提供者</param>
public InternalResolver(IServiceProvider serviceProvider)
{
this.m_serviceProvider = serviceProvider;
this.m_keyedServiceProvider = serviceProvider as IKeyedServiceProvider;
}
/// <inheritdoc/>
public IScopedResolver CreateScopedResolver()
{
return new InternalScopedResolver(this.m_serviceProvider.CreateScope());
}
/// <inheritdoc/>
public object GetService(Type serviceType)
{
return this.m_serviceProvider.GetService(serviceType);
}
/// <inheritdoc/>
public object Resolve(Type fromType, object key)
{
return this.m_keyedServiceProvider.GetKeyedService(fromType, key);
}
/// <inheritdoc/>
public object Resolve(Type fromType)
{
return this.m_serviceProvider.GetService(fromType);
}
/// <summary>
/// 内部作用域解析器。
/// </summary>
private class InternalScopedResolver : DisposableObject, IScopedResolver
{
private readonly IServiceScope serviceScope;
private readonly InternalResolver resolver;
/// <summary>
/// 初始化<see cref="InternalScopedResolver"/>的新实例。
/// </summary>
/// <param name="serviceScope">服务作用域</param>
public InternalScopedResolver(IServiceScope serviceScope)
{
this.serviceScope = serviceScope;
this.resolver = new InternalResolver(serviceScope.ServiceProvider);
}
/// <inheritdoc/>
public IResolver Resolver => this.resolver;
/// <inheritdoc/>
protected override void Dispose(bool disposing)
{
if (disposing)
{
this.serviceScope.Dispose();
}
base.Dispose(disposing);
}
}
}
#endregion
}

View File

@@ -45,6 +45,7 @@ public sealed class ByteBlock : IByteBlock
public ByteBlock(Memory<byte> memory)
{
this.m_memory = memory;
this.m_length = memory.Length;
}
/// <summary>

View File

@@ -44,6 +44,7 @@ public struct ValueByteBlock : IByteBlock
public ValueByteBlock(Memory<byte> memory)
{
this.m_memory = memory;
this.m_length = memory.Length;
}
/// <summary>

View File

@@ -26,7 +26,7 @@ public interface IBytesBuilder
int MaxLength { get; }
/// <summary>
/// 构建对象到<see cref="ByteBlock"/>
/// 构建对象到<see cref="IBytesWriter"/>
/// </summary>
/// <param name="writer">要构建的字节块对象引用。</param>
void Build<TWriter>(ref TWriter writer) where TWriter : IBytesWriter

View File

@@ -16,8 +16,10 @@ using System.IO.Pipelines;
namespace TouchSocket.Core;
/// <summary>
///单线程状况的流式数据处理适配器测试
/// 单线程状况的流式数据处理适配器测试
/// </summary>
/// <typeparam name="TAdapter">自定义数据处理适配器类型。</typeparam>
/// <typeparam name="TRequest">请求信息类型。</typeparam>
public class SingleStreamDataAdapterTester<TAdapter, TRequest>
where TAdapter : CustomDataHandlingAdapter<TRequest>
where TRequest : class, IRequestInfo
@@ -32,12 +34,23 @@ public class SingleStreamDataAdapterTester<TAdapter, TRequest>
/// <summary>
/// Tcp数据处理适配器测试
/// </summary>
/// <param name="adapter">自定义数据处理适配器实例。</param>
/// <param name="receivedCallBack">接收回调委托。</param>
public SingleStreamDataAdapterTester(TAdapter adapter, Action<TRequest> receivedCallBack = default)
{
this.m_adapter = adapter;
this.m_receivedCallBack = receivedCallBack;
}
/// <summary>
/// 异步运行测试。
/// </summary>
/// <param name="memory">要发送的数据内存块。</param>
/// <param name="testCount">测试发送次数。</param>
/// <param name="expectedCount">预期接收次数。</param>
/// <param name="bufferLength">每次写入的缓冲区长度。</param>
/// <param name="cancellationToken">取消操作的令牌。</param>
/// <returns>返回测试所用的时间。</returns>
public async Task<TimeSpan> RunAsync(ReadOnlyMemory<byte> memory, int testCount, int expectedCount, int bufferLength, CancellationToken cancellationToken)
{
this.m_count = 0;

View File

@@ -13,10 +13,14 @@
namespace TouchSocket.Core;
/// <summary>
/// Udp数据处理适配器测试
/// Udp数据处理适配器测试
/// </summary>
public class UdpDataAdapterTester : MultithreadingDataAdapterTester
{
/// <summary>
/// 初始化 <see cref="UdpDataAdapterTester"/> 类的新实例。
/// </summary>
/// <param name="multiThread">多线程数量。</param>
protected UdpDataAdapterTester(int multiThread) : base(multiThread)
{
}

View File

@@ -15,7 +15,7 @@ using System.Net;
namespace TouchSocket.Core;
/// <summary>
/// Udp数据处理适配器
/// Udp数据处理适配器
/// </summary>
public abstract class UdpDataHandlingAdapter : DataHandlingAdapter
{
@@ -23,38 +23,32 @@ public abstract class UdpDataHandlingAdapter : DataHandlingAdapter
public override bool CanSendRequestInfo => false;
/// <summary>
/// 当接收数据处理完成后,回调该函数执行接收
/// 当接收数据处理完成后,回调该函数执行接收
/// </summary>
public Func<EndPoint, ReadOnlyMemory<byte>, IRequestInfo, Task> ReceivedCallBack { get; set; }
/// <summary>
/// 当接收数据处理完成后,异步回调该函数执行发送
/// 当接收数据处理完成后,异步回调该函数执行发送
/// </summary>
public Func<EndPoint, ReadOnlyMemory<byte>, CancellationToken, Task> SendCallBackAsync { get; set; }
/// <summary>
/// 收到数据的切入点,该方法由框架自动调用。
/// </summary>
/// <param name="remoteEndPoint"></param>
/// <param name="memory"></param>
/// <param name="remoteEndPoint">远程端点。</param>
/// <param name="memory">接收到的数据。</param>
public Task ReceivedInputAsync(EndPoint remoteEndPoint, ReadOnlyMemory<byte> memory)
{
return this.PreviewReceivedAsync(remoteEndPoint, memory);
}
#region SendInputAsync
/// <summary>
/// 异步发送输入数据。
/// </summary>
/// <param name="endPoint">要发送数据的端点。</param>
/// <param name="memory">包含要发送的数据的只读内存。</param>
/// <param name="cancellationToken">可取消令箭</param>
/// <param name="cancellationToken">可取消令箭</param>
/// <returns>返回一个任务,表示发送操作。</returns>
/// <remarks>
/// 此方法是一个异步操作,用于向指定的端点发送输入数据。
/// 它使用PreviewSendAsync方法来执行实际的发送操作。
/// </remarks>
public Task SendInputAsync(EndPoint endPoint, ReadOnlyMemory<byte> memory, CancellationToken cancellationToken)
{
return this.PreviewSendAsync(endPoint, memory, cancellationToken);
@@ -63,22 +57,21 @@ public abstract class UdpDataHandlingAdapter : DataHandlingAdapter
/// <summary>
/// 发送数据的切入点,该方法由框架自动调用。
/// </summary>
/// <param name="endPoint"></param>
/// <param name="requestInfo"></param>
/// <param name="cancellationToken">可取消令箭</param>
/// <param name="endPoint">目标端点。</param>
/// <param name="requestInfo">请求信息。</param>
/// <param name="cancellationToken">可取消令箭</param>
public Task SendInputAsync(EndPoint endPoint, IRequestInfo requestInfo, CancellationToken cancellationToken)
{
return this.PreviewSendAsync(endPoint, requestInfo, cancellationToken);
}
#endregion SendInputAsync
/// <summary>
/// 处理已经经过预先处理后的数据
/// 处理已经经过预先处理后的数据
/// </summary>
/// <param name="remoteEndPoint">远程端点,标识数据来源</param>
/// <param name="memory">接收到的二进制数据块</param>
/// <param name="requestInfo">解析后的请求信息</param>
/// <returns>一个异步任务,代表处理过程</returns>
/// <param name="remoteEndPoint">远程端点,标识数据来源</param>
/// <param name="memory">接收到的二进制数据块</param>
/// <param name="requestInfo">解析后的请求信息</param>
/// <returns>一个异步任务,代表处理过程</returns>
protected Task GoReceived(EndPoint remoteEndPoint, ReadOnlyMemory<byte> memory, IRequestInfo requestInfo)
{
// 调用接收回调,继续处理接收到的数据
@@ -86,32 +79,33 @@ public abstract class UdpDataHandlingAdapter : DataHandlingAdapter
}
/// <summary>
/// 发送已经经过预先处理后的数据
/// 发送已经经过预先处理后的数据
/// </summary>
/// <param name="endPoint">目标端点,表示数据发送的目的地址</param>
/// <param name="memory">已经经过预先处理的字节数据,以 ReadOnlyMemory 方式传递以提高性能</param>
/// <param name="cancellationToken">可取消令箭</param>
/// <returns>返回一个 Task 对象,表示异步操作的完成</returns>
/// <param name="endPoint">目标端点,表示数据发送的目的地址</param>
/// <param name="memory">已经经过预先处理的字节数据</param>
/// <param name="cancellationToken">可取消令箭</param>
/// <returns>返回一个任务,表示异步操作的完成</returns>
protected Task GoSendAsync(EndPoint endPoint, ReadOnlyMemory<byte> memory, CancellationToken cancellationToken)
{
return this.SendCallBackAsync.Invoke(endPoint, memory, cancellationToken);
}
/// <summary>
/// 接收数据预先处理数据,然后调用<see cref="GoReceived(EndPoint,IByteBlockReader, IRequestInfo)"/>处理数据
/// 接收数据预先处理数据
/// </summary>
/// <param name="remoteEndPoint"></param>
/// <param name="memory"></param>
/// <param name="remoteEndPoint">远程端点。</param>
/// <param name="memory">接收到的数据。</param>
protected virtual async Task PreviewReceivedAsync(EndPoint remoteEndPoint, ReadOnlyMemory<byte> memory)
{
await this.GoReceived(remoteEndPoint, memory, default).ConfigureAwait(EasyTask.ContinueOnCapturedContext);
}
/// <summary>
/// 当发送数据前预先处理数据
/// 当发送数据前预先处理数据
/// </summary>
/// <param name="endPoint"></param>
/// <param name="requestInfo"></param>
/// <param name="cancellationToken">可取消令箭</param>
/// <param name="endPoint">目标端点。</param>
/// <param name="requestInfo">请求信息。</param>
/// <param name="cancellationToken">可取消令箭</param>
protected virtual async Task PreviewSendAsync(EndPoint endPoint, IRequestInfo requestInfo, CancellationToken cancellationToken)
{
ThrowHelper.ThrowIfNull(requestInfo, nameof(requestInfo));
@@ -135,8 +129,8 @@ public abstract class UdpDataHandlingAdapter : DataHandlingAdapter
/// </summary>
/// <param name="endPoint">数据发送的目标端点。</param>
/// <param name="memory">待发送的字节数据内存。</param>
/// <param name="cancellationToken">可取消令箭</param>
/// <returns>一个表示异步操作完成的 <see cref="Task"/> 对象。</returns>
/// <param name="cancellationToken">可取消令箭</param>
/// <returns>一个表示异步操作完成的任务。</returns>
protected virtual Task PreviewSendAsync(EndPoint endPoint, ReadOnlyMemory<byte> memory, CancellationToken cancellationToken)
{
return this.GoSendAsync(endPoint, memory, cancellationToken);
@@ -145,12 +139,10 @@ public abstract class UdpDataHandlingAdapter : DataHandlingAdapter
/// <inheritdoc/>
protected override void Reset()
{
}
/// <inheritdoc/>
protected override void SafetyDispose(bool disposing)
{
}
}

View File

@@ -22,7 +22,7 @@ using System.Runtime.InteropServices;
namespace TouchSocket.Core;
/// <summary>
/// 为System提供扩展。
/// 为 <see cref="System"/> 提供扩展方法
/// </summary>
public static class SystemExtension
{
@@ -85,11 +85,11 @@ public static class SystemExtension
/// <summary>
/// 获取枚举成员上绑定的指定类型的自定义属性
/// 获取枚举成员上绑定的指定类型的自定义属性
/// </summary>
/// <param name="enumObj">枚举对象</param>
/// <typeparam name="T">要获取的属性类型</typeparam>
/// <returns>指定类型的自定义属性</returns>
/// <typeparam name="T">要获取的属性类型。</typeparam>
/// <param name="enumObj">枚举对象。</param>
/// <returns>指定类型的自定义属性</returns>
public static T GetAttribute<T>(this Enum enumObj) where T : Attribute
{
// 获取枚举对象的类型
@@ -110,13 +110,12 @@ public static class SystemExtension
#region SetBit
/// <summary>
/// 对于给定的无符号长整型数值,设置指定索引位置的位值为指定的布尔值
/// 设置无符号长整型数值的指定位
/// </summary>
/// <param name="value">原始数值。</param>
/// <param name="index">位索引范围为0到63。</param>
/// <param name="bitvalue">要设置的位值true为1false为0。</param>
/// <param name="index">位索引。</param>
/// <param name="bitvalue">要设置的位值。</param>
/// <returns>修改后的数值。</returns>
/// <exception cref="ArgumentOutOfRangeException">当索引值不在有效范围内时抛出异常。</exception>
public static ulong SetBit(this ulong value, int index, bool bitvalue)
{
var accessor = new BitAccessor<ulong>(ref value);
@@ -173,7 +172,7 @@ public static class SystemExtension
#region GetBit
/// <summary>
/// 获取无符号长整型数值的指定位置的位是否为1
/// 获取无符号长整型数值的指定位。
/// </summary>
/// <param name="value">要检查的无符号长整型数值。</param>
/// <param name="index">要检查的位的位置从0到63。</param>
@@ -228,13 +227,26 @@ public static class SystemExtension
#region Byte[]
/// <summary>
/// 字节数组转16进制字符
/// 字节数组转换为十六进制字符串。
/// </summary>
/// <param name="buffer"></param>
/// <param name="offset"></param>
/// <param name="length"></param>
/// <param name="split"></param>
/// <returns></returns>
/// <param name="buffer">字节数组。</param>
/// <param name="split">分隔符。</param>
/// <returns>十六进制字符串。</returns>
public static string ByBytesToHexString(this byte[] buffer, string split = default)
{
return string.IsNullOrEmpty(split)
? BitConverter.ToString(buffer).Replace("-", string.Empty)
: BitConverter.ToString(buffer).Replace("-", split);
}
/// <summary>
/// 将字节缓冲区转换为十六进制字符串。
/// </summary>
/// <param name="buffer">要转换的字节缓冲区。</param>
/// <param name="offset">缓冲区的起始索引。</param>
/// <param name="length">要转换的字节数。</param>
/// <param name="split">可选参数,用于指定分隔符,默认为空。</param>
/// <returns>转换后的十六进制字符串。</returns>
public static string ByBytesToHexString(this byte[] buffer, int offset, int length, string split = default)
{
return string.IsNullOrEmpty(split)
@@ -242,17 +254,6 @@ public static class SystemExtension
: BitConverter.ToString(buffer, offset, length).Replace("-", split);
}
/// <summary>
/// 将字节缓冲区转换为十六进制字符串。
/// </summary>
/// <param name="buffer">要转换的字节缓冲区。</param>
/// <param name="split">可选参数,用于指定分隔符,默认为空。</param>
/// <returns>转换后的十六进制字符串。</returns>
public static string ByBytesToHexString(this byte[] buffer, string split = default)
{
return ByBytesToHexString(buffer, 0, buffer.Length, split);
}
/// <summary>
/// 索引第一个包含数组的索引位置,例如:在{0,1,2,3,1,2,3}中索引{2,3}则返回3。
/// <para>如果目标数组为<see langword="null"/>或长度为0则直接返回offset的值</para>
@@ -1000,6 +1001,12 @@ public static class SystemExtension
}
}
/// <summary>
/// 异步读取流中的所有字节。
/// </summary>
/// <param name="stream">流。</param>
/// <param name="cancellationToken">取消令牌。</param>
/// <returns>字节数组。</returns>
public static async Task<byte[]> ReadAllToByteArrayAsync(this Stream stream, CancellationToken cancellationToken)
{
using (var memoryStream = new MemoryStream())

View File

@@ -12,7 +12,7 @@
namespace TouchSocket.Core;
/// <summary>
/// 简化版文件存储器
/// 简化版文件存储器
/// </summary>
public sealed partial class FileStorage : IDisposable
{
@@ -21,6 +21,10 @@ public sealed partial class FileStorage : IDisposable
internal int m_referenceCount;
private bool m_disposed;
/// <summary>
/// 初始化 <see cref="FileStorage"/> 类的新实例。
/// </summary>
/// <param name="path">文件路径。</param>
internal FileStorage(string path)
{
this.Path = path;
@@ -28,12 +32,12 @@ public sealed partial class FileStorage : IDisposable
}
/// <summary>
/// 文件路径
/// 获取文件路径
/// </summary>
public string Path { get; }
/// <summary>
/// 文件长度
/// 获取文件长度
/// </summary>
public long Length
{
@@ -52,14 +56,25 @@ public sealed partial class FileStorage : IDisposable
}
}
/// <summary>
/// 获取一个值,指示是否可以读取文件。
/// </summary>
public bool CanRead => this.m_fileStream.CanRead;
/// <summary>
/// 获取一个值,指示是否可以查找文件位置。
/// </summary>
public bool CanSeek => this.m_fileStream.CanSeek;
/// <summary>
/// 获取一个值,指示是否可以写入文件。
/// </summary>
public bool CanWrite => this.m_fileStream.CanWrite;
/// <summary>
/// 设置文件长度
/// 设置文件长度
/// </summary>
/// <param name="length">新长度</param>
/// <param name="length">新长度</param>
public void SetLength(long length)
{
this.m_semaphore.Wait();
@@ -75,7 +90,7 @@ public sealed partial class FileStorage : IDisposable
}
/// <summary>
/// 刷新缓冲区
/// 刷新缓冲区
/// </summary>
public void Flush()
{
@@ -142,13 +157,13 @@ public sealed partial class FileStorage : IDisposable
}
/// <summary>
/// 读取数据
/// 读取数据
/// </summary>
/// <param name="position">读取位置</param>
/// <param name="buffer">缓冲区</param>
/// <param name="offset">缓冲区偏移量</param>
/// <param name="count">读取字节数</param>
/// <returns>实际读取的字节数</returns>
/// <param name="position">读取位置</param>
/// <param name="buffer">缓冲区</param>
/// <param name="offset">缓冲区偏移量</param>
/// <param name="count">读取字节数</param>
/// <returns>实际读取的字节数</returns>
public int Read(long position, byte[] buffer, int offset, int count)
{
this.m_semaphore.Wait();
@@ -165,12 +180,12 @@ public sealed partial class FileStorage : IDisposable
}
/// <summary>
/// 写入数据
/// 写入数据
/// </summary>
/// <param name="position">写入位置</param>
/// <param name="buffer">数据</param>
/// <param name="offset">缓冲区偏移量</param>
/// <param name="count">写入字节数</param>
/// <param name="position">写入位置</param>
/// <param name="buffer">数据</param>
/// <param name="offset">缓冲区偏移量</param>
/// <param name="count">写入字节数</param>
public void Write(long position, byte[] buffer, int offset, int count)
{
this.m_semaphore.Wait();
@@ -187,12 +202,12 @@ public sealed partial class FileStorage : IDisposable
}
/// <summary>
/// 异步读取数据
/// 异步读取数据
/// </summary>
/// <param name="position">读取位置</param>
/// <param name="memory">缓冲区</param>
/// <param name="cancellationToken">取消令牌</param>
/// <returns>实际读取的字节数</returns>
/// <param name="position">读取位置</param>
/// <param name="memory">缓冲区</param>
/// <param name="cancellationToken">取消令牌</param>
/// <returns>实际读取的字节数</returns>
public async Task<int> ReadAsync(long position, Memory<byte> memory, CancellationToken cancellationToken = default)
{
await this.m_semaphore.WaitAsync(cancellationToken).ConfigureAwait(false);
@@ -209,11 +224,11 @@ public sealed partial class FileStorage : IDisposable
}
/// <summary>
/// 异步写入数据
/// 异步写入数据
/// </summary>
/// <param name="position">写入位置</param>
/// <param name="memory">数据</param>
/// <param name="cancellationToken">取消令牌</param>
/// <param name="position">写入位置</param>
/// <param name="memory">数据</param>
/// <param name="cancellationToken">取消令牌</param>
public async Task WriteAsync(long position, ReadOnlyMemory<byte> memory, CancellationToken cancellationToken = default)
{
await this.m_semaphore.WaitAsync(cancellationToken).ConfigureAwait(false);
@@ -230,9 +245,9 @@ public sealed partial class FileStorage : IDisposable
}
/// <summary>
/// 异步刷新缓冲区
/// 异步刷新缓冲区
/// </summary>
/// <param name="cancellationToken">取消令牌</param>
/// <param name="cancellationToken">取消令牌</param>
public async Task FlushAsync(CancellationToken cancellationToken = default)
{
await this.m_semaphore.WaitAsync(cancellationToken).ConfigureAwait(false);
@@ -247,13 +262,12 @@ public sealed partial class FileStorage : IDisposable
}
}
/// <summary>
/// 读取数据
/// 读取数据
/// </summary>
/// <param name="position">读取位置</param>
/// <param name="buffer">缓冲区</param>
/// <returns>实际读取的字节数</returns>
/// <param name="position">读取位置</param>
/// <param name="buffer">缓冲区</param>
/// <returns>实际读取的字节数</returns>
public int Read(long position, Span<byte> buffer)
{
this.m_semaphore.Wait();
@@ -270,10 +284,10 @@ public sealed partial class FileStorage : IDisposable
}
/// <summary>
/// 写入数据
/// 写入数据
/// </summary>
/// <param name="position">写入位置</param>
/// <param name="buffer">数据</param>
/// <param name="position">写入位置</param>
/// <param name="buffer">数据</param>
public void Write(long position, ReadOnlySpan<byte> buffer)
{
this.m_semaphore.Wait();

View File

@@ -15,6 +15,9 @@ using System.Reflection;
namespace TouchSocket.Core;
/// <summary>
/// 表示一个字段的封装。
/// </summary>
public sealed class Field
{
/// <summary>
@@ -30,7 +33,7 @@ public sealed class Field
/// <summary>
/// 字段
/// </summary>
/// <param name="fieldInfo">字段信息</param>
/// <param name="fieldInfo">字段信息</param>
public Field(FieldInfo fieldInfo)
{
this.Info = fieldInfo;
@@ -44,37 +47,37 @@ public sealed class Field
}
/// <summary>
/// 获取字段信息
/// 获取字段信息
/// </summary>
public FieldInfo Info { get; }
/// <summary>
/// 从类型的字段获取字段
/// 从类型的字段获取字段
/// </summary>
/// <param name="type">类型</param>
/// <returns></returns>
/// <param name="type">类型</param>
/// <returns>字段数组。</returns>
public static Field[] GetFields([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicFields)] Type type)
{
return type.GetFields().Select(p => new Field(p)).ToArray();
}
/// <summary>
/// 获取字段的值
/// 获取字段的值
/// </summary>
/// <param name="instance">实例</param>
/// <exception cref="NotSupportedException"></exception>
/// <returns></returns>
/// <param name="instance">实例</param>
/// <returns>字段的值。</returns>
/// <exception cref="NotSupportedException">当字段不支持获取值时抛出。</exception>
public object GetValue(object instance)
{
return this.m_geter == null ? throw new NotSupportedException() : this.m_geter.Invoke(instance);
}
/// <summary>
/// 设置字段的值
/// 设置字段的值
/// </summary>
/// <param name="instance">实例</param>
/// <param name="value">值</param>
/// <exception cref="NotSupportedException"></exception>
/// <param name="instance">实例</param>
/// <param name="value">值</param>
/// <exception cref="NotSupportedException">当字段不支持设置值时抛出。</exception>
public void SetValue(object instance, object value)
{
if (this.m_seter == null)

View File

@@ -10,6 +10,7 @@
// 感谢您的下载和使用
//------------------------------------------------------------------------------
using System.Buffers;
using System.Collections;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.CompilerServices;
@@ -133,11 +134,11 @@ public static class FastBinaryFormatter
[RequiresUnreferencedCode("此方法可能会使用反射构建访问器,与剪裁不兼容。如果已使用源生成上下文,可以忽略此警告。")]
public static byte[] SerializeToBytes<[DynamicallyAccessedMembers(AOT.FastBinaryFormatter)] T>(in T graph, FastSerializerContext serializerContext = null)
{
var byteBlock = new ValueByteBlock(1024 * 64);
var byteBlock = new SegmentedBytesWriter();
try
{
Serialize(ref byteBlock, graph, serializerContext);
return byteBlock.ToArray();
return byteBlock.Sequence.ToArray();
}
finally
{
@@ -339,8 +340,8 @@ public static class FastBinaryFormatter
[RequiresUnreferencedCode("此方法可能会使用反射构建访问器,与剪裁不兼容。如果已使用源生成上下文,可以忽略此警告。")]
public static T Deserialize<[DynamicallyAccessedMembers(AOT.FastBinaryFormatter)] T>(byte[] bytes, FastSerializerContext serializerContext = null)
{
var byteBlock = new ValueByteBlock(bytes);
return Deserialize<ValueByteBlock, T>(ref byteBlock, serializerContext);
var reader = new BytesReader(bytes);
return Deserialize<BytesReader, T>(ref reader, serializerContext);
}
/// <summary>
@@ -406,11 +407,9 @@ public static class FastBinaryFormatter
// 复杂类型:先读体长度
var len = ReaderExtension.ReadValue<TReader, int>(ref reader);
var serializeObj = serializerContext.GetSerializeObject(type);
if (serializeObj.Converter != null)
{
return serializeObj.Converter.Read(ref reader, type);
}
return DeserializeClass(type, serializeObj, ref reader, len, serializerContext);
return serializeObj.Converter != null
? serializeObj.Converter.Read(ref reader, type)
: DeserializeClass(type, serializeObj, ref reader, len, serializerContext);
}
[UnconditionalSuppressMessage("AOT", "IL3050", Justification = "数组元素类型已通过DynamicallyAccessedMembers标记保证存在")]

View File

@@ -19,6 +19,7 @@ namespace TouchSocket.Core;
/// </summary>
/// <typeparam name="TState"></typeparam>
[RequiresUnreferencedCode("Members from deserialized types may be trimmed if not referenced directly")]
[RequiresDynamicCode("XML serializer relies on dynamic code generation which is not available with Ahead of Time compilation")]
public class XmlStringToClassSerializerFormatter<TState> : ISerializerFormatter<string, TState>
{
/// <inheritdoc/>

View File

@@ -36,30 +36,25 @@ public sealed class WebSocketFeatureOptions
/// 设置是否自动处理Close报文
/// </summary>
/// <param name="autoClose">是否自动处理Close报文</param>
/// <returns>返回当前配置选项实例,支持链式调用</returns>
public WebSocketFeatureOptions SetAutoClose(bool autoClose)
public void SetAutoClose(bool autoClose)
{
this.AutoClose = autoClose;
return this;
}
/// <summary>
/// 设置是否自动回应Ping报文
/// </summary>
/// <param name="autoPong">是否自动回应Ping报文</param>
/// <returns>返回当前配置选项实例,支持链式调用</returns>
public WebSocketFeatureOptions SetAutoPong(bool autoPong)
public void SetAutoPong(bool autoPong)
{
this.AutoPong = autoPong;
return this;
}
/// <summary>
/// 设置WebSocket连接的URL路径
/// </summary>
/// <param name="url">WebSocket连接路径如果为null或空则表示所有连接都解释为WS</param>
/// <returns>返回当前配置选项实例,支持链式调用</returns>
public WebSocketFeatureOptions SetUrl(string url = "/ws")
public void SetUrl(string url = "/ws")
{
if (url.IsNullOrEmpty())
{
@@ -72,22 +67,15 @@ public sealed class WebSocketFeatureOptions
this.SetVerifyConnection((client, context) =>
{
if (url == "/" || context.Request.UrlEquals(url))
{
return true;
}
return false;
return url == "/" || context.Request.UrlEquals(url);
});
return this;
}
/// <summary>
/// 设置验证连接的同步方法
/// </summary>
/// <param name="verifyConnection">验证连接的同步委托</param>
/// <returns>返回当前配置选项实例,支持链式调用</returns>
public WebSocketFeatureOptions SetVerifyConnection(Func<IHttpSessionClient, HttpContext, bool> verifyConnection)
public void SetVerifyConnection(Func<IHttpSessionClient, HttpContext, bool> verifyConnection)
{
ThrowHelper.ThrowIfNull(verifyConnection, nameof(verifyConnection));
@@ -96,18 +84,15 @@ public sealed class WebSocketFeatureOptions
await EasyTask.CompletedTask.ConfigureAwait(EasyTask.ContinueOnCapturedContext);
return verifyConnection.Invoke(client, context);
};
return this;
}
/// <summary>
/// 设置验证连接的异步方法
/// </summary>
/// <param name="verifyConnection">验证连接的异步委托</param>
/// <returns>返回当前配置选项实例,支持链式调用</returns>
public WebSocketFeatureOptions SetVerifyConnection(Func<IHttpSessionClient, HttpContext, Task<bool>> verifyConnection)
public void SetVerifyConnection(Func<IHttpSessionClient, HttpContext, Task<bool>> verifyConnection)
{
ThrowHelper.ThrowIfNull(verifyConnection, nameof(verifyConnection));
this.VerifyConnection = verifyConnection;
return this;
}
}

View File

@@ -14,6 +14,7 @@ using TouchSocket.Sockets;
namespace TouchSocket.Mqtt;
/// <inheritdoc/>
public abstract class MqttActor : DisposableObject, IOnlineClient
{
#region
@@ -24,11 +25,7 @@ public abstract class MqttActor : DisposableObject, IOnlineClient
#endregion
public MqttActor()
{
}
/// <inheritdoc/>
protected override void Dispose(bool disposing)
{
if (this.DisposedValue)
@@ -44,6 +41,7 @@ public abstract class MqttActor : DisposableObject, IOnlineClient
}
}
/// <inheritdoc/>
protected virtual Task PublishMessageArrivedAsync(MqttArrivedMessage message)
{
if (this.MessageArrived != null)
@@ -59,18 +57,23 @@ public abstract class MqttActor : DisposableObject, IOnlineClient
#region
/// <inheritdoc/>
public string Id { get; protected set; }
/// <inheritdoc/>
public bool Online { get; protected set; }
/// <inheritdoc/>
public CancellationTokenSource TokenSource => this.m_tokenSource;
/// <inheritdoc/>
public WaitHandlePool<MqttIdentifierMessage> WaitHandlePool => this.m_waitHandlePool;
#endregion
#region Publish
/// <inheritdoc/>
public Task PublishAsync(MqttPublishMessage message, CancellationToken cancellationToken)
{
switch (message.QosLevel)
@@ -137,6 +140,7 @@ public abstract class MqttActor : DisposableObject, IOnlineClient
#region InputMqttMessage
/// <inheritdoc/>
public async Task InputMqttMessageAsync(MqttMessage mqttMessage, CancellationToken cancellationToken)
{
switch (mqttMessage)
@@ -385,17 +389,24 @@ public abstract class MqttActor : DisposableObject, IOnlineClient
#region
/// <inheritdoc/>
public Func<MqttActor, MqttClosingEventArgs, Task> Closing { get; set; }
/// <inheritdoc/>
public Func<MqttActor, MqttConnectedEventArgs, Task> Connected { get; set; }
/// <inheritdoc/>
public Func<MqttActor, MqttConnectingEventArgs, Task> Connecting { get; set; }
/// <inheritdoc/>
public Func<MqttActor, MqttReceivedEventArgs, Task> MessageArrived { get; set; }
/// <inheritdoc/>
public Func<MqttActor, MqttMessage, CancellationToken, Task> OutputSendAsync { get; set; }
/// <inheritdoc/>
public MqttProtocolVersion Version { get; protected set; }
#endregion
#region
/// <inheritdoc/>
protected async Task ProtectedMqttOnClosing(MqttDisconnectMessage message)
{
if (this.Closing != null)
@@ -404,6 +415,7 @@ public abstract class MqttActor : DisposableObject, IOnlineClient
}
}
/// <inheritdoc/>
protected async Task ProtectedMqttOnConnected(MqttConnectedEventArgs e)
{
if (this.Connected != null)
@@ -412,6 +424,7 @@ public abstract class MqttActor : DisposableObject, IOnlineClient
}
}
/// <inheritdoc/>
protected async Task ProtectedMqttOnConnecting(MqttConnectingEventArgs e)
{
if (this.Connecting != null)
@@ -420,6 +433,7 @@ public abstract class MqttActor : DisposableObject, IOnlineClient
}
}
/// <inheritdoc/>
protected Task ProtectedOutputSendAsync(MqttMessage message, CancellationToken cancellationToken)
{
if (message.MessageType == MqttMessageType.Connect)

View File

@@ -17,6 +17,11 @@ public sealed class MqttClientActor : MqttActor
private TaskCompletionSource<MqttConnAckMessage> m_waitForConnect;
private readonly WaitDataAsync<MqttPingRespMessage> m_waitForPing = new();
/// <summary>
/// 异步断开连接。
/// </summary>
/// <param name="cancellationToken">取消令牌。</param>
/// <returns>任务。</returns>
public async Task DisconnectAsync(CancellationToken cancellationToken)
{
if (!this.Online)
@@ -36,6 +41,11 @@ public sealed class MqttClientActor : MqttActor
}
}
/// <summary>
/// 异步发送PING消息。
/// </summary>
/// <param name="cancellationToken">取消令牌。</param>
/// <returns>操作结果。</returns>
public async ValueTask<Result> PingAsync(CancellationToken cancellationToken)
{
var contentForAck = new MqttPingReqMessage();
@@ -54,8 +64,12 @@ public sealed class MqttClientActor : MqttActor
};
}
#region
/// <summary>
/// 异步连接。
/// </summary>
/// <param name="message">连接消息。</param>
/// <param name="cancellationToken">取消令牌。</param>
/// <returns>连接确认消息。</returns>
public async Task<MqttConnAckMessage> ConnectAsync(MqttConnectMessage message, CancellationToken cancellationToken)
{
this.m_waitForConnect = new TaskCompletionSource<MqttConnAckMessage>();
@@ -66,32 +80,35 @@ public sealed class MqttClientActor : MqttActor
return connAckMessage;
}
#endregion
#region
/// <inheritdoc/>
protected override Task InputMqttConnAckMessageAsync(MqttConnAckMessage message, CancellationToken cancellationToken)
{
this.m_waitForConnect?.SetResult(message);
return EasyTask.CompletedTask;
}
/// <inheritdoc/>
protected override Task InputMqttConnectMessageAsync(MqttConnectMessage message, CancellationToken cancellationToken)
{
throw ThrowHelper.CreateNotSupportedException($"遇到无法处理的数据报文,Message={message}");
}
/// <inheritdoc/>
protected override Task InputMqttPingRespMessageAsync(MqttPingRespMessage message, CancellationToken cancellationToken)
{
this.m_waitForPing.Set(message);
return EasyTask.CompletedTask;
}
/// <inheritdoc/>
protected override Task InputMqttSubscribeMessageAsync(MqttSubscribeMessage message, CancellationToken cancellationToken)
{
throw ThrowHelper.CreateNotSupportedException($"遇到无法处理的数据报文,Message={message}");
}
/// <inheritdoc/>
protected override Task InputMqttUnsubscribeMessageAsync(MqttUnsubscribeMessage message, CancellationToken cancellationToken)
{
throw ThrowHelper.CreateNotSupportedException($"遇到无法处理的数据报文,Message={message}");
@@ -99,6 +116,12 @@ public sealed class MqttClientActor : MqttActor
#endregion
/// <summary>
/// 异步订阅。
/// </summary>
/// <param name="message">订阅消息。</param>
/// <param name="cancellationToken">取消令牌。</param>
/// <returns>订阅确认消息。</returns>
public async Task<MqttSubAckMessage> SubscribeAsync(MqttSubscribeMessage message, CancellationToken cancellationToken = default)
{
using (var waitDataAsync = this.WaitHandlePool.GetWaitDataAsync(message))
@@ -112,6 +135,12 @@ public sealed class MqttClientActor : MqttActor
}
}
/// <summary>
/// 异步取消订阅。
/// </summary>
/// <param name="message">取消订阅消息。</param>
/// <param name="cancellationToken">取消令牌。</param>
/// <returns>取消订阅确认消息。</returns>
public async Task<MqttUnsubAckMessage> UnsubscribeAsync(MqttUnsubscribeMessage message, CancellationToken cancellationToken = default)
{
using (var waitDataAsync = this.WaitHandlePool.GetWaitDataAsync(message))

View File

@@ -44,8 +44,8 @@ public abstract class RpcAttribute : Attribute
/// 生成代码
/// </summary>
public CodeGeneratorFlag GeneratorFlag { get; set; } =
CodeGeneratorFlag.InstanceSync | CodeGeneratorFlag.InstanceAsync | CodeGeneratorFlag.ExtensionSync | CodeGeneratorFlag.ExtensionAsync
| CodeGeneratorFlag.InterfaceSync | CodeGeneratorFlag.InterfaceAsync;
CodeGeneratorFlag.InstanceAsync | CodeGeneratorFlag.ExtensionAsync
| CodeGeneratorFlag.InterfaceAsync;
/// <summary>
/// 生成泛型方法的约束
@@ -85,11 +85,7 @@ public abstract class RpcAttribute : Attribute
public virtual string GetDescription(RpcMethod rpcMethod)
{
var description = rpcMethod.GetDescription();
if (description.HasValue())
{
return this.ReplacePatterns(description);
}
return "无注释信息";
return description.HasValue() ? this.ReplacePatterns(description) : "无注释信息";
}
/// <summary>
@@ -105,56 +101,56 @@ public abstract class RpcAttribute : Attribute
var parametersStr = this.GetParameters(rpcMethod, out var parameters);
var InterfaceTypes = this.GetGenericConstraintTypes();
if (this.GeneratorFlag.HasFlag(CodeGeneratorFlag.ExtensionSync))
{
codeString.AppendLine("///<summary>");
codeString.AppendLine($"///{description}");
codeString.AppendLine("///</summary>");
foreach (var item in this.Exceptions)
{
codeString.AppendLine($"/// <exception cref=\"{item.Key.FullName}\">{item.Value}</exception>");
}
//if (this.GeneratorFlag.HasFlag(CodeGeneratorFlag.ExtensionSync))
//{
// codeString.AppendLine("///<summary>");
// codeString.AppendLine($"///{description}");
// codeString.AppendLine("///</summary>");
// foreach (var item in this.Exceptions)
// {
// codeString.AppendLine($"/// <exception cref=\"{item.Key.FullName}\">{item.Value}</exception>");
// }
codeString.AppendLine("[AsyncToSyncWarning]");
codeString.Append("public static ");
codeString.Append(this.GetReturn(rpcMethod, false));
codeString.Append(' ');
codeString.Append(this.GetMethodName(rpcMethod, false));
codeString.Append("<TClient>(");//方法参数
// codeString.AppendLine("[AsyncToSyncWarning]");
// codeString.Append("public static ");
// codeString.Append(this.GetReturn(rpcMethod, false));
// codeString.Append(' ');
// codeString.Append(this.GetMethodName(rpcMethod, false));
// codeString.Append("<TClient>(");//方法参数
codeString.Append($"this TClient client");
// codeString.Append($"this TClient client");
codeString.Append(',');
for (var i = 0; i < parametersStr.Count; i++)
{
if (i > 0)
{
codeString.Append(',');
}
// codeString.Append(',');
// for (var i = 0; i < parametersStr.Count; i++)
// {
// if (i > 0)
// {
// codeString.Append(',');
// }
codeString.Append(parametersStr[i]);
}
if (parametersStr.Count > 0)
{
codeString.Append(',');
}
codeString.Append(this.GetInvokeOption());
codeString.AppendLine(") where TClient:");
// codeString.Append(parametersStr[i]);
// }
// if (parametersStr.Count > 0)
// {
// codeString.Append(',');
// }
// codeString.Append(this.GetInvokeOption());
// codeString.AppendLine(") where TClient:");
for (var i = 0; i < InterfaceTypes.Length; i++)
{
if (i > 0)
{
codeString.Append(',');
}
// for (var i = 0; i < InterfaceTypes.Length; i++)
// {
// if (i > 0)
// {
// codeString.Append(',');
// }
codeString.Append(InterfaceTypes[i].FullName);
}
// codeString.Append(InterfaceTypes[i].FullName);
// }
codeString.AppendLine("{");//方法开始
codeString.AppendLine(this.GetExtensionInstanceMethod(rpcMethod, parametersStr, parameters, false));
codeString.AppendLine("}");
}
// codeString.AppendLine("{");//方法开始
// codeString.AppendLine(this.GetExtensionInstanceMethod(rpcMethod, parametersStr, parameters, false));
// codeString.AppendLine("}");
//}
//以下生成异步
if (this.GeneratorFlag.HasFlag(CodeGeneratorFlag.ExtensionAsync))
@@ -232,43 +228,43 @@ public abstract class RpcAttribute : Attribute
var description = this.GetDescription(rpcMethod);
var parametersStr = this.GetParameters(rpcMethod, out var parameters);
if (this.GeneratorFlag.HasFlag(CodeGeneratorFlag.InstanceSync))
{
codeString.AppendLine("///<summary>");
codeString.AppendLine($"///{description}");
codeString.AppendLine("///</summary>");
foreach (var item in this.Exceptions)
{
codeString.AppendLine($"/// <exception cref=\"{item.Key.FullName}\">{item.Value}</exception>");
}
codeString.AppendLine("[AsyncToSyncWarning]");
codeString.Append("public ");
codeString.Append(this.GetReturn(rpcMethod, false));
codeString.Append(' ');
codeString.Append(this.GetMethodName(rpcMethod, false));
codeString.Append('(');//方法参数
//if (this.GeneratorFlag.HasFlag(CodeGeneratorFlag.InstanceSync))
//{
// codeString.AppendLine("///<summary>");
// codeString.AppendLine($"///{description}");
// codeString.AppendLine("///</summary>");
// foreach (var item in this.Exceptions)
// {
// codeString.AppendLine($"/// <exception cref=\"{item.Key.FullName}\">{item.Value}</exception>");
// }
// codeString.AppendLine("[AsyncToSyncWarning]");
// codeString.Append("public ");
// codeString.Append(this.GetReturn(rpcMethod, false));
// codeString.Append(' ');
// codeString.Append(this.GetMethodName(rpcMethod, false));
// codeString.Append('(');//方法参数
for (var i = 0; i < parametersStr.Count; i++)
{
if (i > 0)
{
codeString.Append(',');
}
codeString.Append(parametersStr[i]);
}
if (parametersStr.Count > 0)
{
codeString.Append(',');
}
codeString.Append(this.GetInvokeOption());
codeString.AppendLine(")");
// for (var i = 0; i < parametersStr.Count; i++)
// {
// if (i > 0)
// {
// codeString.Append(',');
// }
// codeString.Append(parametersStr[i]);
// }
// if (parametersStr.Count > 0)
// {
// codeString.Append(',');
// }
// codeString.Append(this.GetInvokeOption());
// codeString.AppendLine(")");
codeString.AppendLine("{");//方法开始
// codeString.AppendLine("{");//方法开始
codeString.AppendLine(this.GetInstanceMethod(rpcMethod, parametersStr, parameters, false));
// codeString.AppendLine(this.GetInstanceMethod(rpcMethod, parametersStr, parameters, false));
codeString.AppendLine("}");
}
// codeString.AppendLine("}");
//}
//以下生成异步
if (this.GeneratorFlag.HasFlag(CodeGeneratorFlag.InstanceAsync))
@@ -324,36 +320,36 @@ public abstract class RpcAttribute : Attribute
var codeString = new StringBuilder();
var description = this.GetDescription(rpcMethod);
var parameters = this.GetParameters(rpcMethod, out _);
if (this.GeneratorFlag.HasFlag(CodeGeneratorFlag.InterfaceSync))
{
codeString.AppendLine("///<summary>");
codeString.AppendLine($"///{description}");
codeString.AppendLine("///</summary>");
foreach (var item in this.Exceptions)
{
codeString.AppendLine($"/// <exception cref=\"{item.Key.FullName}\">{item.Value}</exception>");
}
//if (this.GeneratorFlag.HasFlag(CodeGeneratorFlag.InterfaceSync))
//{
// codeString.AppendLine("///<summary>");
// codeString.AppendLine($"///{description}");
// codeString.AppendLine("///</summary>");
// foreach (var item in this.Exceptions)
// {
// codeString.AppendLine($"/// <exception cref=\"{item.Key.FullName}\">{item.Value}</exception>");
// }
codeString.AppendLine("[AsyncToSyncWarning]");
codeString.Append(this.GetReturn(rpcMethod, false));
codeString.Append(' ');
codeString.Append(this.GetMethodName(rpcMethod, false));
codeString.Append('(');//方法参数
for (var i = 0; i < parameters.Count; i++)
{
if (i > 0)
{
codeString.Append(',');
}
codeString.Append(parameters[i]);
}
if (parameters.Count > 0)
{
codeString.Append(',');
}
codeString.Append(this.GetInvokeOption());
codeString.AppendLine(");");
}
// codeString.AppendLine("[AsyncToSyncWarning]");
// codeString.Append(this.GetReturn(rpcMethod, false));
// codeString.Append(' ');
// codeString.Append(this.GetMethodName(rpcMethod, false));
// codeString.Append('(');//方法参数
// for (var i = 0; i < parameters.Count; i++)
// {
// if (i > 0)
// {
// codeString.Append(',');
// }
// codeString.Append(parameters[i]);
// }
// if (parameters.Count > 0)
// {
// codeString.Append(',');
// }
// codeString.Append(this.GetInvokeOption());
// codeString.AppendLine(");");
//}
if (this.GeneratorFlag.HasFlag(CodeGeneratorFlag.InterfaceAsync))
{
@@ -396,14 +392,9 @@ public abstract class RpcAttribute : Attribute
/// <returns></returns>
public virtual string GetInvokeKey(RpcMethod rpcMethod)
{
if (this.MethodInvoke)
{
return this.GetMethodName(rpcMethod, false);
}
else
{
return !this.InvokeKey.IsNullOrEmpty() ? this.InvokeKey : $"{rpcMethod.ServerFromType.FullName}.{rpcMethod.Name}".ToLower();
}
return this.MethodInvoke
? this.GetMethodName(rpcMethod, false)
: !this.InvokeKey.IsNullOrEmpty() ? this.InvokeKey : $"{rpcMethod.ServerFromType.FullName}.{rpcMethod.Name}".ToLower();
}
/// <summary>
@@ -424,32 +415,15 @@ public abstract class RpcAttribute : Attribute
public virtual string GetMethodName(RpcMethod rpcMethod, bool isAsync)
{
var name = this.MethodName;
if (name.HasValue())
{
name = this.ReplacePatterns(name).Format(rpcMethod.Name);
}
else
{
name = rpcMethod.Name;
}
name = name.HasValue() ? this.ReplacePatterns(name).Format(rpcMethod.Name) : rpcMethod.Name;
if (isAsync)
{
if (name.EndsWith("Async"))
{
return name;
}
return $"{name}Async";
return name.EndsWith("Async") ? name : $"{name}Async";
}
else
{
if (name.EndsWith("Async"))
{
return name.RemoveLastChars(5);
}
return name;
return name.EndsWith("Async") ? name.RemoveLastChars(5) : name;
}
}

View File

@@ -341,15 +341,15 @@ public static class CodeGenerator
rpcAttribute.SetClassCodeGenerator(classCodeGenerator);
if (first)
{
if (rpcAttribute.GeneratorFlag.HasFlag(CodeGeneratorFlag.InterfaceAsync) || rpcAttribute.GeneratorFlag.HasFlag(CodeGeneratorFlag.InterfaceSync))
if (rpcAttribute.GeneratorFlag.HasFlag(CodeGeneratorFlag.InterfaceAsync))
{
serverCellCode.IncludeInterface = true;
}
if (rpcAttribute.GeneratorFlag.HasFlag(CodeGeneratorFlag.InstanceAsync) || rpcAttribute.GeneratorFlag.HasFlag(CodeGeneratorFlag.InstanceSync))
if (rpcAttribute.GeneratorFlag.HasFlag(CodeGeneratorFlag.InstanceAsync))
{
serverCellCode.IncludeInstance = true;
}
if (rpcAttribute.GeneratorFlag.HasFlag(CodeGeneratorFlag.ExtensionAsync) || rpcAttribute.GeneratorFlag.HasFlag(CodeGeneratorFlag.ExtensionSync))
if (rpcAttribute.GeneratorFlag.HasFlag(CodeGeneratorFlag.ExtensionAsync))
{
serverCellCode.IncludeExtension = true;
}

View File

@@ -21,6 +21,7 @@ public enum CodeGeneratorFlag
/// <summary>
/// 生成扩展同步代码
/// </summary>
[Obsolete("此配置已被弃用,目前已经不再支持同步代码生成", true)]
ExtensionSync = 1,
/// <summary>
@@ -31,6 +32,7 @@ public enum CodeGeneratorFlag
/// <summary>
/// 生成实例类同步代码(源代码生成无效)
/// </summary>
[Obsolete("此配置已被弃用,目前已经不再支持同步代码生成", true)]
InstanceSync = 4,
/// <summary>
@@ -41,6 +43,7 @@ public enum CodeGeneratorFlag
/// <summary>
/// 生成接口同步代码
/// </summary>
[Obsolete("此配置已被弃用,目前已经不再支持同步代码生成", true)]
InterfaceSync = 16,
/// <summary>

View File

@@ -24,10 +24,12 @@ public class TransportOption
/// </summary>
public TransportOption()
{
this.ReceivePipeOptions = CreateDefaultPipeOptions();
this.SendPipeOptions = CreateDefaultPipeOptions();
this.ReceivePipeOptions = CreateDefaultReadPipeOptions();
this.SendPipeOptions = CreateDefaultWritePipeOptions();
}
public bool BufferOnDemand { get; set; } = true;
/// <summary>
/// 获取或设置最大缓冲区大小(字节)。
/// </summary>
@@ -48,25 +50,8 @@ public class TransportOption
/// </summary>
public PipeOptions SendPipeOptions { get; set; }
public bool BufferOnDemand { get; set; } = true;
/// <summary>
/// 创建默认的 <see cref="PipeOptions"/>。
/// </summary>
public static PipeOptions CreateDefaultPipeOptions()
{
return new PipeOptions(
pool: null,
readerScheduler: null,
writerScheduler: null,
pauseWriterThreshold: -1,
resumeWriterThreshold: -1,
minimumSegmentSize: -1,
useSynchronizationContext: true);
}
/// <summary>
/// 创建注重调度的 <see cref="PipeOptions"/>,适合需要主线程调度的场景。
/// 创建注重调度的 <see cref="PipeOptions"/>。
/// </summary>
public static PipeOptions CreateSchedulerOptimizedPipeOptions()
{
@@ -74,9 +59,33 @@ public class TransportOption
pool: null,
readerScheduler: PipeScheduler.Inline,
writerScheduler: PipeScheduler.Inline,
pauseWriterThreshold: -1,
resumeWriterThreshold: -1,
pauseWriterThreshold: 1024 * 64,
resumeWriterThreshold: 1024 * 32,
minimumSegmentSize: -1,
useSynchronizationContext: false);
}
private static PipeOptions CreateDefaultReadPipeOptions()
{
return new PipeOptions(
pool: null,
readerScheduler: PipeScheduler.ThreadPool,
writerScheduler: PipeScheduler.ThreadPool,
pauseWriterThreshold: 1024 * 1024,
resumeWriterThreshold: 1024 * 512,
minimumSegmentSize: -1,
useSynchronizationContext: true);
}
private static PipeOptions CreateDefaultWritePipeOptions()
{
return new PipeOptions(
pool: null,
readerScheduler: PipeScheduler.ThreadPool,
writerScheduler: PipeScheduler.ThreadPool,
pauseWriterThreshold: 64 * 1024,
resumeWriterThreshold: 32 * 1024,
minimumSegmentSize: -1,
useSynchronizationContext: true);
}
}