mirror of
https://gitee.com/langsisi_admin/serein-flow
synced 2026-03-02 15:50:47 +08:00
修改了http服务器无法正确处理post请求入参;添加了modbus tcp客户端支持。
This commit is contained in:
@@ -130,7 +130,7 @@ namespace Serein.Library.Network
|
||||
}
|
||||
else if (jsonObject != null && PostArgTypes[i] == PostArgType.IsBobyData)
|
||||
{
|
||||
args[i] = jsonObject;
|
||||
args[i] = jsonObject.ToObject(type);
|
||||
}
|
||||
else if (jsonObject != null)
|
||||
{
|
||||
|
||||
@@ -36,10 +36,10 @@ namespace Serein.Library.Web
|
||||
/// <summary>
|
||||
/// 标记该类为 Web Api 处理类
|
||||
/// </summary>
|
||||
public class AutoHostingAttribute : Attribute
|
||||
public class WebApiControllerAttribute : Attribute
|
||||
{
|
||||
public string Url { get; }
|
||||
public AutoHostingAttribute(string url = "")
|
||||
public WebApiControllerAttribute(string url = "")
|
||||
{
|
||||
this.Url = url;
|
||||
}
|
||||
|
||||
@@ -92,7 +92,7 @@ namespace Serein.Library.Web
|
||||
{
|
||||
if (!controllerType.IsClass || controllerType.IsAbstract) return; // 如果不是类或者是抽象类,则直接返回
|
||||
|
||||
var autoHostingAttribute = controllerType.GetCustomAttribute<AutoHostingAttribute>();
|
||||
var autoHostingAttribute = controllerType.GetCustomAttribute<WebApiControllerAttribute>();
|
||||
var methods = controllerType.GetMethods().Where(m => m.GetCustomAttribute<WebApiAttribute>() != null).ToArray();
|
||||
|
||||
|
||||
@@ -264,7 +264,7 @@ namespace Serein.Library.Web
|
||||
/// <param name="controllerType">控制器类型</param>
|
||||
/// <param name="method">方法信息</param>
|
||||
/// <returns>方法对应的urk</returns>
|
||||
private string AddRoutesUrl(AutoHostingAttribute autoHostingAttribute, WebApiAttribute webAttribute, Type controllerType, MethodInfo method)
|
||||
private string AddRoutesUrl(WebApiControllerAttribute autoHostingAttribute, WebApiAttribute webAttribute, Type controllerType, MethodInfo method)
|
||||
{
|
||||
string controllerName;
|
||||
if (string.IsNullOrWhiteSpace(autoHostingAttribute.Url))
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Net;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
@@ -47,8 +48,15 @@ namespace Serein.Library.Web
|
||||
{
|
||||
while (listener.IsListening)
|
||||
{
|
||||
var context = await listener.GetContextAsync(); // 获取请求上下文
|
||||
ProcessRequestAsync(context); // 处理请求
|
||||
try
|
||||
{
|
||||
var context = await listener.GetContextAsync(); // 获取请求上下文
|
||||
await ProcessRequestAsync(context); // 处理请求
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.WriteLine(ex.Message);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -84,7 +92,7 @@ namespace Serein.Library.Web
|
||||
/// </summary>
|
||||
/// <param name="context"></param>
|
||||
/// <returns></returns>
|
||||
private async void ProcessRequestAsync(HttpListenerContext context)
|
||||
private async Task ProcessRequestAsync(HttpListenerContext context)
|
||||
{
|
||||
// 添加CORS头部
|
||||
context.Response.Headers.Add("Access-Control-Allow-Origin", "*");
|
||||
|
||||
47
Library/Network/Modbus/ModbusFunctionCode.cs
Normal file
47
Library/Network/Modbus/ModbusFunctionCode.cs
Normal file
@@ -0,0 +1,47 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Serein.Library.Network.Modbus
|
||||
{
|
||||
/// <summary>
|
||||
/// Modbus 功能码枚举
|
||||
/// </summary>
|
||||
public enum ModbusFunctionCode
|
||||
{
|
||||
/// <summary>
|
||||
/// 读线圈
|
||||
/// </summary>
|
||||
ReadCoils = 0x01,
|
||||
/// <summary>
|
||||
/// 读离散输入
|
||||
/// </summary>
|
||||
ReadDiscreteInputs = 0x02,
|
||||
/// <summary>
|
||||
/// 读保持寄存器
|
||||
/// </summary>
|
||||
ReadHoldingRegisters = 0x03,
|
||||
/// <summary>
|
||||
/// 读输入寄存器
|
||||
/// </summary>
|
||||
ReadInputRegisters = 0x04,
|
||||
/// <summary>
|
||||
/// 写单个线圈
|
||||
/// </summary>
|
||||
WriteSingleCoil = 0x05,
|
||||
/// <summary>
|
||||
/// 写单个寄存器
|
||||
/// </summary>
|
||||
WriteSingleRegister = 0x06,
|
||||
/// <summary>
|
||||
/// 写多个线圈
|
||||
/// </summary>
|
||||
WriteMultipleCoils = 0x0F,
|
||||
/// <summary>
|
||||
/// 写多个寄存器
|
||||
/// </summary>
|
||||
WriteMultipleRegister = 0x10,
|
||||
}
|
||||
}
|
||||
403
Library/Network/Modbus/ModbusTcpClient.cs
Normal file
403
Library/Network/Modbus/ModbusTcpClient.cs
Normal file
@@ -0,0 +1,403 @@
|
||||
using System;
|
||||
using System.Buffers.Binary;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net.Sockets;
|
||||
using System.Text;
|
||||
using System.Threading.Channels;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace Serein.Library.Network.Modbus
|
||||
{
|
||||
/// <summary>
|
||||
/// Modbus TCP 客户端
|
||||
/// </summary>
|
||||
public class ModbusTcpClient : IDisposable
|
||||
{
|
||||
/// <summary>
|
||||
/// 消息通道
|
||||
/// </summary>
|
||||
private readonly Channel<ModbusTcpRequest> _channel = Channel.CreateUnbounded<ModbusTcpRequest>();
|
||||
/// <summary>
|
||||
/// TCP客户端
|
||||
/// </summary>
|
||||
private readonly TcpClient _tcpClient;
|
||||
/// <summary>
|
||||
/// TCP客户端的网络流,用于发送和接收数据
|
||||
/// </summary>
|
||||
private readonly NetworkStream _stream;
|
||||
/// <summary>
|
||||
/// 存储未完成请求的字典,键为事务ID,值为任务完成源
|
||||
/// </summary>
|
||||
private readonly ConcurrentDictionary<ushort, TaskCompletionSource<byte[]>> _pendingRequests = new();
|
||||
/// <summary>
|
||||
/// 事务ID计数器,用于生成唯一的事务ID
|
||||
/// </summary>
|
||||
private int _transactionId = 0;
|
||||
|
||||
public ModbusTcpClient(string host, int port = 502)
|
||||
{
|
||||
_tcpClient = new TcpClient();
|
||||
_tcpClient.Connect(host, port);
|
||||
_stream = _tcpClient.GetStream();
|
||||
|
||||
_ = ProcessQueueAsync(); // 启动后台消费者
|
||||
_ = ReceiveLoopAsync(); // 启动接收响应线程
|
||||
}
|
||||
|
||||
#region 功能码封装
|
||||
|
||||
/// <summary>
|
||||
/// 读取线圈状态
|
||||
/// </summary>
|
||||
/// <param name="startAddress"></param>
|
||||
/// <param name="quantity"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<bool[]> ReadCoils(ushort startAddress, ushort quantity)
|
||||
{
|
||||
var pdu = BuildReadPdu(startAddress, quantity);
|
||||
var responsePdu = await SendAsync(ModbusFunctionCode.ReadCoils, pdu);
|
||||
return ParseDiscreteBits(responsePdu, quantity);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 读取离散输入状态
|
||||
/// </summary>
|
||||
/// <param name="startAddress"></param>
|
||||
/// <param name="quantity"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<bool[]> ReadDiscreteInputs(ushort startAddress, ushort quantity)
|
||||
{
|
||||
var pdu = BuildReadPdu(startAddress, quantity);
|
||||
var responsePdu = await SendAsync(ModbusFunctionCode.ReadDiscreteInputs, pdu);
|
||||
return ParseDiscreteBits(responsePdu, quantity);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 读取保持寄存器
|
||||
/// </summary>
|
||||
/// <param name="startAddress"></param>
|
||||
/// <param name="quantity"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<ushort[]> ReadHoldingRegisters(ushort startAddress, ushort quantity)
|
||||
{
|
||||
var pdu = BuildReadPdu(startAddress, quantity);
|
||||
var responsePdu = await SendAsync(ModbusFunctionCode.ReadHoldingRegisters, pdu);
|
||||
return ParseRegisters(responsePdu, quantity);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 读取输入寄存器
|
||||
/// </summary>
|
||||
/// <param name="startAddress"></param>
|
||||
/// <param name="quantity"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<ushort[]> ReadInputRegisters(ushort startAddress, ushort quantity)
|
||||
{
|
||||
var pdu = BuildReadPdu(startAddress, quantity);
|
||||
var responsePdu = await SendAsync(ModbusFunctionCode.ReadInputRegisters, pdu);
|
||||
return ParseRegisters(responsePdu, quantity);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 写单个线圈
|
||||
/// </summary>
|
||||
/// <param name="address"></param>
|
||||
/// <param name="value"></param>
|
||||
/// <returns></returns>
|
||||
public async Task WriteSingleCoil(ushort address, bool value)
|
||||
{
|
||||
var pdu = new byte[]
|
||||
{
|
||||
(byte)(address >> 8), // 地址高字节
|
||||
(byte)(address & 0xFF), // 地址低字节
|
||||
value ? (byte)0xFF : (byte)0x00, // 线圈值高字节,高电平为0xFF,低电平为00
|
||||
0x00 // 线圈值低字节
|
||||
};
|
||||
await SendAsync(ModbusFunctionCode.WriteSingleCoil, pdu);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 写单个寄存器
|
||||
/// </summary>
|
||||
/// <param name="address"></param>
|
||||
/// <param name="value"></param>
|
||||
/// <returns></returns>
|
||||
public async Task WriteSingleRegister(ushort address, ushort value)
|
||||
{
|
||||
var pdu = new byte[]
|
||||
{
|
||||
(byte)(address >> 8), // 地址高字节
|
||||
(byte)(address & 0xFF), // 地址低字节
|
||||
(byte)(value >> 8), // 寄存器值高字节
|
||||
(byte)(value & 0xFF) // 寄存器值低字节
|
||||
};
|
||||
await SendAsync(ModbusFunctionCode.WriteSingleRegister, pdu);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 写多个线圈
|
||||
/// </summary>
|
||||
/// <param name="startAddress"></param>
|
||||
/// <param name="values"></param>
|
||||
/// <returns></returns>
|
||||
public async Task WriteMultipleCoils(ushort startAddress, bool[] values)
|
||||
{
|
||||
int byteCount = (values.Length + 7) / 8; // 计算需要的字节数
|
||||
byte[] data = new byte[byteCount];
|
||||
|
||||
for (int i = 0; i < values.Length; i++)
|
||||
{
|
||||
if (values[i])
|
||||
data[i / 8] |= (byte)(1 << (i % 8)); // 设置对应位
|
||||
}
|
||||
|
||||
var pdu = new List<byte>
|
||||
{
|
||||
(byte)(startAddress >> 8), // 地址高字节
|
||||
(byte)(startAddress & 0xFF), // 地址低字节
|
||||
(byte)(values.Length >> 8), // 数量高字节
|
||||
(byte)(values.Length & 0xFF), // 数量低字节
|
||||
(byte)data.Length // 字节数
|
||||
};
|
||||
|
||||
pdu.AddRange(data);
|
||||
|
||||
await SendAsync(ModbusFunctionCode.WriteMultipleCoils, pdu.ToArray());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 写多个寄存器
|
||||
/// </summary>
|
||||
/// <param name="startAddress"></param>
|
||||
/// <param name="values"></param>
|
||||
/// <returns></returns>
|
||||
public async Task WriteMultipleRegisters(ushort startAddress, ushort[] values)
|
||||
{
|
||||
var pdu = new List<byte>
|
||||
{
|
||||
(byte)(startAddress >> 8), // 地址高字节
|
||||
(byte)(startAddress & 0xFF), // 地址低字节
|
||||
(byte)(values.Length >> 8), // 数量高字节
|
||||
(byte)(values.Length & 0xFF), // 数量低字节
|
||||
(byte)(values.Length * 2) // 字节数
|
||||
};
|
||||
|
||||
foreach (var val in values)
|
||||
{
|
||||
pdu.Add((byte)(val >> 8)); // 寄存器值高字节
|
||||
pdu.Add((byte)(val & 0xFF)); // 寄存器值低字节
|
||||
}
|
||||
|
||||
await SendAsync(ModbusFunctionCode.WriteMultipleRegister, pdu.ToArray());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 构建读取PDU数据
|
||||
/// </summary>
|
||||
/// <param name="startAddress"></param>
|
||||
/// <param name="quantity"></param>
|
||||
/// <returns></returns>
|
||||
private byte[] BuildReadPdu(ushort startAddress, ushort quantity)
|
||||
{
|
||||
byte[] buffer = new byte[4];
|
||||
BinaryPrimitives.WriteUInt16BigEndian(buffer.AsSpan(0, 2), startAddress); // 起始地址高低字节
|
||||
BinaryPrimitives.WriteUInt16BigEndian(buffer.AsSpan(2, 2), quantity); // 读取数量高低字节
|
||||
return buffer;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 解析离散位数据
|
||||
/// </summary>
|
||||
/// <param name="pdu"></param>
|
||||
/// <param name="count"></param>
|
||||
/// <returns></returns>
|
||||
private bool[] ParseDiscreteBits(byte[] pdu, ushort count)
|
||||
{
|
||||
int byteCount = pdu[2]; // 第2字节是后续的字节数量
|
||||
int dataIndex = 3; // 数据从第3字节开始(0-based)
|
||||
|
||||
var result = new bool[count];
|
||||
|
||||
for (int i = 0, bytePos = 0, bitPos = 0; i < count; i++, bitPos++)
|
||||
{
|
||||
if (bitPos == 8)
|
||||
{
|
||||
bitPos = 0;
|
||||
bytePos++;
|
||||
}
|
||||
result[i] = ((pdu[dataIndex + bytePos] >> bitPos) & 0x01) != 0;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 解析寄存器数据
|
||||
/// </summary>
|
||||
/// <param name="pdu"></param>
|
||||
/// <param name="count"></param>
|
||||
/// <returns></returns>
|
||||
private ushort[] ParseRegisters(byte[] pdu, ushort count)
|
||||
{
|
||||
var result = new ushort[count];
|
||||
int dataStart = 3; // 数据从第3字节开始
|
||||
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
int offset = dataStart + i * 2;
|
||||
result[i] = (ushort)((pdu[offset] << 8) | pdu[offset + 1]);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// 处理消息队列,发送请求到服务器
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private async Task ProcessQueueAsync()
|
||||
{
|
||||
var request = await _channel.Reader.ReadAsync();
|
||||
byte[] packet = BuildPacket(request.TransactionId, 0x01, (byte)request.FunctionCode, request.PDU);
|
||||
await _stream.WriteAsync(packet, 0, packet.Length);
|
||||
await _stream.FlushAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 发送请求并等待响应
|
||||
/// </summary>
|
||||
/// <param name="functionCode">功能码</param>
|
||||
/// <param name="pdu">内容</param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="TimeoutException"></exception>
|
||||
public Task<byte[]> SendAsync(ModbusFunctionCode functionCode, byte[] pdu)
|
||||
{
|
||||
int id = Interlocked.Increment(ref _transactionId);
|
||||
var transactionId = (ushort)(id % ushort.MaxValue); // 0~65535 循环
|
||||
var tcs = new TaskCompletionSource<byte[]>(TaskCreationOptions.RunContinuationsAsynchronously);
|
||||
|
||||
var request = new ModbusTcpRequest
|
||||
{
|
||||
TransactionId = transactionId,
|
||||
FunctionCode = functionCode,
|
||||
PDU = pdu,
|
||||
Completion = tcs
|
||||
};
|
||||
_pendingRequests[transactionId] = tcs;
|
||||
_channel.Writer.TryWrite(request);
|
||||
|
||||
return tcs.Task;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 接收数据循环
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private async Task ReceiveLoopAsync()
|
||||
{
|
||||
var buffer = new byte[1024];
|
||||
while (true)
|
||||
{
|
||||
#if NET462
|
||||
int len = await _stream.ReadAsync(buffer, 0, buffer.Length).ConfigureAwait(false);
|
||||
#else
|
||||
int len = await _stream.ReadAsync(buffer.AsMemory(0, buffer.Length)).ConfigureAwait(false);
|
||||
#endif
|
||||
|
||||
if (len == 0) return; // 连接关闭
|
||||
|
||||
if (len < 6)
|
||||
{
|
||||
Console.WriteLine("接收到的数据长度不足");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
ushort protocolId = BinaryPrimitives.ReadUInt16BigEndian(buffer.AsSpan(2, 2));
|
||||
if (protocolId != 0x0000)
|
||||
{
|
||||
Console.WriteLine($"协议不匹配: {protocolId:X4}");
|
||||
return;
|
||||
}
|
||||
|
||||
ushort dataLength = BinaryPrimitives.ReadUInt16BigEndian(buffer.AsSpan(4, 2));
|
||||
// 检查数据长度是否合法
|
||||
if (dataLength > 253 || len < 6 + dataLength)
|
||||
{
|
||||
Console.WriteLine($"数据长度异常: dataLength={dataLength}, 实际接收={len}");
|
||||
return;
|
||||
}
|
||||
|
||||
ushort transactionId = BinaryPrimitives.ReadUInt16BigEndian(buffer.AsSpan(0, 2));
|
||||
if (_pendingRequests.TryRemove(transactionId, out var tcs))
|
||||
{
|
||||
var responsePdu = new ReadOnlySpan<byte>(buffer, 6, dataLength).ToArray();
|
||||
tcs.SetResult(responsePdu); // 如需 byte[] 则 ToArray
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine($"未匹配到 TransactionId={transactionId} 的请求");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 构造 Modbus Tcp 报文
|
||||
/// </summary>
|
||||
/// <param name="transactionId"></param>
|
||||
/// <param name="unitId"></param>
|
||||
/// <param name="functionCode"></param>
|
||||
/// <param name="pduData"></param>
|
||||
/// <returns></returns>
|
||||
private byte[] BuildPacket(ushort transactionId, byte unitId, byte functionCode, byte[] pduData)
|
||||
{
|
||||
int pduLength = 1 + pduData.Length; // PDU 长度 = 功能码1字节 + 数据长度
|
||||
int totalLength = 7 + pduLength; // MBAP头长度 = 7字节 + PDU长度
|
||||
|
||||
Span<byte> packet = totalLength <= 256 ? stackalloc byte[totalLength] : new byte[totalLength];
|
||||
|
||||
// 写入事务ID(大端序)
|
||||
packet[0] = (byte)(transactionId >> 8);
|
||||
packet[1] = (byte)(transactionId);
|
||||
|
||||
// 协议ID(固定0x0000)
|
||||
packet[2] = 0;
|
||||
packet[3] = 0;
|
||||
|
||||
// 长度(PDU长度 + 1字节UnitID)
|
||||
ushort length = (ushort)(pduLength + 1);
|
||||
packet[4] = (byte)(length >> 8);
|
||||
packet[5] = (byte)(length);
|
||||
|
||||
// UnitID & 功能码
|
||||
packet[6] = unitId;
|
||||
packet[7] = functionCode;
|
||||
|
||||
// 复制PDU数据
|
||||
pduData.AsSpan().CopyTo(packet.Slice(8));
|
||||
|
||||
return packet.ToArray();
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
var tcs = _pendingRequests.Values.ToArray();
|
||||
foreach (var pending in tcs)
|
||||
{
|
||||
pending.TrySetCanceled();
|
||||
}
|
||||
_stream?.Close();
|
||||
_tcpClient?.Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
32
Library/Network/Modbus/ModbusTcpRequest.cs
Normal file
32
Library/Network/Modbus/ModbusTcpRequest.cs
Normal file
@@ -0,0 +1,32 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Serein.Library.Network.Modbus
|
||||
{
|
||||
/// <summary>
|
||||
/// Modbus TCP 请求实体
|
||||
/// </summary>
|
||||
public class ModbusTcpRequest
|
||||
{
|
||||
/// <summary>
|
||||
/// 事务ID
|
||||
/// </summary>
|
||||
public ushort TransactionId { get; set; }
|
||||
/// <summary>
|
||||
/// 功能码
|
||||
/// </summary>
|
||||
public ModbusFunctionCode FunctionCode { get; set; }
|
||||
/// <summary>
|
||||
/// PDU 数据
|
||||
/// </summary>
|
||||
public byte[] PDU { get; set; }
|
||||
/// <summary>
|
||||
/// 请求的完成源,用于异步等待响应
|
||||
/// </summary>
|
||||
public TaskCompletionSource<byte[]> Completion { get; set; }
|
||||
}
|
||||
|
||||
}
|
||||
110
Library/ScriptBaseFunc.cs
Normal file
110
Library/ScriptBaseFunc.cs
Normal file
@@ -0,0 +1,110 @@
|
||||
using Serein.Library;
|
||||
using Serein.Library.Utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Serein.Library
|
||||
{
|
||||
|
||||
|
||||
public static class ScriptBaseFunc
|
||||
{
|
||||
public static DateTime now() => DateTime.Now;
|
||||
|
||||
#region 常用的类型转换
|
||||
public static bool @bool(object value)
|
||||
{
|
||||
return ConvertHelper.ValueParse<bool>(value);
|
||||
}
|
||||
public static byte @byte(object value)
|
||||
{
|
||||
return ConvertHelper.ValueParse<byte>(value);
|
||||
}
|
||||
public static decimal @decimal(object value)
|
||||
{
|
||||
return ConvertHelper.ValueParse<decimal>(value);
|
||||
}
|
||||
public static float @float(object value)
|
||||
{
|
||||
return ConvertHelper.ValueParse<float>(value);
|
||||
}
|
||||
public static double @double(object value)
|
||||
{
|
||||
return ConvertHelper.ValueParse<double>(value);
|
||||
}
|
||||
public static int @int(object value)
|
||||
{
|
||||
return ConvertHelper.ValueParse<int>(value);
|
||||
}
|
||||
public static int @long(object value)
|
||||
{
|
||||
return ConvertHelper.ValueParse<int>(value);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public static int len(object target)
|
||||
{
|
||||
// 获取数组或集合对象
|
||||
// 访问数组或集合中的指定索引
|
||||
if (target is Array array)
|
||||
{
|
||||
return array.Length;
|
||||
}
|
||||
else if (target is string chars)
|
||||
{
|
||||
return chars.Length;
|
||||
}
|
||||
else if (target is IDictionary<object, object> dict)
|
||||
{
|
||||
return dict.Count;
|
||||
}
|
||||
else if (target is IList<object> list)
|
||||
{
|
||||
return list.Count;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ArgumentException($"并非有效集合");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static string str(object obj)
|
||||
{
|
||||
return obj?.ToString() ?? string.Empty;
|
||||
}
|
||||
|
||||
|
||||
public static object global(string name)
|
||||
{
|
||||
return SereinEnv.GetFlowGlobalData(name);
|
||||
}
|
||||
|
||||
public static Type type(object type)
|
||||
{
|
||||
return type.GetType();
|
||||
}
|
||||
|
||||
public static void log(object value)
|
||||
{
|
||||
SereinEnv.WriteLine(InfoType.INFO, value?.ToString());
|
||||
}
|
||||
|
||||
public static async Task sleep(object value)
|
||||
{
|
||||
if (value is int @int)
|
||||
{
|
||||
Console.WriteLine($"等待{@int}ms");
|
||||
await Task.Delay(@int);
|
||||
}
|
||||
else if (value is TimeSpan timeSpan)
|
||||
{
|
||||
Console.WriteLine($"等待{timeSpan}");
|
||||
await Task.Delay(timeSpan);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<Version>1.2.0</Version>
|
||||
<Version>1.2.1.1</Version>
|
||||
<TargetFrameworks>net8.0;net462</TargetFrameworks>
|
||||
<BaseOutputPath>..\.\.Output</BaseOutputPath>
|
||||
<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
using Newtonsoft.Json.Linq;
|
||||
using Serein.Library.Api;
|
||||
using Serein.Library.Utils;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Reactive.Linq;
|
||||
using System.Reactive.Subjects;
|
||||
using System.Threading;
|
||||
using System.Threading.Channels;
|
||||
using System.Threading.Tasks;
|
||||
using System.Transactions;
|
||||
|
||||
namespace Serein.Library.Utils
|
||||
{
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user