Files
serein-flow/Library/Network/WebSocket/Attribute.cs

169 lines
6.9 KiB
C#
Raw Normal View History

using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
using System.Net.WebSockets;
namespace Serein.Library.Network.WebSocketCommunication
{
2024-10-10 20:52:19 +08:00
/// <summary>
/// <para>标记该类是处理模板需要获取WebSocketServer/WebSocketClient了实例后使用(Server/Client).MsgHandleHelper.AddModule()进行添加。</para>
/// <para>处理模板需要继承 ISocketHandleModule 接口否则WebSocket接受到数据时将无法进行调用相应的处理模板。</para>
/// <para>使用方式:</para>
/// <para>[AutoSocketModule(ThemeKey = "theme", DataKey = "data")]</para>
/// <para>public class PlcSocketService : ISocketHandleModule</para>
2024-10-11 16:46:16 +08:00
/// <para>类中方法示例void AddUser(string name,int age)</para>
2024-10-10 20:52:19 +08:00
/// <para>Json示例{ "theme":"AddUser", //【ThemeKey】 </para>
/// <para> "data": { // 【DataKey】 </para>
/// <para> "name":"张三", </para>
/// <para> "age":35, } } </para>
2024-10-11 16:46:16 +08:00
/// <para>WebSocket中收到以上该Json时通过ThemeKey获取到"AddUser"然后找到AddUser()方法</para>
/// <para>然后根据方法入参名称从data对应的json数据中取出"name""age"对应的数据作为入参进行调用。AddUser("张三",35)</para>
2024-10-10 20:52:19 +08:00
/// <para></para>
/// </summary>
[AttributeUsage(AttributeTargets.Class)]
public sealed class AutoSocketModuleAttribute : Attribute
{
/// <summary>
/// 业务标识
/// </summary>
2024-10-10 20:52:19 +08:00
public string ThemeKey;
/// <summary>
/// 数据标识
/// </summary>
2024-10-10 20:52:19 +08:00
public string DataKey;
/// <summary>
/// ID标识
/// </summary>
public string MsgIdKey;
2024-10-10 20:52:19 +08:00
}
/// <summary>
/// <para>作用WebSocket中处理Json时将通过Json中ThemeKey 对应的内容ThemeValue自动路由到相应方法进行处理同时要求Data中必须存在对应入参。</para>
/// <para>如果没有显式设置 ThemeValue将默认使用方法名称作为ThemeValue。</para>
/// <para>如果没有显式设置 IsReturnValue 标记为 false 当方法顺利完成没有抛出异常且返回对象非null会自动转为json文本发送回去</para>
/// <para>如果没有显式设置 ArgNotNull 标记为 false ,当外部尝试调用时,若 Json Data 不包含响应的数据,将会被忽略此次调用</para>
2024-10-10 20:52:19 +08:00
/// <para>如果返回类型为Task或Task&lt;TResult&gt;将会自动等待异步完成并获取结果无法处理Task&lt;Task&lt;TResult&gt;&gt;的情况)。</para>
/// <para>如果返回了值类型,会自动装箱为引用对象。</para>
/// <para>如果有方法执行过程中发送消息的需求,请在入参中声明以下类型的成员,调用时将传入发送消息的委托。</para>
/// <para>Action&lt;string&gt; : 发送文本内容。</para>
/// <para>Action&lt;object&gt; : 会自动将对象解析为Json字符串发送文本内容。</para>
/// <para>Action&lt;dynamic&gt; : 会自动将对象解析为Json字符串发送文本内容。</para>
/// <para>Func&lt;string,Task&gt; : 异步发送文本内容。</para>
/// <para>Func&lt;object,Task&gt; : 会自动将对象解析为Json字符串异步发送文本内容。</para>
/// <para>Func&lt;dynamic,Task&gt; : 会自动将对象解析为Json字符串异步发送文本内容。</para>
/// </summary>
[AttributeUsage(AttributeTargets.Method)]
public sealed class AutoSocketHandleAttribute : Attribute
{
2024-10-10 20:52:19 +08:00
/// <summary>
/// 描述Json业务字段如果不设置将默认使用方法名称。
/// </summary>
public string ThemeValue = string.Empty;
2024-10-10 20:52:19 +08:00
/// <summary>
/// <para>标记方法执行完成后是否需要将结果发送。</para>
/// <para>注意以下返回值,返回的 json 中将不会新建 DataKey 字段:</para>
/// <para>1.返回类型为 void </para>
/// <para>2.返回类型为 Task </para>
/// <para>2.返回类型为 Unit </para>
2024-10-10 20:52:19 +08:00
/// <para>补充如果返回类型是Task&lt;TResult&gt;</para>
/// <para>会进行异步等待当Task结束后自动获取TResult进行发送请避免Task&lt;Task&lt;TResult&gt;&gt;诸如此类的Task泛型嵌套</para>
/// </summary>
public bool IsReturnValue = true;
/// <summary>
/// <para>表示该方法所有入参不能为空所需的参数在请求Json的Data不存在</para>
/// <para>若有一个参数无法从data获取则不会进行调用该方法</para>
/// <para>如果设置该属性为 false ,但某些入参不能为空,而不希望在代码中进行检查,请为入参添加[NotNull]/[Needful]特性</para>
/// </summary>
public bool ArgNotNull = true;
}
/// <summary>
/// 使用 DataKey 整体数据
/// </summary>
[AttributeUsage(AttributeTargets.Parameter)]
public sealed class UseDataAttribute : Attribute
{
}
/// <summary>
/// 使用 MsgIdKey 整体数据
/// </summary>
[AttributeUsage(AttributeTargets.Parameter)]
public sealed class UseMsgIdAttribute : Attribute
{
}
internal class WebSocketHandleConfiguration : HandleConfiguration
{
/// <summary>
/// 主题
/// </summary>
public string ThemeValue { get; set; } = string.Empty;
}
/// <summary>
/// socket模块处理数据配置
/// </summary>
public class HandleConfiguration
{
/// <summary>
/// Emit委托
/// </summary>
public DelegateDetails DelegateDetails { get; set; }
/// <summary>
/// 未捕获的异常跟踪
/// </summary>
public Action<Exception, Action<object>> OnExceptionTracking { get; set; }
/// <summary>
/// 所使用的实例
/// </summary>
public ISocketHandleModule Instance { get; set; }
/// <summary>
/// 是否需要返回
/// </summary>
public bool IsReturnValue { get; set; } = true;
/// <summary>
/// 是否要求必须不为null
/// </summary>
public bool ArgNotNull { get; set; } = true;
/// <summary>
/// 是否使Data整体内容作为入参参数
/// </summary>
public bool[] UseData { get; set; }
/// <summary>
/// 是否使用消息ID作为入参参数
/// </summary>
public bool[] UseMsgId { get; set; }
/// <summary>
/// 参数名称
/// </summary>
public string[] ParameterName { get; set; }
/// <summary>
/// 参数类型
/// </summary>
public Type[] ParameterType { get; set; }
/// <summary>
/// 是否检查变量为空
/// </summary>
public bool[] IsCheckArgNotNull { get; set; }
}
2024-10-10 20:52:19 +08:00
}