mirror of
https://github.com/RRQM/TouchSocket.git
synced 2025-12-18 17:36:43 +08:00
补充仓库
This commit is contained in:
83
README.md
83
README.md
@@ -28,20 +28,16 @@
|
||||
## 💿描述
|
||||
| 名称 |描述|
|
||||
|---|---|
|
||||
| [](https://www.nuget.org/packages/RRQMCore/) | RRQMCore是为RRQM系提供基础服务功能的库,其中包含:<br>**内存池**、**对象池**、**等待逻辑池**、**AppMessenger**、**3DES加密**、<br>**Xml快速存储**、**运行时间测量器**、**文件快捷操作**、<br>**高性能序列化器**、**规范日志接口**等。 |
|
||||
|[](https://www.nuget.org/packages/RRQMSocket/)| **RRQMSocket**是一个整合性的、超轻量级的、可以免费商用使用<br>的网络通信服务框架。它具有 **高并发连接** 、 **高并发处理** 、 <br>**事件订阅** 、 **插件式扩展** 、 **多线程处理** 、 **内存池** 、 **对象池** <br>等特点,让使用者能够更加简单的、快速的搭建网络框架。|
|
||||
|[](https://www.nuget.org/packages/RRQMSocketFramework/)| **RRQMSocketFramework**是RRQMSocket系列的增强企业版,<br>两者在基础功能上没有区别,但是在扩展功能上有一定差异性,<br>例如RPC中的EventBus、文件传输中的限速功能等,<br>具体差异请看[RRQM商业运营](https://gitee.com/RRQM_OS/RRQM/wikis/%E5%95%86%E4%B8%9A%E8%BF%90%E8%90%A5)|
|
||||
|
||||
## 🎀依赖、扩展库
|
||||
| 名称 |描述|
|
||||
|---|---|
|
||||
| [](https://gitee.com/RRQM_OS/RRQMCore) | RRQMCore是为RRQM系提供基础服务功能的库,其中包含:<br>**内存池**、**对象池**、**等待逻辑池**、**AppMessenger**、**3DES加密**、<br>**Xml快速存储**、**运行时间测量器**、**文件快捷操作**、<br>**高性能序列化器**、**规范日志接口**等。 |
|
||||
| [](https://gitee.com/RRQM_OS/rrqmsocket.filetransfer) | RRQMSocket.FileTransfer是一个高性能的文件传输框架,您可以<br>用它传输**任意大小**的文件,它可以完美支持**上传下载混合式队列传输**、<br>**断点续传**、 **快速上传** 、**传输限速**、**获取文件信息**、**删除文件**等。<br>在实时测试中,它的传输速率可达1000Mb/s。 |
|
||||
| [](https://gitee.com/RRQM_OS/rrqmsocket.websocket) | RRQMSocket.WebSocket是一个高效,超轻量级的WebSocket框架。<br>它包含了Service和Client两大组件,同时定义了文本、二进制或<br>其他类型数据的快捷发送、分片发送接口,可与js等任意WebSocket组件交互|
|
||||
| [](https://gitee.com/RRQM_OS/rrqmsocket.http) | RRQMSocket.Http是一个能够简单解析Http的服务组件,<br>能够快速响应Http服务请求。|
|
||||
|[](https://gitee.com/RRQM_OS/rrqmsocket.rpc) |RPC是一个超轻量、高性能、可扩展的微服务管理平台框架,<br>目前已完成开发**RRQMRPC**、**XmlRpc**、**JsonRpc**、**WebApi**部分。<br> **RRQMRPC**部分使用RRQM专属协议,支持客户端**异步调用**,<br>服务端**异步触发**、以及**out**和**ref**关键字,**函数回调**等。<br>在调用效率上也是非常强悍,在调用空载函数,且返回状态时,<br>**10w**次调用仅用时**3.8**秒,不返回状态用时**0.9**秒。<br>其他协议调用性能详看性能评测。
|
||||
|[](https://gitee.com/RRQM_OS/rrqmsocket.rpc.xmlrpc)| XmlRpc是一个扩展于RRQMSocket.RPC的XmlRpc组件,可以通过<br>该组件创建XmlRpc服务解析器,完美支持XmlRpc数据类型,类型嵌套,<br>Array等,也能与CookComputing.XmlRpcV2完美对接。<br>不限Web,Android等平台。|
|
||||
| [](https://gitee.com/RRQM_OS/rrqmsocket.rpc.jsonrpc)| JsonRpc是一个扩展于RRQMSocket.RPC的JsonRpc组件,<br>可以通过该组件创建JsonRpc服务解析器,支持JsonRpc全部功能,可与Web,Android等平台无缝对接。|
|
||||
|[](https://gitee.com/RRQM_OS/rrqmsocket.rpc.webapi)| WebApi是一个扩展于RRQMSocket.RPC的WebApi组件,可以通过<br>该组件创建WebApi服务解析器,让桌面端、Web端、移动端可以<br>跨语言调用RPC函数。功能支持路由、Get传参、Post传参等。|
|
||||
|[](https://www.nuget.org/packages/RRQMSocketFramework/)| **RRQMSocketFramework**是RRQMSocket系列的企业版,两者在<br>功能上几乎没有区别,但是RRQMSocketFramework无任何依赖,<br>且可以提供专属的定制功能。具体差异请看[RRQM商业运营](https://gitee.com/RRQM_OS/RRQM/wikis/%E5%95%86%E4%B8%9A%E8%BF%90%E8%90%A5)|
|
||||
| [](https://www.nuget.org/packages/RRQMSocket.FileTransfer/) | RRQMSocket.FileTransfer是一个高性能的文件传输框架,您可以<br>用它传输**任意大小**的文件,它可以完美支持**上传下载混合式队列传输**、<br>**断点续传**、 **快速上传** 、**传输限速**、**获取文件信息**、**删除文件**等。<br>在实时测试中,它的传输速率可达1000Mb/s。 |
|
||||
| [](https://www.nuget.org/packages/RRQMSocket.WebSocket/) | RRQMSocket.WebSocket是一个高效,超轻量级的WebSocket框架。<br>它包含了Service和Client两大组件,同时定义了文本、二进制或<br>其他类型数据的快捷发送、分片发送接口,可与js等任意WebSocket组件交互|
|
||||
| [](https://www.nuget.org/packages/RRQMSocket.Http/) | RRQMSocket.Http是一个能够简单解析Http的服务组件,<br>能够快速响应Http服务请求。|
|
||||
|[](https://www.nuget.org/packages/RRQMSocket.RPC/) |RPC是一个超轻量、高性能、可扩展的微服务管理平台框架,<br>目前已完成开发**RRQMRPC**、**XmlRpc**、**JsonRpc**、**WebApi**部分。<br> **RRQMRPC**部分使用RRQM专属协议,支持客户端**异步调用**,<br>服务端**异步触发**、以及**out**和**ref**关键字,**函数回调**等。<br>在调用效率上也是非常强悍,在调用空载函数,且返回状态时,<br>**10w**次调用仅用时**3.8**秒,不返回状态用时**0.9**秒。<br>其他协议调用性能详看性能评测。
|
||||
|[](https://www.nuget.org/packages/RRQMSocket.RPC.XmlRpc/)| XmlRpc是一个扩展于RRQMSocket.RPC的XmlRpc组件,可以通过<br>该组件创建XmlRpc服务解析器,完美支持XmlRpc数据类型,类型嵌套,<br>Array等,也能与CookComputing.XmlRpcV2完美对接。<br>不限Web,Android等平台。|
|
||||
| [](https://www.nuget.org/packages/RRQMSocket.RPC.JsonRpc/)| JsonRpc是一个扩展于RRQMSocket.RPC的JsonRpc组件,<br>可以通过该组件创建JsonRpc服务解析器,支持JsonRpc全部功能,可与Web,Android等平台无缝对接。|
|
||||
|[](https://www.nuget.org/packages/RRQMSocket.RPC.WebApi/)| WebApi是一个扩展于RRQMSocket.RPC的WebApi组件,可以通过<br>该组件创建WebApi服务解析器,让桌面端、Web端、移动端可以<br>跨语言调用RPC函数。功能支持路由、Get传参、Post传参等。|
|
||||
|
||||
|
||||
## 🖥支持环境
|
||||
@@ -66,7 +62,7 @@ RRQMSocket的IOCP和传统也不一样,就以微软官方示例为例,使用
|
||||
|
||||
#### 数据处理适配器
|
||||
|
||||
相信大家都使用过其他的Socket产品,例如HPSocket,SuperSocket等,那么RRQMSocket在设计时也是借鉴了其他产品的优秀设计理念,数据处理适配器就是其中之一,但和其他产品的设计不同的是,RRQMSocket的适配器功能更加强大,它不仅可以提前解析数据包,还可以解析数据对象。例如:可以使用固定包头对数据进行预处理,从而解决**数据分包**、**粘包**的问题。也可以直接解析**HTTP**数据协议、WebSocket数据协议等。
|
||||
相信大家都使用过其他的Socket产品,例如HPSocket,SuperSocket等,那么RRQMSocket在设计时也是借鉴了其他产品的优秀设计理念,数据处理适配器就是其中之一,但和其他产品的设计不同的是,RRQMSocket的适配器功能更加强大,它不仅可以提前解析数据包,还可以解析数据对象。例如:可以使用固定包头对数据进行预处理,从而解决数据分包、粘包的问题。也可以直接解析HTTP协议,经过适配器处理后传回一个HttpRequest对象等。
|
||||
|
||||
#### 兼容性与适配
|
||||
|
||||
@@ -79,6 +75,12 @@ RRQMSocket提供多种框架模型,能够完全兼容基于TCP、UDP协议的
|
||||
- [源代码仓库主页](https://gitee.com/RRQM_Home)
|
||||
- 交流QQ群:234762506
|
||||
|
||||
## 🍻RRQM系产品
|
||||
|
||||
| 名称| 版本(Nuget Version)|下载(Nuget Download)| 描述 |
|
||||
|------|----------|-------------|-------|
|
||||
| [RRQMSkin](https://gitee.com/RRQM_OS/RRQMSkin) | [](https://www.nuget.org/packages/RRQMSkin/) | [](https://www.nuget.org/packages/RRQMSkin/) | RRQMSkin是WPF的控件样式库,其中包含: **无边框窗体** 、 **圆角窗体** 、 **水波纹按钮** 、 **输入提示筛选框** 、 **控件拖动效果** 、**圆角图片框**、 **弧形文字** 、 **扇形元素** 、 **指针元素** 、 **饼图** 、 **时钟** 、 **速度表盘** 等。|
|
||||
|
||||
## 🌟API手册
|
||||
- [ API首页 ](https://gitee.com/RRQM_OS/RRQM/wikis/pages)
|
||||
- [说明](https://gitee.com/RRQM_OS/RRQM/wikis/pages?sort_id=3984529&doc_id=1402901)
|
||||
@@ -88,28 +90,42 @@ RRQMSocket提供多种框架模型,能够完全兼容基于TCP、UDP协议的
|
||||
|
||||
|
||||
## ✨简单示例
|
||||
|
||||
**_更多配置请查看API文档的配置说明文档,一下仅以最简方式创建实例。_**
|
||||
|
||||
【TcpService】
|
||||
|
||||
```
|
||||
SimpleTcpService service = new SimpleTcpService();
|
||||
service.Connected += (client, e) =>{//有客户端连接};
|
||||
service.Disconnected += (client, e) =>{//有客户端断开连接};
|
||||
service.Connecting += (client, e) =>{//e.IsPermitOperation = false;//是否允许连接};
|
||||
|
||||
service.Connected += (client, e) =>
|
||||
{
|
||||
//有客户端连接
|
||||
};
|
||||
|
||||
service.Disconnected += (client, e) =>
|
||||
{
|
||||
//有客户端断开连接
|
||||
};
|
||||
|
||||
service.Connecting += (client, e) =>
|
||||
{
|
||||
//e.IsPermitOperation = false;//是否允许连接
|
||||
};
|
||||
|
||||
service.Received += (client, byteBlock, obj) =>
|
||||
{
|
||||
//从客户端收到信息
|
||||
string mes = Encoding.UTF8.GetString(byteBlock.Buffer, 0, byteBlock.Len);
|
||||
Console.WriteLine($"已从{client.Name}接收到信息:{mes}");//Name即IP+Port
|
||||
};
|
||||
|
||||
//声明配置
|
||||
var config = new TcpServiceConfig();
|
||||
config.ListenIPHosts = new IPHost[] { new IPHost("127.0.0.1:7789"), new IPHost(7790) };//同时监听两个地址
|
||||
|
||||
//载入配置
|
||||
service.Setup(config);
|
||||
|
||||
//启动
|
||||
|
||||
try
|
||||
{
|
||||
service.Start();
|
||||
@@ -119,18 +135,37 @@ catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine(ex.Message);
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
【TcpClient】
|
||||
|
||||
```
|
||||
SimpleTcpClient tcpClient = new SimpleTcpClient();
|
||||
tcpClient.Connected += (client, e) =>{//成功连接到服务器};
|
||||
tcpClient.Disconnected += (client, e) =>{//从服务器断开连接,当连接不成功时不会触发。};
|
||||
|
||||
tcpClient.Connected += (client, e) =>
|
||||
{
|
||||
//成功连接到服务器
|
||||
};
|
||||
|
||||
tcpClient.Disconnected += (client, e) =>
|
||||
{
|
||||
//从服务器断开连接,当连接不成功时不会触发。
|
||||
};
|
||||
|
||||
//声明配置
|
||||
var config = new TcpClientConfig();
|
||||
config.RemoteIPHost = new IPHost("127.0.0.1:7789");//远程IPHost
|
||||
|
||||
//载入配置
|
||||
tcpClient.Setup("127.0.0.1:7789");
|
||||
tcpClient.Setup(config);
|
||||
|
||||
tcpClient.Connect();
|
||||
tcpClient.Send(new byte[]{1,2,3});
|
||||
|
||||
while (true)
|
||||
{
|
||||
tcpClient.Send(new byte[]{1,2,3});
|
||||
}
|
||||
```
|
||||
|
||||
## 🧲应用场景模拟
|
||||
|
||||
880
RRQMCore/ByteManager/ByteBlock.cs
Normal file
880
RRQMCore/ByteManager/ByteBlock.cs
Normal file
@@ -0,0 +1,880 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权(除特别声明或在RRQMCore.XREF命名空间的代码)归作者本人若汝棋茗所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权
|
||||
// CSDN博客:https://blog.csdn.net/qq_40374647
|
||||
// 哔哩哔哩视频:https://space.bilibili.com/94253567
|
||||
// Gitee源代码仓库:https://gitee.com/RRQM_Home
|
||||
// Github源代码仓库:https://github.com/RRQM
|
||||
// 交流QQ群:234762506
|
||||
// 感谢您的下载和使用
|
||||
//------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------
|
||||
using RRQMCore.Exceptions;
|
||||
using RRQMCore.Serialization;
|
||||
using RRQMCore.XREF.Newtonsoft.Json;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
|
||||
namespace RRQMCore.ByteManager
|
||||
{
|
||||
/// <summary>
|
||||
/// 字节块流
|
||||
/// </summary>
|
||||
public sealed class ByteBlock : Stream, IDisposable
|
||||
{
|
||||
internal bool @using;
|
||||
|
||||
internal long length;
|
||||
|
||||
private static float ratio = 1.5f;
|
||||
|
||||
private byte[] _buffer;
|
||||
|
||||
private bool holding;
|
||||
|
||||
private long position;
|
||||
|
||||
/// <summary>
|
||||
/// 构造函数
|
||||
/// </summary>
|
||||
/// <param name="capacity"></param>
|
||||
/// <param name="equalSize"></param>
|
||||
public ByteBlock(int capacity = 1024 * 10, bool equalSize = false) : this(BytePool.GetByteCore(capacity, equalSize))
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 构造函数
|
||||
/// </summary>
|
||||
/// <param name="bytes"></param>
|
||||
internal ByteBlock(byte[] bytes)
|
||||
{
|
||||
this.@using = true;
|
||||
this._buffer = bytes;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 扩容增长比,默认为1.5,
|
||||
/// min:1.5
|
||||
/// </summary>
|
||||
public static float Ratio
|
||||
{
|
||||
get { return ratio; }
|
||||
set
|
||||
{
|
||||
if (value < 1.5)
|
||||
{
|
||||
value = 1.5f;
|
||||
}
|
||||
ratio = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 字节实例
|
||||
/// </summary>
|
||||
public byte[] Buffer
|
||||
{
|
||||
get { return _buffer; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 可读取
|
||||
/// </summary>
|
||||
public override bool CanRead => this.@using;
|
||||
|
||||
/// <summary>
|
||||
/// 支持查找
|
||||
/// </summary>
|
||||
public override bool CanSeek => this.@using;
|
||||
|
||||
/// <summary>
|
||||
/// 可写入
|
||||
/// </summary>
|
||||
public override bool CanWrite => this.@using;
|
||||
|
||||
/// <summary>
|
||||
/// 容量
|
||||
/// </summary>
|
||||
public int Capacity => this._buffer.Length;
|
||||
|
||||
/// <summary>
|
||||
/// 表示持续性持有,为True时,Dispose将调用无效。
|
||||
/// </summary>
|
||||
public bool Holding
|
||||
{
|
||||
get { return holding; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Int真实长度
|
||||
/// </summary>
|
||||
public int Len
|
||||
{ get { return (int)length; } }
|
||||
|
||||
/// <summary>
|
||||
/// 真实长度
|
||||
/// </summary>
|
||||
public override long Length
|
||||
{ get { return length; } }
|
||||
|
||||
/// <summary>
|
||||
/// int型流位置
|
||||
/// </summary>
|
||||
public int Pos
|
||||
{
|
||||
get { return (int)position; }
|
||||
set { position = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 流位置
|
||||
/// </summary>
|
||||
public override long Position
|
||||
{
|
||||
get { return position; }
|
||||
set { position = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 使用状态
|
||||
/// </summary>
|
||||
public bool Using
|
||||
{
|
||||
get { return @using; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 直接完全释放,游离该对象,然后等待GC
|
||||
/// </summary>
|
||||
public void AbsoluteDispose()
|
||||
{
|
||||
this.holding = false;
|
||||
this.@using = false;
|
||||
this.position = 0;
|
||||
this.length = 0;
|
||||
this._buffer = default;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 清空数据
|
||||
/// </summary>
|
||||
public void Clear()
|
||||
{
|
||||
if (!this.@using)
|
||||
{
|
||||
throw new RRQMException("内存块已释放");
|
||||
}
|
||||
Array.Clear(this._buffer, 0, this._buffer.Length);
|
||||
}
|
||||
/// <summary>
|
||||
/// 回收资源
|
||||
/// </summary>
|
||||
public new void Dispose()
|
||||
{
|
||||
if (this.holding)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (this.@using)
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
if (this.@using)
|
||||
{
|
||||
GC.SuppressFinalize(this);
|
||||
BytePool.Recycle(this._buffer);
|
||||
this.AbsoluteDispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 无实际效果
|
||||
/// </summary>
|
||||
public override void Flush()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 读取
|
||||
/// </summary>
|
||||
/// <param name="buffer"></param>
|
||||
/// <param name="offset"></param>
|
||||
/// <param name="count"></param>
|
||||
/// <returns></returns>
|
||||
public override int Read(byte[] buffer, int offset, int count)
|
||||
{
|
||||
if (!this.@using)
|
||||
{
|
||||
throw new RRQMException("内存块已释放");
|
||||
}
|
||||
int len = this._buffer.Length - this.position > count ? count : this._buffer.Length - (int)this.position;
|
||||
Array.Copy(this._buffer, this.position, buffer, offset, len);
|
||||
this.position += len;
|
||||
return len;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 读取数据
|
||||
/// </summary>
|
||||
/// <param name="buffer"></param>
|
||||
/// <returns></returns>
|
||||
public int Read(byte[] buffer)
|
||||
{
|
||||
return Read(buffer, 0, buffer.Length);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置流位置
|
||||
/// </summary>
|
||||
/// <param name="offset"></param>
|
||||
/// <param name="origin"></param>
|
||||
/// <returns></returns>
|
||||
public override long Seek(long offset, SeekOrigin origin)
|
||||
{
|
||||
if (!this.@using)
|
||||
{
|
||||
throw new RRQMException("内存块已释放");
|
||||
}
|
||||
switch (origin)
|
||||
{
|
||||
case SeekOrigin.Begin:
|
||||
this.position = offset;
|
||||
break;
|
||||
|
||||
case SeekOrigin.Current:
|
||||
this.position = offset;
|
||||
break;
|
||||
|
||||
case SeekOrigin.End:
|
||||
this.position = this.length + offset;
|
||||
break;
|
||||
}
|
||||
return this.position;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 重新设置容量
|
||||
/// </summary>
|
||||
/// <param name="size">新尺寸</param>
|
||||
/// <param name="retainedData">是否保留元数据</param>
|
||||
public void SetCapacity(int size, bool retainedData = false)
|
||||
{
|
||||
if (!this.@using)
|
||||
{
|
||||
throw new RRQMException("内存块已释放");
|
||||
}
|
||||
byte[] bytes = new byte[size];
|
||||
|
||||
if (retainedData)
|
||||
{
|
||||
Array.Copy(this._buffer, 0, bytes, 0, this._buffer.Length);
|
||||
}
|
||||
BytePool.Recycle(this._buffer);
|
||||
this._buffer = bytes;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置持续持有属性,当为True时,调用Dispose会失效,表示该对象将长期持有,直至设置为False。
|
||||
/// 当为False时,会自动调用Dispose。
|
||||
/// </summary>
|
||||
/// <param name="holding"></param>
|
||||
public void SetHolding(bool holding)
|
||||
{
|
||||
if (!this.@using)
|
||||
{
|
||||
throw new RRQMException("内存块已释放");
|
||||
}
|
||||
this.holding = holding;
|
||||
if (!holding)
|
||||
{
|
||||
this.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置实际长度
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
public override void SetLength(long value)
|
||||
{
|
||||
if (!this.@using)
|
||||
{
|
||||
throw new RRQMException("内存块已释放");
|
||||
}
|
||||
if (value > this._buffer.Length)
|
||||
{
|
||||
throw new RRQMException("设置值超出容量");
|
||||
}
|
||||
this.length = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 转换为有效内存
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public byte[] ToArray()
|
||||
{
|
||||
return ToArray(0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 从指定位置转化到有效内存
|
||||
/// </summary>
|
||||
/// <param name="offset"></param>
|
||||
/// <returns></returns>
|
||||
public byte[] ToArray(int offset)
|
||||
{
|
||||
if (!this.@using)
|
||||
{
|
||||
throw new RRQMException("内存块已释放");
|
||||
}
|
||||
byte[] buffer = new byte[this.length - offset];
|
||||
Array.Copy(this._buffer, offset, buffer, 0, buffer.Length);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 写入
|
||||
/// </summary>
|
||||
/// <param name="buffer"></param>
|
||||
/// <param name="offset"></param>
|
||||
/// <param name="count"></param>
|
||||
public override void Write(byte[] buffer, int offset, int count)
|
||||
{
|
||||
if (!this.@using)
|
||||
{
|
||||
throw new RRQMException("内存块已释放");
|
||||
}
|
||||
if (this._buffer.Length - this.position < count)
|
||||
{
|
||||
int need = this._buffer.Length + count - ((int)(this._buffer.Length - this.position));
|
||||
int lend = this._buffer.Length;
|
||||
while (need > lend)
|
||||
{
|
||||
lend = (int)(lend * ratio);
|
||||
}
|
||||
this.SetCapacity(lend, true);
|
||||
}
|
||||
Array.Copy(buffer, offset, _buffer, this.position, count);
|
||||
this.position += count;
|
||||
this.length += count;
|
||||
if (this.length<this.position)
|
||||
{
|
||||
this.length = this.position;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 写入
|
||||
/// </summary>
|
||||
/// <param name="buffer"></param>
|
||||
/// <returns></returns>
|
||||
public void Write(byte[] buffer)
|
||||
{
|
||||
this.Write(buffer, 0, buffer.Length);
|
||||
}
|
||||
|
||||
#region BytesPackage
|
||||
|
||||
/// <summary>
|
||||
/// 从当前流位置读取一个独立的<see cref="byte"/>数组包
|
||||
/// </summary>
|
||||
public byte[] ReadBytesPackage()
|
||||
{
|
||||
byte status = this.ReadByte();
|
||||
if (status == 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
int length = this.ReadInt32();
|
||||
byte[] data = new byte[length];
|
||||
Array.Copy(this._buffer, this.position, data, 0, length);
|
||||
this.position += length;
|
||||
return data;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 尝试获取数据包信息,方便从Buffer操作数据
|
||||
/// </summary>
|
||||
/// <param name="pos"></param>
|
||||
/// <param name="len"></param>
|
||||
/// <returns></returns>
|
||||
public bool TryReadBytesPackageInfo(out int pos, out int len)
|
||||
{
|
||||
byte status = this.ReadByte();
|
||||
if (status == 0)
|
||||
{
|
||||
pos = 0;
|
||||
len = 0;
|
||||
return false;
|
||||
}
|
||||
len = this.ReadInt32();
|
||||
pos = (int)this.position;
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 写入一个独立的<see cref="byte"/>数组包
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
/// <param name="offset"></param>
|
||||
/// <param name="length"></param>
|
||||
public ByteBlock WriteBytesPackage(byte[] value, int offset, int length)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
this.Write((byte)0);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.Write((byte)1);
|
||||
this.Write(length);
|
||||
this.Write(value, offset, length);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 写入一个独立的<see cref="byte"/>数组包
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
public ByteBlock WriteBytesPackage(byte[] value)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
return this.WriteBytesPackage(value, 0, 0);
|
||||
}
|
||||
return this.WriteBytesPackage(value, 0, value.Length);
|
||||
}
|
||||
|
||||
#endregion BytesPackage
|
||||
|
||||
#region Int32
|
||||
|
||||
/// <summary>
|
||||
/// 从当前流位置读取一个<see cref="int"/>值
|
||||
/// </summary>
|
||||
public int ReadInt32()
|
||||
{
|
||||
int value = RRQMBitConverter.Default.ToInt32(this._buffer, (int)this.position);
|
||||
this.position += 4;
|
||||
return value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 写入<see cref="int"/>值
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
public ByteBlock Write(int value)
|
||||
{
|
||||
this.Write(RRQMBitConverter.Default.GetBytes(value));
|
||||
return this;
|
||||
}
|
||||
|
||||
#endregion Int32
|
||||
|
||||
#region Int16
|
||||
|
||||
/// <summary>
|
||||
/// 从当前流位置读取一个<see cref="short"/>值
|
||||
/// </summary>
|
||||
public short ReadInt16()
|
||||
{
|
||||
short value = RRQMBitConverter.Default.ToInt16(this._buffer, (int)this.position);
|
||||
this.position += 2;
|
||||
return value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 写入<see cref="short"/>值
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
public ByteBlock Write(short value)
|
||||
{
|
||||
this.Write(RRQMBitConverter.Default.GetBytes(value));
|
||||
return this;
|
||||
}
|
||||
|
||||
#endregion Int16
|
||||
|
||||
#region Int64
|
||||
|
||||
/// <summary>
|
||||
/// 从当前流位置读取一个<see cref="long"/>值
|
||||
/// </summary>
|
||||
public long ReadInt64()
|
||||
{
|
||||
long value = RRQMBitConverter.Default.ToInt64(this._buffer, (int)this.position);
|
||||
this.position += 8;
|
||||
return value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 写入<see cref="long"/>值
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
public ByteBlock Write(long value)
|
||||
{
|
||||
this.Write(RRQMBitConverter.Default.GetBytes(value));
|
||||
return this;
|
||||
}
|
||||
|
||||
#endregion Int64
|
||||
|
||||
#region Boolean
|
||||
|
||||
/// <summary>
|
||||
/// 从当前流位置读取一个<see cref="bool"/>值
|
||||
/// </summary>
|
||||
public bool ReadBoolean()
|
||||
{
|
||||
bool value = RRQMBitConverter.Default.ToBoolean(this._buffer, (int)this.position);
|
||||
this.position += 1;
|
||||
return value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 写入<see cref="bool"/>值
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
public ByteBlock Write(bool value)
|
||||
{
|
||||
this.Write(RRQMBitConverter.Default.GetBytes(value));
|
||||
return this;
|
||||
}
|
||||
|
||||
#endregion Boolean
|
||||
|
||||
#region Byte
|
||||
|
||||
/// <summary>
|
||||
/// 从当前流位置读取一个<see cref="byte"/>值
|
||||
/// </summary>
|
||||
public new byte ReadByte()
|
||||
{
|
||||
byte value = this._buffer[this.position];
|
||||
this.position++;
|
||||
return value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 写入<see cref="byte"/>值
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
/// <returns></returns>
|
||||
public ByteBlock Write(byte value)
|
||||
{
|
||||
this.Write(new byte[] { value }, 0, 1);
|
||||
return this;
|
||||
}
|
||||
|
||||
#endregion Byte
|
||||
|
||||
#region String
|
||||
|
||||
/// <summary>
|
||||
/// 从当前流位置读取一个<see cref="string"/>值
|
||||
/// </summary>
|
||||
public string ReadString()
|
||||
{
|
||||
byte value = this.ReadByte();
|
||||
if (value == 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
else if (value == 1)
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
else
|
||||
{
|
||||
ushort len = this.ReadUInt16();
|
||||
string str = Encoding.UTF8.GetString(this._buffer, (int)this.position, len);
|
||||
this.position += len;
|
||||
return str;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 写入<see cref="string"/>值
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
public ByteBlock Write(string value)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
this.Write((byte)0);
|
||||
}
|
||||
else if (value == string.Empty)
|
||||
{
|
||||
this.Write((byte)1);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.Write((byte)2);
|
||||
byte[] buffer = Encoding.UTF8.GetBytes(value);
|
||||
if (buffer.Length > ushort.MaxValue)
|
||||
{
|
||||
throw new RRQMException("传输长度超长");
|
||||
}
|
||||
this.Write((ushort)buffer.Length);
|
||||
this.Write(buffer);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
#endregion String
|
||||
|
||||
#region Char
|
||||
|
||||
/// <summary>
|
||||
/// 从当前流位置读取一个<see cref="char"/>值
|
||||
/// </summary>
|
||||
public char ReadChar()
|
||||
{
|
||||
char value = RRQMBitConverter.Default.ToChar(this._buffer, (int)this.position);
|
||||
this.position += 2;
|
||||
return value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 写入<see cref="char"/>值
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
public ByteBlock Write(char value)
|
||||
{
|
||||
this.Write(RRQMBitConverter.Default.GetBytes(value));
|
||||
return this;
|
||||
}
|
||||
|
||||
#endregion Char
|
||||
|
||||
#region Double
|
||||
|
||||
/// <summary>
|
||||
/// 从当前流位置读取一个<see cref="double"/>值
|
||||
/// </summary>
|
||||
public double ReadDouble()
|
||||
{
|
||||
double value = RRQMBitConverter.Default.ToDouble(this._buffer, (int)this.position);
|
||||
this.position += 8;
|
||||
return value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 写入<see cref="double"/>值
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
public ByteBlock Write(double value)
|
||||
{
|
||||
this.Write(RRQMBitConverter.Default.GetBytes(value));
|
||||
return this;
|
||||
}
|
||||
|
||||
#endregion Double
|
||||
|
||||
#region Float
|
||||
|
||||
/// <summary>
|
||||
/// 从当前流位置读取一个<see cref="float"/>值
|
||||
/// </summary>
|
||||
public double ReadFloat()
|
||||
{
|
||||
float value = RRQMBitConverter.Default.ToSingle(this._buffer, (int)this.position);
|
||||
this.position += 4;
|
||||
return value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 写入<see cref="float"/>值
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
public ByteBlock Write(float value)
|
||||
{
|
||||
this.Write(RRQMBitConverter.Default.GetBytes(value));
|
||||
return this;
|
||||
}
|
||||
|
||||
#endregion Float
|
||||
|
||||
#region UInt16
|
||||
|
||||
/// <summary>
|
||||
/// 从当前流位置读取一个<see cref="ushort"/>值
|
||||
/// </summary>
|
||||
public ushort ReadUInt16()
|
||||
{
|
||||
ushort value = RRQMBitConverter.Default.ToUInt16(this._buffer, (int)this.position);
|
||||
this.position += 2;
|
||||
return value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 写入<see cref="ushort"/>值
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
public ByteBlock Write(ushort value)
|
||||
{
|
||||
this.Write(RRQMBitConverter.Default.GetBytes(value));
|
||||
return this;
|
||||
}
|
||||
|
||||
#endregion UInt16
|
||||
|
||||
#region UInt32
|
||||
|
||||
/// <summary>
|
||||
/// 从当前流位置读取一个<see cref="uint"/>值
|
||||
/// </summary>
|
||||
public uint ReadUInt32()
|
||||
{
|
||||
uint value = RRQMBitConverter.Default.ToUInt32(this._buffer, (int)this.position);
|
||||
this.position += 4;
|
||||
return value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 写入<see cref="uint"/>值
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
public ByteBlock Write(uint value)
|
||||
{
|
||||
this.Write(RRQMBitConverter.Default.GetBytes(value));
|
||||
return this;
|
||||
}
|
||||
|
||||
#endregion UInt32
|
||||
|
||||
#region UInt64
|
||||
|
||||
/// <summary>
|
||||
/// 从当前流位置读取一个<see cref="ulong"/>值
|
||||
/// </summary>
|
||||
public ulong ReadUInt64()
|
||||
{
|
||||
ulong value = RRQMBitConverter.Default.ToUInt64(this._buffer, (int)this.position);
|
||||
this.position += 8;
|
||||
return value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 写入<see cref="ulong"/>值
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
public ByteBlock Write(ulong value)
|
||||
{
|
||||
this.Write(RRQMBitConverter.Default.GetBytes(value));
|
||||
return this;
|
||||
}
|
||||
|
||||
#endregion UInt64
|
||||
|
||||
#region DateTime
|
||||
|
||||
/// <summary>
|
||||
/// 从当前流位置读取一个<see cref="DateTime"/>值
|
||||
/// </summary>
|
||||
public DateTime ReadDateTime()
|
||||
{
|
||||
long value = RRQMBitConverter.Default.ToInt64(this._buffer, (int)this.position);
|
||||
this.position += 8;
|
||||
return DateTime.FromBinary(value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 写入<see cref="DateTime"/>值
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
public ByteBlock Write(DateTime value)
|
||||
{
|
||||
this.Write(RRQMBitConverter.Default.GetBytes(value.ToBinary()));
|
||||
return this;
|
||||
}
|
||||
|
||||
#endregion DateTime
|
||||
|
||||
#region Object
|
||||
|
||||
/// <summary>
|
||||
/// 从当前流位置读取一个泛型值
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="serializationType"></param>
|
||||
/// <returns></returns>
|
||||
public T ReadObject<T>(SerializationType serializationType = SerializationType.RRQMBinary)
|
||||
{
|
||||
int length = this.ReadInt32();
|
||||
|
||||
if (length == 0)
|
||||
{
|
||||
return default;
|
||||
}
|
||||
|
||||
T obj;
|
||||
|
||||
switch (serializationType)
|
||||
{
|
||||
case SerializationType.RRQMBinary:
|
||||
{
|
||||
obj = SerializeConvert.RRQMBinaryDeserialize<T>(this._buffer, (int)this.position);
|
||||
}
|
||||
break;
|
||||
|
||||
case SerializationType.Json:
|
||||
{
|
||||
string jsonString = Encoding.UTF8.GetString(this._buffer, (int)this.position, length);
|
||||
obj = JsonConvert.DeserializeObject<T>(jsonString);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new RRQMException("未定义的序列化类型");
|
||||
}
|
||||
|
||||
this.position += length;
|
||||
return obj;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 写入<see cref="object"/>值
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
/// <param name="serializationType"></param>
|
||||
public ByteBlock WriteObject(object value, SerializationType serializationType = SerializationType.RRQMBinary)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
this.Write(0);
|
||||
return this;
|
||||
}
|
||||
byte[] data;
|
||||
switch (serializationType)
|
||||
{
|
||||
case SerializationType.RRQMBinary:
|
||||
{
|
||||
data = SerializeConvert.RRQMBinarySerialize(value);
|
||||
}
|
||||
break;
|
||||
|
||||
case SerializationType.Json:
|
||||
{
|
||||
data = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(value));
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new RRQMException("未定义的序列化类型");
|
||||
}
|
||||
|
||||
this.Write(data.Length);
|
||||
this.Write(data);
|
||||
return this;
|
||||
}
|
||||
|
||||
#endregion Object
|
||||
}
|
||||
}
|
||||
478
RRQMCore/ByteManager/BytePool.cs
Normal file
478
RRQMCore/ByteManager/BytePool.cs
Normal file
@@ -0,0 +1,478 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权(除特别声明或在RRQMCore.XREF命名空间的代码)归作者本人若汝棋茗所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权
|
||||
// CSDN博客:https://blog.csdn.net/qq_40374647
|
||||
// 哔哩哔哩视频:https://space.bilibili.com/94253567
|
||||
// Gitee源代码仓库:https://gitee.com/RRQM_Home
|
||||
// Github源代码仓库:https://github.com/RRQM
|
||||
// 交流QQ群:234762506
|
||||
// 感谢您的下载和使用
|
||||
//------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace RRQMCore.ByteManager
|
||||
{
|
||||
/// <summary>
|
||||
/// 字节池
|
||||
/// </summary>
|
||||
public static class BytePool
|
||||
{
|
||||
private static readonly ConcurrentDictionary<long, BytesQueue> bytesDictionary = new ConcurrentDictionary<long, BytesQueue>();
|
||||
|
||||
private static bool autoZero;
|
||||
private static long fullSize;
|
||||
private static int keyCapacity;
|
||||
private static int maxBlockSize;
|
||||
private static long maxSize;
|
||||
private static int minBlockSize;
|
||||
|
||||
static BytePool()
|
||||
{
|
||||
keyCapacity = 100;
|
||||
autoZero = false;
|
||||
maxSize = 1024 * 1024 * 512;
|
||||
SetBlockSize(1024 * 64, 1024 * 1024 * 5);
|
||||
AddSizeKey(10240);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 回收内存时,自动归零
|
||||
/// </summary>
|
||||
public static bool AutoZero
|
||||
{
|
||||
get { return autoZero; }
|
||||
set { autoZero = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 键容量
|
||||
/// </summary>
|
||||
public static int KeyCapacity
|
||||
{
|
||||
get { return keyCapacity; }
|
||||
set { keyCapacity = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 单个块最大值
|
||||
/// </summary>
|
||||
public static int MaxBlockSize
|
||||
{
|
||||
get { return maxBlockSize; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 允许的内存池最大值
|
||||
/// </summary>
|
||||
public static long MaxSize
|
||||
{
|
||||
get { return maxSize; }
|
||||
set
|
||||
{
|
||||
if (value < 1024)
|
||||
{
|
||||
value = 1024;
|
||||
}
|
||||
maxSize = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 单个块最小值
|
||||
/// </summary>
|
||||
public static int MinBlockSize
|
||||
{
|
||||
get { return minBlockSize; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 添加尺寸键
|
||||
/// </summary>
|
||||
/// <param name="byteSize"></param>
|
||||
/// <returns></returns>
|
||||
public static bool AddSizeKey(int byteSize)
|
||||
{
|
||||
if (bytesDictionary.TryAdd(byteSize, new BytesQueue(byteSize)))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 清理
|
||||
/// </summary>
|
||||
public static void Clear()
|
||||
{
|
||||
bytesDictionary.Clear();
|
||||
GC.Collect();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 确定是否包含指定尺寸键
|
||||
/// </summary>
|
||||
/// <param name="byteSize"></param>
|
||||
/// <returns></returns>
|
||||
public static bool ContainsSizeKey(int byteSize)
|
||||
{
|
||||
return bytesDictionary.ContainsKey(byteSize);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取所以内存键
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static long[] GetAllSizeKeys()
|
||||
{
|
||||
return bytesDictionary.Keys.ToArray();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取ByteBlock
|
||||
/// </summary>
|
||||
/// <param name="byteSize">长度</param>
|
||||
/// <param name="equalSize">要求长度相同</param>
|
||||
/// <returns></returns>
|
||||
public static ByteBlock GetByteBlock(int byteSize, bool equalSize)
|
||||
{
|
||||
ByteBlock byteBlock = new ByteBlock(GetByteCore(byteSize, equalSize));
|
||||
return byteBlock;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取ByteBlock
|
||||
/// </summary>
|
||||
/// <param name="byteSize"></param>
|
||||
/// <returns></returns>
|
||||
public static ByteBlock GetByteBlock(int byteSize)
|
||||
{
|
||||
if (byteSize < minBlockSize)
|
||||
{
|
||||
byteSize = minBlockSize;
|
||||
}
|
||||
return GetByteBlock(byteSize, false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取最大长度的ByteBlock
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static ByteBlock GetByteBlock()
|
||||
{
|
||||
return GetByteBlock(maxBlockSize, true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取内存池容量
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static long GetPoolSize()
|
||||
{
|
||||
long size = 0;
|
||||
foreach (var item in bytesDictionary.Values)
|
||||
{
|
||||
size += item.FullSize;
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 移除尺寸键
|
||||
/// </summary>
|
||||
/// <param name="byteSize"></param>
|
||||
/// <returns></returns>
|
||||
public static bool RemoveSizeKey(int byteSize)
|
||||
{
|
||||
if (bytesDictionary.TryRemove(byteSize, out BytesQueue queue))
|
||||
{
|
||||
queue.Clear();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置内存块参数
|
||||
/// </summary>
|
||||
/// <param name="minBlockSize"></param>
|
||||
/// <param name="maxBlockSize"></param>
|
||||
public static void SetBlockSize(int minBlockSize, int maxBlockSize)
|
||||
{
|
||||
BytePool.maxBlockSize = maxBlockSize;
|
||||
BytePool.minBlockSize = minBlockSize;
|
||||
|
||||
bytesDictionary.Clear();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取内存核心
|
||||
/// </summary>
|
||||
/// <param name="byteSize"></param>
|
||||
/// <param name="equalSize"></param>
|
||||
/// <returns></returns>
|
||||
public static byte[] GetByteCore(int byteSize, bool equalSize)
|
||||
{
|
||||
BytesQueue bytesCollection;
|
||||
if (equalSize)
|
||||
{
|
||||
//等长
|
||||
if (bytesDictionary.TryGetValue(byteSize, out bytesCollection))
|
||||
{
|
||||
if (bytesCollection.TryGet(out byte[] bytes))
|
||||
{
|
||||
fullSize -= byteSize;
|
||||
return bytes;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
CheckKeyCapacity(byteSize);
|
||||
}
|
||||
return new byte[byteSize];
|
||||
}
|
||||
else
|
||||
{
|
||||
byteSize = HitSize(byteSize);
|
||||
//搜索已创建集合
|
||||
if (bytesDictionary.TryGetValue(byteSize, out bytesCollection))
|
||||
{
|
||||
if (bytesCollection.TryGet(out byte[] bytes))
|
||||
{
|
||||
fullSize -= byteSize;
|
||||
return bytes;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
CheckKeyCapacity(byteSize);
|
||||
}
|
||||
return new byte[byteSize];
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 回收内存核心
|
||||
/// </summary>
|
||||
/// <param name="bytes"></param>
|
||||
public static void Recycle(byte[] bytes)
|
||||
{
|
||||
if (maxSize > fullSize)
|
||||
{
|
||||
if (bytesDictionary.TryGetValue(bytes.Length, out BytesQueue bytesQueue))
|
||||
{
|
||||
if (autoZero)
|
||||
{
|
||||
Array.Clear(bytes, 0, bytes.Length);
|
||||
}
|
||||
fullSize += bytes.Length;
|
||||
bytesQueue.Add(bytes);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
long size = 0;
|
||||
foreach (var collection in bytesDictionary.Values)
|
||||
{
|
||||
size += collection.FullSize;
|
||||
}
|
||||
fullSize = size;
|
||||
}
|
||||
}
|
||||
|
||||
private static void CheckKeyCapacity(int byteSize)
|
||||
{
|
||||
if (byteSize < minBlockSize || byteSize > maxBlockSize)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (bytesDictionary.Count < keyCapacity)
|
||||
{
|
||||
bytesDictionary.TryAdd(byteSize, new BytesQueue(byteSize));
|
||||
}
|
||||
else
|
||||
{
|
||||
List<BytesQueue> bytesQueues = bytesDictionary.Values.ToList();
|
||||
bytesQueues.Sort((x, y) => { return x.referenced > y.referenced ? -1 : 1; });
|
||||
for (int i = (int)(bytesQueues.Count * 0.2); i < bytesQueues.Count; i++)
|
||||
{
|
||||
if (bytesDictionary.TryRemove(bytesQueues[i].size, out BytesQueue queue))
|
||||
{
|
||||
queue.Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static int HitSize(int num)
|
||||
{
|
||||
switch (num)
|
||||
{
|
||||
case <= 1024:
|
||||
{
|
||||
return 1024;
|
||||
}
|
||||
case <= 2048:
|
||||
{
|
||||
return 2048;
|
||||
}
|
||||
case <= 4096:
|
||||
{
|
||||
return 4096;
|
||||
}
|
||||
case <= 8192:
|
||||
{
|
||||
return 8192;
|
||||
}
|
||||
case <= 10240:
|
||||
{
|
||||
return 10240;
|
||||
}
|
||||
case <= 16384:
|
||||
{
|
||||
return 16384;
|
||||
}
|
||||
case <= 32768:
|
||||
{
|
||||
return 32768;
|
||||
}
|
||||
case <= 65536:
|
||||
{
|
||||
return 65536;
|
||||
}
|
||||
case <= 131072:
|
||||
{
|
||||
return 131072;
|
||||
}
|
||||
case <= 262144:
|
||||
{
|
||||
return 262144;
|
||||
}
|
||||
case <= 524288:
|
||||
{
|
||||
return 524288;
|
||||
}
|
||||
case <= 1048576:
|
||||
{
|
||||
return 1048576;
|
||||
}
|
||||
case <= 2097152:
|
||||
{
|
||||
return 2097152;
|
||||
}
|
||||
case <= 4194304:
|
||||
{
|
||||
return 4194304;
|
||||
}
|
||||
case <= 8388608:
|
||||
{
|
||||
return 8388608;
|
||||
}
|
||||
case <= 16777216:
|
||||
{
|
||||
return 16777216;
|
||||
}
|
||||
case <= 33554432:
|
||||
{
|
||||
return 33554432;
|
||||
}
|
||||
case <= 67108864:
|
||||
{
|
||||
return 67108864;
|
||||
}
|
||||
case <= 134217728:
|
||||
{
|
||||
return 134217728;
|
||||
}
|
||||
default:
|
||||
return num;
|
||||
}
|
||||
|
||||
//U3D无法编译时替换。
|
||||
|
||||
//if (num <= 1024)
|
||||
//{
|
||||
// return 1024;
|
||||
//}
|
||||
//else if (num <= 2048)
|
||||
//{
|
||||
// return 2048;
|
||||
//}
|
||||
//else if (num <= 4096)
|
||||
//{
|
||||
// return 4096;
|
||||
//}
|
||||
//else if (num <= 8192)
|
||||
//{
|
||||
// return 8192;
|
||||
//}
|
||||
//else if (num <= 10240)
|
||||
//{
|
||||
// return 10240;
|
||||
//}
|
||||
//else if (num <= 16384)
|
||||
//{
|
||||
// return 16384;
|
||||
//}
|
||||
//else if (num <= 32768)
|
||||
//{
|
||||
// return 32768;
|
||||
//}
|
||||
//else if (num <= 65536)
|
||||
//{
|
||||
// return 65536;
|
||||
//}
|
||||
//else if (num <= 131072)
|
||||
//{
|
||||
// return 131072;
|
||||
//}
|
||||
//else if (num <= 262144)
|
||||
//{
|
||||
// return 262144;
|
||||
//}
|
||||
//else if (num <= 524288)
|
||||
//{
|
||||
// return 524288;
|
||||
//}
|
||||
//else if (num <= 1048576)
|
||||
//{
|
||||
// return 1048576;
|
||||
//}
|
||||
//else if (num <= 2097152)
|
||||
//{
|
||||
// return 2097152;
|
||||
//}
|
||||
//else if (num <= 4194304)
|
||||
//{
|
||||
// return 4194304;
|
||||
//}
|
||||
//else if (num <= 8388608)
|
||||
//{
|
||||
// return 8388608;
|
||||
//}
|
||||
//else if (num <= 16777216)
|
||||
//{
|
||||
// return 16777216;
|
||||
//}
|
||||
//else if (num <= 33554432)
|
||||
//{
|
||||
// return 33554432;
|
||||
//}
|
||||
//else if (num <= 67108864)
|
||||
//{
|
||||
// return 67108864;
|
||||
//}
|
||||
//else if (num <= 134217728)
|
||||
//{
|
||||
// return 134217728;
|
||||
//}
|
||||
//else
|
||||
//{
|
||||
// return num;
|
||||
//}
|
||||
}
|
||||
}
|
||||
}
|
||||
66
RRQMCore/ByteManager/BytesQueue.cs
Normal file
66
RRQMCore/ByteManager/BytesQueue.cs
Normal file
@@ -0,0 +1,66 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权(除特别声明或在RRQMCore.XREF命名空间的代码)归作者本人若汝棋茗所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权
|
||||
// CSDN博客:https://blog.csdn.net/qq_40374647
|
||||
// 哔哩哔哩视频:https://space.bilibili.com/94253567
|
||||
// Gitee源代码仓库:https://gitee.com/RRQM_Home
|
||||
// Github源代码仓库:https://github.com/RRQM
|
||||
// 交流QQ群:234762506
|
||||
// 感谢您的下载和使用
|
||||
//------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------
|
||||
using RRQMCore.Exceptions;
|
||||
using RRQMCore.Helper;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace RRQMCore.ByteManager
|
||||
{
|
||||
/// <summary>
|
||||
/// 字节块集合
|
||||
/// </summary>
|
||||
[DebuggerDisplay("Count = {bytesQueue.Count}")]
|
||||
internal class BytesQueue
|
||||
{
|
||||
internal int size;
|
||||
|
||||
internal BytesQueue(int size)
|
||||
{
|
||||
this.size = size;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 占用空间
|
||||
/// </summary>
|
||||
public long FullSize
|
||||
{ get { return this.size * this.bytesQueue.Count; } }
|
||||
|
||||
private ConcurrentQueue<byte[]> bytesQueue = new ConcurrentQueue<byte[]>();
|
||||
|
||||
internal long referenced;
|
||||
|
||||
/// <summary>
|
||||
/// 获取当前实例中的空闲的Block
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public bool TryGet(out byte[] bytes)
|
||||
{
|
||||
referenced++;
|
||||
return this.bytesQueue.TryDequeue(out bytes);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 向当前集合添加Block
|
||||
/// </summary>
|
||||
/// <param name="bytes"></param>
|
||||
public void Add(byte[] bytes)
|
||||
{
|
||||
this.bytesQueue.Enqueue(bytes);
|
||||
}
|
||||
|
||||
internal void Clear()
|
||||
{
|
||||
this.bytesQueue.Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
24
RRQMCore/Collections/Concurrent/Common/IQueueData.cs
Normal file
24
RRQMCore/Collections/Concurrent/Common/IQueueData.cs
Normal file
@@ -0,0 +1,24 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权(除特别声明或在RRQMCore.XREF命名空间的代码)归作者本人若汝棋茗所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权
|
||||
// CSDN博客:https://blog.csdn.net/qq_40374647
|
||||
// 哔哩哔哩视频:https://space.bilibili.com/94253567
|
||||
// Gitee源代码仓库:https://gitee.com/RRQM_Home
|
||||
// Github源代码仓库:https://github.com/RRQM
|
||||
// 交流QQ群:234762506
|
||||
// 感谢您的下载和使用
|
||||
//------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------
|
||||
namespace RRQMCore.Collections.Concurrent
|
||||
{
|
||||
/// <summary>
|
||||
/// 队列数据
|
||||
/// </summary>
|
||||
public interface IQueueData
|
||||
{
|
||||
/// <summary>
|
||||
/// 数据长度
|
||||
/// </summary>
|
||||
int Size { get; }
|
||||
}
|
||||
}
|
||||
124
RRQMCore/Collections/Concurrent/ConcurrentDoublyDictionary.cs
Normal file
124
RRQMCore/Collections/Concurrent/ConcurrentDoublyDictionary.cs
Normal file
@@ -0,0 +1,124 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权(除特别声明或在RRQMCore.XREF命名空间的代码)归作者本人若汝棋茗所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权
|
||||
// CSDN博客:https://blog.csdn.net/qq_40374647
|
||||
// 哔哩哔哩视频:https://space.bilibili.com/94253567
|
||||
// Gitee源代码仓库:https://gitee.com/RRQM_Home
|
||||
// Github源代码仓库:https://github.com/RRQM
|
||||
// 交流QQ群:234762506
|
||||
// 感谢您的下载和使用
|
||||
//------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------
|
||||
using System.Collections.Concurrent;
|
||||
|
||||
namespace RRQMCore.Collections.Concurrent
|
||||
{
|
||||
/// <summary>
|
||||
/// 安全双向字典
|
||||
/// </summary>
|
||||
public class ConcurrentDoublyDictionary<TKey, TValue>
|
||||
{
|
||||
private ConcurrentDictionary<TKey, TValue> keyToValue;
|
||||
private ConcurrentDictionary<TValue, TKey> valueToKey;
|
||||
|
||||
/// <summary>
|
||||
/// 构造函数
|
||||
/// </summary>
|
||||
public ConcurrentDoublyDictionary()
|
||||
{
|
||||
this.keyToValue = new ConcurrentDictionary<TKey, TValue>();
|
||||
this.valueToKey = new ConcurrentDictionary<TValue, TKey>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 由键指向值得集合
|
||||
/// </summary>
|
||||
public ConcurrentDictionary<TKey, TValue> KeyToValue => this.keyToValue;
|
||||
|
||||
/// <summary>
|
||||
/// 由值指向键的集合
|
||||
/// </summary>
|
||||
public ConcurrentDictionary<TValue, TKey> ValueToKey => this.valueToKey;
|
||||
|
||||
/// <summary>
|
||||
/// 尝试将指定的键和值添加到字典中。
|
||||
/// </summary>
|
||||
/// <param name="key"></param>
|
||||
/// <param name="value"></param>
|
||||
/// <returns></returns>
|
||||
public bool TryAdd(TKey key, TValue value)
|
||||
{
|
||||
if (this.keyToValue.TryAdd(key, value))
|
||||
{
|
||||
if (this.valueToKey.TryAdd(value, key))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.keyToValue.TryRemove(key, out _);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 由键尝试移除
|
||||
/// </summary>
|
||||
/// <param name="key"></param>
|
||||
/// <param name="value"></param>
|
||||
/// <returns></returns>
|
||||
public bool TryRemoveFromKey(TKey key, out TValue value)
|
||||
{
|
||||
if (this.keyToValue.TryRemove(key, out value))
|
||||
{
|
||||
if (this.valueToKey.TryRemove(value, out _))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 由值尝试移除
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
/// <param name="key"></param>
|
||||
/// <returns></returns>
|
||||
public bool TryRemoveFromValue(TValue value, out TKey key)
|
||||
{
|
||||
if (this.valueToKey.TryRemove(value, out key))
|
||||
{
|
||||
if (this.keyToValue.TryRemove(key, out _))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 由键获取到值
|
||||
/// </summary>
|
||||
/// <param name="key"></param>
|
||||
/// <param name="value"></param>
|
||||
/// <returns></returns>
|
||||
public bool TryGetFromKey(TKey key, out TValue value)
|
||||
{
|
||||
return this.keyToValue.TryGetValue(key, out value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 由值获取到键
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
/// <param name="key"></param>
|
||||
/// <returns></returns>
|
||||
public bool TryGetFromValue(TValue value, out TKey key)
|
||||
{
|
||||
return this.valueToKey.TryGetValue(value, out key);
|
||||
}
|
||||
}
|
||||
}
|
||||
212
RRQMCore/Collections/Concurrent/ConcurrentList.cs
Normal file
212
RRQMCore/Collections/Concurrent/ConcurrentList.cs
Normal file
@@ -0,0 +1,212 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权(除特别声明或在RRQMCore.XREF命名空间的代码)归作者本人若汝棋茗所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权
|
||||
// CSDN博客:https://blog.csdn.net/qq_40374647
|
||||
// 哔哩哔哩视频:https://space.bilibili.com/94253567
|
||||
// Gitee源代码仓库:https://gitee.com/RRQM_Home
|
||||
// Github源代码仓库:https://github.com/RRQM
|
||||
// 交流QQ群:234762506
|
||||
// 感谢您的下载和使用
|
||||
//------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace RRQMCore.Collections.Concurrent
|
||||
{
|
||||
/// <summary>
|
||||
/// 线程安全的List
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
public class ConcurrentList<T> : IList<T>
|
||||
{
|
||||
/// <summary>
|
||||
/// 构造函数
|
||||
/// </summary>
|
||||
public ConcurrentList()
|
||||
{
|
||||
this.list = new List<T>();
|
||||
this.locker = new object();
|
||||
}
|
||||
|
||||
private List<T> list;
|
||||
private object locker;
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置指定索引处的元素。
|
||||
/// </summary>
|
||||
/// <param name="index"></param>
|
||||
/// <returns></returns>
|
||||
public T this[int index]
|
||||
{
|
||||
get
|
||||
{
|
||||
lock (locker)
|
||||
{
|
||||
return this.list[index];
|
||||
}
|
||||
}
|
||||
set
|
||||
{
|
||||
lock (locker)
|
||||
{
|
||||
this.list[index] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取集合中包含的元素数。
|
||||
/// </summary>
|
||||
public int Count
|
||||
{ get { lock (locker) { return this.list.Count; } } }
|
||||
|
||||
/// <summary>
|
||||
/// 是否只读
|
||||
/// </summary>
|
||||
public bool IsReadOnly
|
||||
{ get { return false; } }
|
||||
|
||||
/// <summary>
|
||||
/// 将某项添加到 System.Collections.Generic.ICollection`1 中。
|
||||
/// </summary>
|
||||
/// <param name="item"></param>
|
||||
public void Add(T item)
|
||||
{
|
||||
lock (this.locker)
|
||||
{
|
||||
this.list.Add(item);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 从 System.Collections.Generic.ICollection`1 中移除所有项。
|
||||
/// </summary>
|
||||
public void Clear()
|
||||
{
|
||||
lock (this.locker)
|
||||
{
|
||||
this.list.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 确定 System.Collections.Generic.ICollection`1 是否包含特定值。
|
||||
/// </summary>
|
||||
/// <param name="item"></param>
|
||||
/// <returns></returns>
|
||||
public bool Contains(T item)
|
||||
{
|
||||
lock (this.locker)
|
||||
{
|
||||
return this.Contains(item);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 从特定的 System.Collections.Generic.ICollection`1 索引处开始,将 System.Array 的元素复制到一个 System.Array
|
||||
/// </summary>
|
||||
/// <param name="array"></param>
|
||||
/// <param name="arrayIndex"></param>
|
||||
public void CopyTo(T[] array, int arrayIndex)
|
||||
{
|
||||
lock (this.locker)
|
||||
{
|
||||
this.list.CopyTo(array, arrayIndex);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 返回一个循环访问集合的枚举器。
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public IEnumerator<T> GetEnumerator()
|
||||
{
|
||||
lock (this.locker)
|
||||
{
|
||||
return this.list.GetEnumerator();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 确定 System.Collections.Generic.IList`1 中特定项的索引。
|
||||
/// </summary>
|
||||
/// <param name="item"></param>
|
||||
/// <returns></returns>
|
||||
public int IndexOf(T item)
|
||||
{
|
||||
lock (this.locker)
|
||||
{
|
||||
return this.IndexOf(item);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 在 System.Collections.Generic.IList`1 中的指定索引处插入一个项。
|
||||
/// </summary>
|
||||
/// <param name="index"></param>
|
||||
/// <param name="item"></param>
|
||||
public void Insert(int index, T item)
|
||||
{
|
||||
lock (this.locker)
|
||||
{
|
||||
this.list.Insert(index, item);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 从 System.Collections.Generic.ICollection`1 中移除特定对象的第一个匹配项。
|
||||
/// </summary>
|
||||
/// <param name="item"></param>
|
||||
/// <returns></returns>
|
||||
public bool Remove(T item)
|
||||
{
|
||||
lock (this.locker)
|
||||
{
|
||||
return this.list.Remove(item);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 从 System.Collections.Generic.List`1 中移除一定范围的元素。
|
||||
/// </summary>
|
||||
/// <param name="index"></param>
|
||||
/// <param name="count"></param>
|
||||
public void RemoveRange(int index, int count)
|
||||
{
|
||||
lock (this.locker)
|
||||
{
|
||||
this.list.RemoveRange(index, count);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 移除位于指定索引处的 System.Collections.Generic.IList`1 项。
|
||||
/// </summary>
|
||||
/// <param name="index"></param>
|
||||
public void RemoveAt(int index)
|
||||
{
|
||||
lock (this.locker)
|
||||
{
|
||||
this.list.RemoveAt(index);
|
||||
}
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
lock (this.locker)
|
||||
{
|
||||
return this.list.GetEnumerator();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 重写ToString
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public override string ToString()
|
||||
{
|
||||
return $"Count={this.Count}";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权(除特别声明或在RRQMCore.XREF命名空间的代码)归作者本人若汝棋茗所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权
|
||||
// CSDN博客:https://blog.csdn.net/qq_40374647
|
||||
// 哔哩哔哩视频:https://space.bilibili.com/94253567
|
||||
// Gitee源代码仓库:https://gitee.com/RRQM_Home
|
||||
// Github源代码仓库:https://github.com/RRQM
|
||||
// 交流QQ群:234762506
|
||||
// 感谢您的下载和使用
|
||||
//------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------
|
||||
using System.Collections.Concurrent;
|
||||
using System.Threading;
|
||||
|
||||
namespace RRQMCore.Collections.Concurrent
|
||||
{
|
||||
/// <summary>
|
||||
/// 智能安全队列
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
public class IntelligentConcurrentQueue<T> : ConcurrentQueue<T>
|
||||
{
|
||||
private int count;
|
||||
|
||||
private int maxCount;
|
||||
|
||||
/// <summary>
|
||||
/// 构造函数
|
||||
/// </summary>
|
||||
/// <param name="maxCount"></param>
|
||||
public IntelligentConcurrentQueue(int maxCount)
|
||||
{
|
||||
this.maxCount = maxCount;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 允许的最大长度
|
||||
/// </summary>
|
||||
public int MaxCount
|
||||
{
|
||||
get { return maxCount; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 长度
|
||||
/// </summary>
|
||||
public new int Count
|
||||
{
|
||||
get { return this.count; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 入队
|
||||
/// </summary>
|
||||
/// <param name="item"></param>
|
||||
public new void Enqueue(T item)
|
||||
{
|
||||
SpinWait.SpinUntil(this.Check);
|
||||
Interlocked.Increment(ref count);
|
||||
base.Enqueue(item);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 出队
|
||||
/// </summary>
|
||||
/// <param name="result"></param>
|
||||
/// <returns></returns>
|
||||
public new bool TryDequeue(out T result)
|
||||
{
|
||||
if (base.TryDequeue(out result))
|
||||
{
|
||||
Interlocked.Decrement(ref count);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private bool Check()
|
||||
{
|
||||
return this.count < this.maxCount;
|
||||
}
|
||||
}
|
||||
}
|
||||
91
RRQMCore/Collections/Concurrent/IntelligentDataQueue.cs
Normal file
91
RRQMCore/Collections/Concurrent/IntelligentDataQueue.cs
Normal file
@@ -0,0 +1,91 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权(除特别声明或在RRQMCore.XREF命名空间的代码)归作者本人若汝棋茗所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权
|
||||
// CSDN博客:https://blog.csdn.net/qq_40374647
|
||||
// 哔哩哔哩视频:https://space.bilibili.com/94253567
|
||||
// Gitee源代码仓库:https://gitee.com/RRQM_Home
|
||||
// Github源代码仓库:https://github.com/RRQM
|
||||
// 交流QQ群:234762506
|
||||
// 感谢您的下载和使用
|
||||
//------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------
|
||||
using System.Collections.Concurrent;
|
||||
using System.Threading;
|
||||
|
||||
namespace RRQMCore.Collections.Concurrent
|
||||
{
|
||||
/// <summary>
|
||||
/// 智能数据安全队列
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
public class IntelligentDataQueue<T> : ConcurrentQueue<T> where T : IQueueData
|
||||
{
|
||||
private long actualSize;
|
||||
|
||||
private long maxSize;
|
||||
|
||||
/// <summary>
|
||||
/// 构造函数
|
||||
/// </summary>
|
||||
/// <param name="maxSize"></param>
|
||||
public IntelligentDataQueue(long maxSize)
|
||||
{
|
||||
this.maxSize = maxSize;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 允许的最大长度
|
||||
/// </summary>
|
||||
public long MaxSize
|
||||
{
|
||||
get { return maxSize; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 实际尺寸
|
||||
/// </summary>
|
||||
public long ActualSize
|
||||
{
|
||||
get { return this.actualSize; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 入队
|
||||
/// </summary>
|
||||
/// <param name="item"></param>
|
||||
public new void Enqueue(T item)
|
||||
{
|
||||
SpinWait.SpinUntil(this.Check);
|
||||
this.Calculate(item.Size);
|
||||
base.Enqueue(item);
|
||||
}
|
||||
|
||||
private void Calculate(long value)
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
this.actualSize += value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 出队
|
||||
/// </summary>
|
||||
/// <param name="result"></param>
|
||||
/// <returns></returns>
|
||||
public new bool TryDequeue(out T result)
|
||||
{
|
||||
if (base.TryDequeue(out result))
|
||||
{
|
||||
this.Calculate(-result.Size);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private bool Check()
|
||||
{
|
||||
return this.actualSize < this.maxSize;
|
||||
}
|
||||
}
|
||||
}
|
||||
35
RRQMCore/Common/Enum/EndianType.cs
Normal file
35
RRQMCore/Common/Enum/EndianType.cs
Normal file
@@ -0,0 +1,35 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权(除特别声明或在RRQMCore.XREF命名空间的代码)归作者本人若汝棋茗所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权
|
||||
// CSDN博客:https://blog.csdn.net/qq_40374647
|
||||
// 哔哩哔哩视频:https://space.bilibili.com/94253567
|
||||
// Gitee源代码仓库:https://gitee.com/RRQM_Home
|
||||
// Github源代码仓库:https://github.com/RRQM
|
||||
// 交流QQ群:234762506
|
||||
// 感谢您的下载和使用
|
||||
//------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace RRQMCore
|
||||
{
|
||||
/// <summary>
|
||||
/// 大小端类型
|
||||
/// </summary>
|
||||
public enum EndianType
|
||||
{
|
||||
/// <summary>
|
||||
/// 小端模式
|
||||
/// </summary>
|
||||
Little,
|
||||
|
||||
/// <summary>
|
||||
/// 大端模式
|
||||
/// </summary>
|
||||
Big
|
||||
}
|
||||
}
|
||||
29
RRQMCore/Common/IResult.cs
Normal file
29
RRQMCore/Common/IResult.cs
Normal file
@@ -0,0 +1,29 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权(除特别声明或在RRQMCore.XREF命名空间的代码)归作者本人若汝棋茗所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权
|
||||
// CSDN博客:https://blog.csdn.net/qq_40374647
|
||||
// 哔哩哔哩视频:https://space.bilibili.com/94253567
|
||||
// Gitee源代码仓库:https://gitee.com/RRQM_Home
|
||||
// Github源代码仓库:https://github.com/RRQM
|
||||
// 交流QQ群:234762506
|
||||
// 感谢您的下载和使用
|
||||
//------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------
|
||||
namespace RRQMCore
|
||||
{
|
||||
/// <summary>
|
||||
/// 返回通知接口
|
||||
/// </summary>
|
||||
public interface IResult
|
||||
{
|
||||
/// <summary>
|
||||
/// 是否成功
|
||||
/// </summary>
|
||||
ResultCode ResultCode { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 消息
|
||||
/// </summary>
|
||||
string Message { get; }
|
||||
}
|
||||
}
|
||||
38
RRQMCore/Common/Metadata.cs
Normal file
38
RRQMCore/Common/Metadata.cs
Normal file
@@ -0,0 +1,38 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权(除特别声明或在RRQMCore.XREF命名空间的代码)归作者本人若汝棋茗所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权
|
||||
// CSDN博客:https://blog.csdn.net/qq_40374647
|
||||
// 哔哩哔哩视频:https://space.bilibili.com/94253567
|
||||
// Gitee源代码仓库:https://gitee.com/RRQM_Home
|
||||
// Github源代码仓库:https://github.com/RRQM
|
||||
// 交流QQ群:234762506
|
||||
// 感谢您的下载和使用
|
||||
//------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace RRQMCore
|
||||
{
|
||||
/// <summary>
|
||||
/// 可传输的元数据
|
||||
/// </summary>
|
||||
public class Metadata : Dictionary<string, string>
|
||||
{
|
||||
/// <summary>
|
||||
/// 添加或更新
|
||||
/// </summary>
|
||||
/// <param name="key"></param>
|
||||
/// <param name="value"></param>
|
||||
public void AddOrUpdate(string key, string value)
|
||||
{
|
||||
if (this.ContainsKey(key))
|
||||
{
|
||||
this[key] = value;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.Add(key, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
439
RRQMCore/Common/RRQMBitConverter.cs
Normal file
439
RRQMCore/Common/RRQMBitConverter.cs
Normal file
@@ -0,0 +1,439 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权(除特别声明或在RRQMCore.XREF命名空间的代码)归作者本人若汝棋茗所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权
|
||||
// CSDN博客:https://blog.csdn.net/qq_40374647
|
||||
// 哔哩哔哩视频:https://space.bilibili.com/94253567
|
||||
// Gitee源代码仓库:https://gitee.com/RRQM_Home
|
||||
// Github源代码仓库:https://github.com/RRQM
|
||||
// 交流QQ群:234762506
|
||||
// 感谢您的下载和使用
|
||||
//------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace RRQMCore
|
||||
{
|
||||
/// <summary>
|
||||
/// 将基数据类型转换为指定端的一个字节数组,
|
||||
/// 或将一个字节数组转换为指定端基数据类型。
|
||||
/// </summary>
|
||||
public class RRQMBitConverter
|
||||
{
|
||||
/// <summary>
|
||||
/// 以大端
|
||||
/// </summary>
|
||||
public static RRQMBitConverter BigEndian;
|
||||
|
||||
/// <summary>
|
||||
/// 以小端
|
||||
/// </summary>
|
||||
public static RRQMBitConverter LittleEndian;
|
||||
|
||||
static RRQMBitConverter()
|
||||
{
|
||||
BigEndian = new RRQMBitConverter(EndianType.Big);
|
||||
LittleEndian = new RRQMBitConverter(EndianType.Little);
|
||||
DefaultEndianType = EndianType.Little;
|
||||
}
|
||||
|
||||
private static RRQMBitConverter @default;
|
||||
/// <summary>
|
||||
/// 以默认小端,可通过<see cref="RRQMBitConverter.DefaultEndianType"/>重新指定默认端。
|
||||
/// </summary>
|
||||
public static RRQMBitConverter Default
|
||||
{
|
||||
get { return @default; }
|
||||
}
|
||||
|
||||
private static EndianType @defaultEndianType;
|
||||
/// <summary>
|
||||
/// 默认大小端切换。
|
||||
/// </summary>
|
||||
public static EndianType DefaultEndianType
|
||||
{
|
||||
get { return @defaultEndianType; }
|
||||
set
|
||||
{
|
||||
@defaultEndianType = value;
|
||||
switch (value)
|
||||
{
|
||||
case EndianType.Little:
|
||||
@default = LittleEndian;
|
||||
break;
|
||||
case EndianType.Big:
|
||||
@default = BigEndian;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private EndianType endianType;
|
||||
/// <summary>
|
||||
/// 构造函数
|
||||
/// </summary>
|
||||
/// <param name="endianType"></param>
|
||||
public RRQMBitConverter(EndianType endianType)
|
||||
{
|
||||
this.endianType = endianType;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 指定大小端。
|
||||
/// </summary>
|
||||
public EndianType EndianType
|
||||
{
|
||||
get { return endianType; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 判断当前系统是否为设置的大小端
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public bool IsSameOfSet()
|
||||
{
|
||||
return !(BitConverter.IsLittleEndian ^ (endianType == EndianType.Little));
|
||||
}
|
||||
|
||||
#region ushort
|
||||
/// <summary>
|
||||
/// 转换为指定端2字节
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
/// <returns></returns>
|
||||
public byte[] GetBytes(ushort value)
|
||||
{
|
||||
byte[] bytes = BitConverter.GetBytes(value);
|
||||
if (!IsSameOfSet())
|
||||
{
|
||||
Array.Reverse(bytes);
|
||||
}
|
||||
return bytes;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 转换为指定端模式的2字节转换为UInt16数据。
|
||||
/// </summary>
|
||||
/// <param name="buffer"></param>
|
||||
/// <param name="offset"></param>
|
||||
/// <returns></returns>
|
||||
public ushort ToUInt16(byte[] buffer, int offset)
|
||||
{
|
||||
byte[] bytes = new byte[2];
|
||||
Array.Copy(buffer, offset, bytes, 0, 2);
|
||||
if (!IsSameOfSet())
|
||||
{
|
||||
Array.Reverse(bytes);
|
||||
}
|
||||
return BitConverter.ToUInt16(bytes, 0);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region ulong
|
||||
/// <summary>
|
||||
/// 转换为指定端8字节
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
/// <returns></returns>
|
||||
public byte[] GetBytes(ulong value)
|
||||
{
|
||||
byte[] bytes = BitConverter.GetBytes(value);
|
||||
if (!IsSameOfSet())
|
||||
{
|
||||
Array.Reverse(bytes);
|
||||
}
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 转换为指定端模式的Ulong数据。
|
||||
/// </summary>
|
||||
/// <param name="buffer"></param>
|
||||
/// <param name="offset"></param>
|
||||
/// <returns></returns>
|
||||
public ulong ToUInt64(byte[] buffer, int offset)
|
||||
{
|
||||
byte[] bytes = new byte[8];
|
||||
Array.Copy(buffer, offset, bytes, 0, 8);
|
||||
if (!IsSameOfSet())
|
||||
{
|
||||
Array.Reverse(bytes);
|
||||
}
|
||||
return BitConverter.ToUInt64(bytes, 0);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region bool
|
||||
/// <summary>
|
||||
/// 转换为指定端1字节
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
/// <returns></returns>
|
||||
public byte[] GetBytes(bool value)
|
||||
{
|
||||
return BitConverter.GetBytes(value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 转换为指定端模式的bool数据。
|
||||
/// </summary>
|
||||
/// <param name="buffer"></param>
|
||||
/// <param name="offset"></param>
|
||||
/// <returns></returns>
|
||||
public bool ToBoolean(byte[] buffer, int offset)
|
||||
{
|
||||
return BitConverter.ToBoolean(buffer, offset);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region char
|
||||
/// <summary>
|
||||
/// 转换为指定端2字节
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
/// <returns></returns>
|
||||
public byte[] GetBytes(char value)
|
||||
{
|
||||
byte[] bytes = BitConverter.GetBytes(value);
|
||||
if (!IsSameOfSet())
|
||||
{
|
||||
Array.Reverse(bytes);
|
||||
}
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 转换为指定端模式的Char数据。
|
||||
/// </summary>
|
||||
/// <param name="buffer"></param>
|
||||
/// <param name="offset"></param>
|
||||
/// <returns></returns>
|
||||
public char ToChar(byte[] buffer, int offset)
|
||||
{
|
||||
byte[] bytes = new byte[2];
|
||||
Array.Copy(buffer, offset, bytes, 0, bytes.Length);
|
||||
if (!IsSameOfSet())
|
||||
{
|
||||
Array.Reverse(bytes);
|
||||
}
|
||||
return BitConverter.ToChar(bytes, 0);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region short
|
||||
/// <summary>
|
||||
/// 转换为指定端2字节
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
/// <returns></returns>
|
||||
public byte[] GetBytes(short value)
|
||||
{
|
||||
byte[] bytes = BitConverter.GetBytes(value);
|
||||
if (!IsSameOfSet())
|
||||
{
|
||||
Array.Reverse(bytes);
|
||||
}
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 转换为指定端模式的Short数据。
|
||||
/// </summary>
|
||||
/// <param name="buffer"></param>
|
||||
/// <param name="offset"></param>
|
||||
/// <returns></returns>
|
||||
public short ToInt16(byte[] buffer, int offset)
|
||||
{
|
||||
byte[] bytes = new byte[2];
|
||||
Array.Copy(buffer, offset, bytes, 0, bytes.Length);
|
||||
if (!IsSameOfSet())
|
||||
{
|
||||
Array.Reverse(bytes);
|
||||
}
|
||||
return BitConverter.ToInt16(bytes, 0);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region int
|
||||
/// <summary>
|
||||
/// 转换为指定端4字节
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
/// <returns></returns>
|
||||
public byte[] GetBytes(int value)
|
||||
{
|
||||
byte[] bytes = BitConverter.GetBytes(value);
|
||||
if (!IsSameOfSet())
|
||||
{
|
||||
Array.Reverse(bytes);
|
||||
}
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 转换为指定端模式的int数据。
|
||||
/// </summary>
|
||||
/// <param name="buffer"></param>
|
||||
/// <param name="offset"></param>
|
||||
/// <returns></returns>
|
||||
public int ToInt32(byte[] buffer, int offset)
|
||||
{
|
||||
byte[] bytes = new byte[4];
|
||||
Array.Copy(buffer, offset, bytes, 0, bytes.Length);
|
||||
if (!IsSameOfSet())
|
||||
{
|
||||
Array.Reverse(bytes);
|
||||
}
|
||||
return BitConverter.ToInt32(bytes, 0);
|
||||
}
|
||||
#endregion
|
||||
#region long
|
||||
/// <summary>
|
||||
/// 转换为指定端8字节
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
/// <returns></returns>
|
||||
public byte[] GetBytes(long value)
|
||||
{
|
||||
byte[] bytes = BitConverter.GetBytes(value);
|
||||
if (!IsSameOfSet())
|
||||
{
|
||||
Array.Reverse(bytes);
|
||||
}
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 转换为指定端模式的long数据。
|
||||
/// </summary>
|
||||
/// <param name="buffer"></param>
|
||||
/// <param name="offset"></param>
|
||||
/// <returns></returns>
|
||||
public long ToInt64(byte[] buffer, int offset)
|
||||
{
|
||||
byte[] bytes = new byte[8];
|
||||
Array.Copy(buffer, offset, bytes, 0, bytes.Length);
|
||||
if (!IsSameOfSet())
|
||||
{
|
||||
Array.Reverse(bytes);
|
||||
}
|
||||
return BitConverter.ToInt64(bytes, 0);
|
||||
}
|
||||
#endregion
|
||||
#region uint
|
||||
/// <summary>
|
||||
/// 转换为指定端4字节
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
/// <returns></returns>
|
||||
public byte[] GetBytes(uint value)
|
||||
{
|
||||
byte[] bytes = BitConverter.GetBytes(value);
|
||||
if (!IsSameOfSet())
|
||||
{
|
||||
Array.Reverse(bytes);
|
||||
}
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 转换为指定端模式的Uint数据。
|
||||
/// </summary>
|
||||
/// <param name="buffer"></param>
|
||||
/// <param name="offset"></param>
|
||||
/// <returns></returns>
|
||||
public uint ToUInt32(byte[] buffer, int offset)
|
||||
{
|
||||
byte[] bytes = new byte[4];
|
||||
Array.Copy(buffer, offset, bytes, 0, bytes.Length);
|
||||
if (!IsSameOfSet())
|
||||
{
|
||||
Array.Reverse(bytes);
|
||||
}
|
||||
return BitConverter.ToUInt32(bytes, 0);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region float
|
||||
/// <summary>
|
||||
/// 转换为指定端4字节
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
/// <returns></returns>
|
||||
public byte[] GetBytes(float value)
|
||||
{
|
||||
byte[] bytes = BitConverter.GetBytes(value);
|
||||
if (!IsSameOfSet())
|
||||
{
|
||||
Array.Reverse(bytes);
|
||||
}
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 转换为指定端模式的float数据。
|
||||
/// </summary>
|
||||
/// <param name="buffer"></param>
|
||||
/// <param name="offset"></param>
|
||||
/// <returns></returns>
|
||||
public float ToSingle(byte[] buffer, int offset)
|
||||
{
|
||||
byte[] bytes = new byte[4];
|
||||
Array.Copy(buffer, offset, bytes, 0, bytes.Length);
|
||||
if (!IsSameOfSet())
|
||||
{
|
||||
Array.Reverse(bytes);
|
||||
}
|
||||
return BitConverter.ToSingle(bytes, 0);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region long
|
||||
/// <summary>
|
||||
/// 转换为指定端8字节
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
/// <returns></returns>
|
||||
public byte[] GetBytes(double value)
|
||||
{
|
||||
byte[] bytes = BitConverter.GetBytes(value);
|
||||
if (!IsSameOfSet())
|
||||
{
|
||||
Array.Reverse(bytes);
|
||||
}
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 转换为指定端模式的double数据。
|
||||
/// </summary>
|
||||
/// <param name="buffer"></param>
|
||||
/// <param name="offset"></param>
|
||||
/// <returns></returns>
|
||||
public double ToDouble(byte[] buffer, int offset)
|
||||
{
|
||||
byte[] bytes = new byte[8];
|
||||
Array.Copy(buffer, offset, bytes, 0, bytes.Length);
|
||||
if (!IsSameOfSet())
|
||||
{
|
||||
Array.Reverse(bytes);
|
||||
}
|
||||
return BitConverter.ToDouble(bytes, 0);
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
45
RRQMCore/Common/RRQMCoreTools.cs
Normal file
45
RRQMCore/Common/RRQMCoreTools.cs
Normal file
@@ -0,0 +1,45 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权(除特别声明或在RRQMCore.XREF命名空间的代码)归作者本人若汝棋茗所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权
|
||||
// CSDN博客:https://blog.csdn.net/qq_40374647
|
||||
// 哔哩哔哩视频:https://space.bilibili.com/94253567
|
||||
// Gitee源代码仓库:https://gitee.com/RRQM_Home
|
||||
// Github源代码仓库:https://github.com/RRQM
|
||||
// 交流QQ群:234762506
|
||||
// 感谢您的下载和使用
|
||||
//------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace RRQMCore.Common
|
||||
{
|
||||
/// <summary>
|
||||
/// RRQMCoreTools
|
||||
/// </summary>
|
||||
public static class RRQMCoreTools
|
||||
{
|
||||
/// <summary>
|
||||
/// 判断字符串compare 在 input字符串中出现的次数
|
||||
/// </summary>
|
||||
/// <param name="input">源字符串</param>
|
||||
/// <param name="compare">用于比较的字符串</param>
|
||||
/// <returns>字符串compare 在 input字符串中出现的次数</returns>
|
||||
public static int GetStringCount(string input, string compare)
|
||||
{
|
||||
int index = input.IndexOf(compare);
|
||||
if (index != -1)
|
||||
{
|
||||
return 1 + GetStringCount(input.Substring(index + compare.Length), compare);
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
21
RRQMCore/Common/RRQMObject.cs
Normal file
21
RRQMCore/Common/RRQMObject.cs
Normal file
@@ -0,0 +1,21 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权(除特别声明或在RRQMCore.XREF命名空间的代码)归作者本人若汝棋茗所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权
|
||||
// CSDN博客:https://blog.csdn.net/qq_40374647
|
||||
// 哔哩哔哩视频:https://space.bilibili.com/94253567
|
||||
// Gitee源代码仓库:https://gitee.com/RRQM_Home
|
||||
// Github源代码仓库:https://github.com/RRQM
|
||||
// 交流QQ群:234762506
|
||||
// 感谢您的下载和使用
|
||||
//------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace RRQMCore
|
||||
{
|
||||
/// <summary>
|
||||
/// RRQM系对象基类
|
||||
/// </summary>
|
||||
public class RRQMObject
|
||||
{
|
||||
}
|
||||
}
|
||||
44
RRQMCore/Common/RRQMReadonly.cs
Normal file
44
RRQMCore/Common/RRQMReadonly.cs
Normal file
@@ -0,0 +1,44 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权(除特别声明或在RRQMCore.XREF命名空间的代码)归作者本人若汝棋茗所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权
|
||||
// CSDN博客:https://blog.csdn.net/qq_40374647
|
||||
// 哔哩哔哩视频:https://space.bilibili.com/94253567
|
||||
// Gitee源代码仓库:https://gitee.com/RRQM_Home
|
||||
// Github源代码仓库:https://github.com/RRQM
|
||||
// 交流QQ群:234762506
|
||||
// 感谢您的下载和使用
|
||||
//------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------
|
||||
using System;
|
||||
using System.Collections;
|
||||
|
||||
namespace RRQMCore
|
||||
{
|
||||
/// <summary>
|
||||
/// 常量
|
||||
/// </summary>
|
||||
public class RRQMReadonly
|
||||
{
|
||||
#pragma warning disable CS1591 // 缺少对公共可见类型或成员的 XML 注释
|
||||
public static readonly Type stringType = typeof(string);
|
||||
public static readonly Type byteType = typeof(byte);
|
||||
public static readonly Type sbyteType = typeof(sbyte);
|
||||
public static readonly Type shortType = typeof(short);
|
||||
public static readonly Type ushortType = typeof(ushort);
|
||||
public static readonly Type intType = typeof(int);
|
||||
public static readonly Type uintType = typeof(uint);
|
||||
public static readonly Type boolType = typeof(bool);
|
||||
public static readonly Type charType = typeof(char);
|
||||
public static readonly Type longType = typeof(long);
|
||||
public static readonly Type ulongType = typeof(ulong);
|
||||
public static readonly Type floatType = typeof(float);
|
||||
public static readonly Type doubleType = typeof(double);
|
||||
public static readonly Type decimalType = typeof(decimal);
|
||||
public static readonly Type dateTimeType = typeof(DateTime);
|
||||
public static readonly Type bytesType = typeof(byte[]);
|
||||
public static readonly Type dicType = typeof(IDictionary);
|
||||
public static readonly Type iEnumerableType = typeof(IEnumerable);
|
||||
public static readonly Type listType = typeof(IList);
|
||||
#pragma warning restore CS1591 // 缺少对公共可见类型或成员的 XML 注释
|
||||
}
|
||||
}
|
||||
105
RRQMCore/Common/ResType.cs
Normal file
105
RRQMCore/Common/ResType.cs
Normal file
@@ -0,0 +1,105 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权(除特别声明或在RRQMCore.XREF命名空间的代码)归作者本人若汝棋茗所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权
|
||||
// CSDN博客:https://blog.csdn.net/qq_40374647
|
||||
// 哔哩哔哩视频:https://space.bilibili.com/94253567
|
||||
// Gitee源代码仓库:https://gitee.com/RRQM_Home
|
||||
// Github源代码仓库:https://github.com/RRQM
|
||||
// 交流QQ群:234762506
|
||||
// 感谢您的下载和使用
|
||||
//------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace RRQMCore
|
||||
{
|
||||
/// <summary>
|
||||
/// RRQMCore资源枚举
|
||||
/// </summary>
|
||||
public enum ResType
|
||||
{
|
||||
/// <summary>
|
||||
/// 未知错误
|
||||
/// </summary>
|
||||
UnknownError,
|
||||
|
||||
/// <summary>
|
||||
/// 已知错误
|
||||
/// </summary>
|
||||
KnownError,
|
||||
|
||||
/// <summary>
|
||||
/// 参数为空
|
||||
/// </summary>
|
||||
ArgumentNull,
|
||||
|
||||
/// <summary>
|
||||
/// 远程终端拒绝该操作
|
||||
/// </summary>
|
||||
RemoteRefuse,
|
||||
|
||||
/// <summary>
|
||||
/// 远程终端不响应该操作
|
||||
/// </summary>
|
||||
RemoteNotSupported,
|
||||
|
||||
/// <summary>
|
||||
/// 远程终端异常
|
||||
/// </summary>
|
||||
RemoteException,
|
||||
|
||||
/// <summary>
|
||||
/// 通道设置失败
|
||||
/// </summary>
|
||||
SetChannelFail,
|
||||
|
||||
/// <summary>
|
||||
/// 路径无效
|
||||
/// </summary>
|
||||
PathInvalid,
|
||||
|
||||
/// <summary>
|
||||
/// 文件已存在
|
||||
/// </summary>
|
||||
FileExists,
|
||||
|
||||
/// <summary>
|
||||
/// 远程文件不存在
|
||||
/// </summary>
|
||||
RemoteFileNotExists,
|
||||
|
||||
/// <summary>
|
||||
/// 创建写入流失败
|
||||
/// </summary>
|
||||
CreateWriteStreamFail,
|
||||
|
||||
/// <summary>
|
||||
/// 没有找到流文件
|
||||
/// </summary>
|
||||
NotFindStream,
|
||||
|
||||
/// <summary>
|
||||
/// 流文件正在被应用
|
||||
/// </summary>
|
||||
StreamReferencing,
|
||||
|
||||
/// <summary>
|
||||
/// 接收流容器为空
|
||||
/// </summary>
|
||||
StreamBucketNull,
|
||||
|
||||
/// <summary>
|
||||
/// 加载流异常。
|
||||
/// </summary>
|
||||
LoadStreamFail,
|
||||
|
||||
/// <summary>
|
||||
/// 事件操作器异常
|
||||
/// </summary>
|
||||
GetEventArgsFail,
|
||||
|
||||
/// <summary>
|
||||
/// 长时间没有响应。
|
||||
/// </summary>
|
||||
NoResponse,
|
||||
}
|
||||
}
|
||||
60
RRQMCore/Common/Result.cs
Normal file
60
RRQMCore/Common/Result.cs
Normal file
@@ -0,0 +1,60 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权(除特别声明或在RRQMCore.XREF命名空间的代码)归作者本人若汝棋茗所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权
|
||||
// CSDN博客:https://blog.csdn.net/qq_40374647
|
||||
// 哔哩哔哩视频:https://space.bilibili.com/94253567
|
||||
// Gitee源代码仓库:https://gitee.com/RRQM_Home
|
||||
// Github源代码仓库:https://github.com/RRQM
|
||||
// 交流QQ群:234762506
|
||||
// 感谢您的下载和使用
|
||||
//------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace RRQMCore
|
||||
{
|
||||
/// <summary>
|
||||
/// 结果返回
|
||||
/// </summary>
|
||||
public struct Result : IResult
|
||||
{
|
||||
/// <summary>
|
||||
/// 构造函数
|
||||
/// </summary>
|
||||
/// <param name="resultCode"></param>
|
||||
/// <param name="message"></param>
|
||||
public Result(ResultCode resultCode, string message)
|
||||
{
|
||||
this.ResultCode = resultCode;
|
||||
this.Message = message;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 构造函数
|
||||
/// </summary>
|
||||
/// <param name="resultCode"></param>
|
||||
public Result(ResultCode resultCode)
|
||||
{
|
||||
this.ResultCode = resultCode;
|
||||
this.Message = resultCode.GetResString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <inheritdoc/>
|
||||
/// </summary>
|
||||
public ResultCode ResultCode { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// <inheritdoc/>
|
||||
/// </summary>
|
||||
public string Message { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// ToString
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public override string ToString()
|
||||
{
|
||||
return $"类型:{ResultCode},信息:{Message}";
|
||||
}
|
||||
}
|
||||
}
|
||||
45
RRQMCore/Common/ResultCode.cs
Normal file
45
RRQMCore/Common/ResultCode.cs
Normal file
@@ -0,0 +1,45 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权(除特别声明或在RRQMCore.XREF命名空间的代码)归作者本人若汝棋茗所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权
|
||||
// CSDN博客:https://blog.csdn.net/qq_40374647
|
||||
// 哔哩哔哩视频:https://space.bilibili.com/94253567
|
||||
// Gitee源代码仓库:https://gitee.com/RRQM_Home
|
||||
// Github源代码仓库:https://github.com/RRQM
|
||||
// 交流QQ群:234762506
|
||||
// 感谢您的下载和使用
|
||||
//------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace RRQMCore
|
||||
{
|
||||
/// <summary>
|
||||
/// 结果类型
|
||||
/// </summary>
|
||||
public enum ResultCode
|
||||
{
|
||||
/// <summary>
|
||||
/// 未执行的
|
||||
/// </summary>
|
||||
Default,
|
||||
|
||||
/// <summary>
|
||||
/// 错误
|
||||
/// </summary>
|
||||
Error,
|
||||
|
||||
/// <summary>
|
||||
/// 成功
|
||||
/// </summary>
|
||||
Success,
|
||||
|
||||
/// <summary>
|
||||
/// 操作超时
|
||||
/// </summary>
|
||||
Overtime,
|
||||
|
||||
/// <summary>
|
||||
/// 操作取消
|
||||
/// </summary>
|
||||
Canceled
|
||||
}
|
||||
}
|
||||
112
RRQMCore/Common/SnowflakeIDGenerator.cs
Normal file
112
RRQMCore/Common/SnowflakeIDGenerator.cs
Normal file
@@ -0,0 +1,112 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权(除特别声明或在RRQMCore.XREF命名空间的代码)归作者本人若汝棋茗所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权
|
||||
// CSDN博客:https://blog.csdn.net/qq_40374647
|
||||
// 哔哩哔哩视频:https://space.bilibili.com/94253567
|
||||
// Gitee源代码仓库:https://gitee.com/RRQM_Home
|
||||
// Github源代码仓库:https://github.com/RRQM
|
||||
// 交流QQ群:234762506
|
||||
// 感谢您的下载和使用
|
||||
//------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------
|
||||
using System;
|
||||
|
||||
namespace RRQMCore
|
||||
{
|
||||
/// <summary>
|
||||
/// 雪花ID生成器(该代码来自网络)
|
||||
/// </summary>
|
||||
public class SnowflakeIDGenerator
|
||||
{
|
||||
//机器ID
|
||||
private static long workerId;
|
||||
|
||||
private static long twepoch = 687888001020L; //唯一时间,这是一个避免重复的随机量,自行设定不要大于当前时间戳
|
||||
private static long sequence = 0L;
|
||||
private static int workerIdBits = 4; //机器码字节数。4个字节用来保存机器码(定义为Long类型会出现,最大偏移64位,所以左移64位没有意义)
|
||||
|
||||
/// <summary>
|
||||
/// 最大机器ID
|
||||
/// </summary>
|
||||
public static long maxWorkerId = -1L ^ (-1L << workerIdBits); //最大机器ID
|
||||
|
||||
private static int sequenceBits = 10; //计数器字节数,10个字节用来保存计数码
|
||||
private static int workerIdShift = sequenceBits; //机器码数据左移位数,就是后面计数器占用的位数
|
||||
private static int timestampLeftShift = sequenceBits + workerIdBits; //时间戳左移动位数就是机器码和计数器总字节数
|
||||
|
||||
/// <summary>
|
||||
/// 一微秒内可以产生计数,如果达到该值则等到下一微妙在进行生成
|
||||
/// </summary>
|
||||
public static long sequenceMask = -1L ^ -1L << sequenceBits; //一微秒内可以产生计数,如果达到该值则等到下一微妙在进行生成
|
||||
|
||||
private long lastTimestamp = -1L;
|
||||
|
||||
/// <summary>
|
||||
/// 机器码
|
||||
/// </summary>
|
||||
/// <param name="workerId"></param>
|
||||
public SnowflakeIDGenerator(long workerId)
|
||||
{
|
||||
if (workerId > maxWorkerId || workerId < 0)
|
||||
throw new Exception(string.Format("worker Id can't be greater than {0} or less than 0 ", workerId));
|
||||
SnowflakeIDGenerator.workerId = workerId;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取ID
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public long NextID()
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
long timestamp = timeGen();
|
||||
if (this.lastTimestamp == timestamp)
|
||||
{ //同一微妙中生成ID
|
||||
SnowflakeIDGenerator.sequence = (SnowflakeIDGenerator.sequence + 1) & SnowflakeIDGenerator.sequenceMask; //用&运算计算该微秒内产生的计数是否已经到达上限
|
||||
if (SnowflakeIDGenerator.sequence == 0)
|
||||
{
|
||||
//一微妙内产生的ID计数已达上限,等待下一微妙
|
||||
timestamp = tillNextMillis(this.lastTimestamp);
|
||||
}
|
||||
}
|
||||
else
|
||||
{ //不同微秒生成ID
|
||||
SnowflakeIDGenerator.sequence = 0; //计数清0
|
||||
}
|
||||
if (timestamp < lastTimestamp)
|
||||
{ //如果当前时间戳比上一次生成ID时时间戳还小,抛出异常,因为不能保证现在生成的ID之前没有生成过
|
||||
throw new Exception(string.Format("Clock moved backwards. Refusing to generate id for {0} milliseconds",
|
||||
this.lastTimestamp - timestamp));
|
||||
}
|
||||
this.lastTimestamp = timestamp; //把当前时间戳保存为最后生成ID的时间戳
|
||||
long nextId = (timestamp - twepoch << timestampLeftShift) | SnowflakeIDGenerator.workerId << SnowflakeIDGenerator.workerIdShift | SnowflakeIDGenerator.sequence;
|
||||
return nextId;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取下一微秒时间戳
|
||||
/// </summary>
|
||||
/// <param name="lastTimestamp"></param>
|
||||
/// <returns></returns>
|
||||
private long tillNextMillis(long lastTimestamp)
|
||||
{
|
||||
long timestamp = timeGen();
|
||||
while (timestamp <= lastTimestamp)
|
||||
{
|
||||
timestamp = timeGen();
|
||||
}
|
||||
return timestamp;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 生成当前时间戳
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private long timeGen()
|
||||
{
|
||||
return (long)(DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalMilliseconds;
|
||||
}
|
||||
}
|
||||
}
|
||||
43
RRQMCore/Common/StringResStore.cs
Normal file
43
RRQMCore/Common/StringResStore.cs
Normal file
@@ -0,0 +1,43 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权(除特别声明或在RRQMCore.XREF命名空间的代码)归作者本人若汝棋茗所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权
|
||||
// CSDN博客:https://blog.csdn.net/qq_40374647
|
||||
// 哔哩哔哩视频:https://space.bilibili.com/94253567
|
||||
// Gitee源代码仓库:https://gitee.com/RRQM_Home
|
||||
// Github源代码仓库:https://github.com/RRQM
|
||||
// 交流QQ群:234762506
|
||||
// 感谢您的下载和使用
|
||||
//------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------
|
||||
using RRQMCore.Helper;
|
||||
using System;
|
||||
|
||||
namespace RRQMCore
|
||||
{
|
||||
/// <summary>
|
||||
/// 字符串资源字典
|
||||
/// </summary>
|
||||
public static class StringResStore
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取资源字符
|
||||
/// </summary>
|
||||
/// <param name="enum"></param>
|
||||
/// <returns></returns>
|
||||
public static string GetResString(this Enum @enum)
|
||||
{
|
||||
return Resource.ResourceManager.GetString(@enum.ToString());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取资源字符
|
||||
/// </summary>
|
||||
/// <param name="enum"></param>
|
||||
/// <param name="objs"></param>
|
||||
/// <returns></returns>
|
||||
public static string GetResString(this Enum @enum, params object[] objs)
|
||||
{
|
||||
return Resource.ResourceManager.GetString(@enum.ToString()).Format(objs);
|
||||
}
|
||||
}
|
||||
}
|
||||
21
RRQMCore/Data/Converter/CollectionConvert.cs
Normal file
21
RRQMCore/Data/Converter/CollectionConvert.cs
Normal file
@@ -0,0 +1,21 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权(除特别声明或在RRQMCore.XREF命名空间的代码)归作者本人若汝棋茗所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权
|
||||
// CSDN博客:https://blog.csdn.net/qq_40374647
|
||||
// 哔哩哔哩视频:https://space.bilibili.com/94253567
|
||||
// Gitee源代码仓库:https://gitee.com/RRQM_Home
|
||||
// Github源代码仓库:https://github.com/RRQM
|
||||
// 交流QQ群:234762506
|
||||
// 感谢您的下载和使用
|
||||
//------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace RRQMCore.Data.Converter
|
||||
{
|
||||
/// <summary>
|
||||
/// 集合转换器
|
||||
/// </summary>
|
||||
public class CollectionConvert
|
||||
{
|
||||
}
|
||||
}
|
||||
90
RRQMCore/Data/Converter/ValueConvert.cs
Normal file
90
RRQMCore/Data/Converter/ValueConvert.cs
Normal file
@@ -0,0 +1,90 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权(除特别声明或在RRQMCore.XREF命名空间的代码)归作者本人若汝棋茗所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权
|
||||
// CSDN博客:https://blog.csdn.net/qq_40374647
|
||||
// 哔哩哔哩视频:https://space.bilibili.com/94253567
|
||||
// Gitee源代码仓库:https://gitee.com/RRQM_Home
|
||||
// Github源代码仓库:https://github.com/RRQM
|
||||
// 交流QQ群:234762506
|
||||
// 感谢您的下载和使用
|
||||
//------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------
|
||||
using System;
|
||||
|
||||
namespace RRQMCore.Data.Converter
|
||||
{
|
||||
/// <summary>
|
||||
/// 值转换器
|
||||
/// </summary>
|
||||
public static class ValueConvert
|
||||
{
|
||||
/// <summary>
|
||||
/// int型转换器
|
||||
/// </summary>
|
||||
/// <param name="valueString">数字字符串</param>
|
||||
/// <param name="defaultValue">默认值</param>
|
||||
/// <returns>返回值结果</returns>
|
||||
public static int IntConvert(string valueString, int defaultValue = 0)
|
||||
{
|
||||
int result;
|
||||
if (int.TryParse(valueString, out result))
|
||||
{
|
||||
return result;
|
||||
}
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// int型转换器
|
||||
/// </summary>
|
||||
/// <param name="valueObject"></param>
|
||||
/// <returns></returns>
|
||||
public static int IntConvert(object valueObject)
|
||||
{
|
||||
return (int)valueObject;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// long值转换器
|
||||
/// </summary>
|
||||
/// <param name="valueObject"></param>
|
||||
/// <returns></returns>
|
||||
public static long LongConvert(object valueObject)
|
||||
{
|
||||
return (long)valueObject;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 双精度值转换
|
||||
/// </summary>
|
||||
/// <param name="valueString">数字字符串</param>
|
||||
/// <param name="defaultValue">默认值</param>
|
||||
/// <returns>返回值结果</returns>
|
||||
public static double DoubleConvert(string valueString, double defaultValue = 0)
|
||||
{
|
||||
double result;
|
||||
if (double.TryParse(valueString, out result))
|
||||
{
|
||||
return result;
|
||||
}
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 枚举类型转换
|
||||
/// </summary>
|
||||
/// <typeparam name="T">枚举类型</typeparam>
|
||||
/// <param name="valueString">枚举字符串</param>
|
||||
/// <param name="defaultValue">默认值</param>
|
||||
/// <returns>返回值结果</returns>
|
||||
public static T EnumConvert<T>(string valueString, T defaultValue = default(T)) where T : struct
|
||||
{
|
||||
T result;
|
||||
if (Enum.TryParse(valueString, out result))
|
||||
{
|
||||
return result;
|
||||
}
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
68
RRQMCore/Data/Security/DataLock.cs
Normal file
68
RRQMCore/Data/Security/DataLock.cs
Normal file
@@ -0,0 +1,68 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权(除特别声明或在RRQMCore.XREF命名空间的代码)归作者本人若汝棋茗所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权
|
||||
// CSDN博客:https://blog.csdn.net/qq_40374647
|
||||
// 哔哩哔哩视频:https://space.bilibili.com/94253567
|
||||
// Gitee源代码仓库:https://gitee.com/RRQM_Home
|
||||
// Github源代码仓库:https://github.com/RRQM
|
||||
// 交流QQ群:234762506
|
||||
// 感谢您的下载和使用
|
||||
//------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------
|
||||
using System.IO;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
|
||||
namespace RRQMCore.Data.Security
|
||||
{
|
||||
/// <summary>
|
||||
/// 数据锁,用于加密或解密
|
||||
/// </summary>
|
||||
public static class DataLock
|
||||
{
|
||||
/// <summary>
|
||||
/// 使用3DES加密
|
||||
/// </summary>
|
||||
/// <param name="data">待加密字节</param>
|
||||
/// <param name="encryptKey">加密口令(长度为8)</param>
|
||||
/// <returns></returns>
|
||||
public static byte[] EncryptDES(byte[] data, string encryptKey)
|
||||
{
|
||||
byte[] rgbKey = Encoding.UTF8.GetBytes(encryptKey.Substring(0, 8));
|
||||
byte[] rgbIV = { 0x12, 0x34, 4, 0x78, 0x90, 255, 0xCD, 0xEF };
|
||||
DESCryptoServiceProvider dCSP = new DESCryptoServiceProvider();
|
||||
using (MemoryStream mStream = new MemoryStream())
|
||||
{
|
||||
using (CryptoStream cStream = new CryptoStream(mStream, dCSP.CreateEncryptor(rgbKey, rgbIV), CryptoStreamMode.Write))
|
||||
{
|
||||
cStream.Write(data, 0, data.Length);
|
||||
cStream.FlushFinalBlock();
|
||||
return mStream.ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 使用3DES解密
|
||||
/// </summary>
|
||||
/// <param name="data">待解密字节</param>
|
||||
/// <param name="decryptionKey">解密口令(长度为8)</param>
|
||||
/// <returns></returns>
|
||||
public static byte[] DecryptDES(byte[] data, string decryptionKey)
|
||||
{
|
||||
byte[] rgbKey = Encoding.UTF8.GetBytes(decryptionKey);
|
||||
byte[] rgbIV = { 0x12, 0x34, 4, 0x78, 0x90, 255, 0xCD, 0xEF };
|
||||
DESCryptoServiceProvider DCSP = new DESCryptoServiceProvider();
|
||||
|
||||
using (MemoryStream mStream = new MemoryStream())
|
||||
{
|
||||
using (CryptoStream cStream = new CryptoStream(mStream, DCSP.CreateDecryptor(rgbKey, rgbIV), CryptoStreamMode.Write))
|
||||
{
|
||||
cStream.Write(data, 0, data.Length);
|
||||
cStream.FlushFinalBlock();
|
||||
return mStream.ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
720
RRQMCore/Data/XML/XmlTool.cs
Normal file
720
RRQMCore/Data/XML/XmlTool.cs
Normal file
@@ -0,0 +1,720 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权(除特别声明或在RRQMCore.XREF命名空间的代码)归作者本人若汝棋茗所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权
|
||||
// CSDN博客:https://blog.csdn.net/qq_40374647
|
||||
// 哔哩哔哩视频:https://space.bilibili.com/94253567
|
||||
// Gitee源代码仓库:https://gitee.com/RRQM_Home
|
||||
// Github源代码仓库:https://github.com/RRQM
|
||||
// 交流QQ群:234762506
|
||||
// 感谢您的下载和使用
|
||||
//------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Xml;
|
||||
|
||||
namespace RRQMCore.Data.XML
|
||||
{
|
||||
/// <summary>
|
||||
/// xml主类
|
||||
/// </summary>
|
||||
public class XmlTool
|
||||
{
|
||||
/// <summary>
|
||||
/// 构造函数
|
||||
/// </summary>
|
||||
/// <param name="path">文件路径,包含文件名</param>
|
||||
public XmlTool(string path)
|
||||
{
|
||||
this.path = path;
|
||||
}
|
||||
|
||||
private string path = null;
|
||||
|
||||
#region 存储
|
||||
|
||||
/// <summary>
|
||||
/// 单节点,单属性储存
|
||||
/// </summary>
|
||||
/// <param name="NodeName">节点名</param>
|
||||
/// <param name="Attribute_name">属性名</param>
|
||||
/// <param name="Attribute_value">属性值</param>
|
||||
public void AttributeStorage(string NodeName, string Attribute_name, string Attribute_value)
|
||||
{
|
||||
if (File.Exists(path))
|
||||
{//存在Xml的文件
|
||||
XmlDocument xml = new XmlDocument();
|
||||
xml.Load(path);
|
||||
XmlElement root = xml.DocumentElement;
|
||||
XmlNodeList nodeList = root.ChildNodes;
|
||||
bool N = false;//节点判断变量
|
||||
foreach (XmlNode item in nodeList)
|
||||
{//判断是否存在该节点
|
||||
if (item.Name == NodeName)
|
||||
{
|
||||
N = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (N == false)
|
||||
{//不存在节点,属性,建立节点,属性
|
||||
XmlElement PointName = xml.CreateElement(NodeName);
|
||||
PointName.SetAttribute(Attribute_name, Attribute_value);
|
||||
root.AppendChild(PointName);
|
||||
}
|
||||
else
|
||||
{//存在属性进行赋值
|
||||
XmlNode PointName = xml.SelectSingleNode("Root/" + NodeName);
|
||||
PointName.Attributes[Attribute_name].Value = Attribute_value;
|
||||
}
|
||||
xml.Save(path);
|
||||
}
|
||||
else
|
||||
{
|
||||
XmlDocument xml = new XmlDocument();
|
||||
XmlDeclaration dec = xml.CreateXmlDeclaration("1.0", "UTF-8", null);
|
||||
XmlElement root = xml.CreateElement("Root");
|
||||
xml.AppendChild(root);//根元素
|
||||
|
||||
XmlElement PointName = xml.CreateElement(NodeName);
|
||||
PointName.SetAttribute(Attribute_name, Attribute_value);
|
||||
root.AppendChild(PointName);
|
||||
xml.Save(path);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 单节点,多属性存储
|
||||
/// </summary>
|
||||
/// <param name="NodeName">节点名</param>
|
||||
/// <param name="Attribute_name">属性集合</param>
|
||||
/// <param name="Attribute_value">属性值集合</param>
|
||||
public void AttributeStorage(string NodeName, string[] Attribute_name, string[] Attribute_value)
|
||||
{
|
||||
if (Attribute_name.Length != Attribute_value.Length)
|
||||
{
|
||||
Console.WriteLine("属性名数量和属性值数量不一致,无法储存");
|
||||
return;
|
||||
}
|
||||
if (File.Exists(path))
|
||||
{//存在Xml的文件
|
||||
XmlDocument xml = new XmlDocument();
|
||||
xml.Load(path);
|
||||
XmlElement root = xml.DocumentElement;
|
||||
XmlNodeList nodeList = root.ChildNodes;
|
||||
bool N = false;//节点变量
|
||||
foreach (XmlNode item in nodeList)
|
||||
{//判断是否存在该节点
|
||||
if (item.Name == NodeName)
|
||||
{
|
||||
N = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (N == false)
|
||||
{//不存在节点,属性,建立节点,属性
|
||||
XmlElement PointName = xml.CreateElement(NodeName);
|
||||
for (int i = 0; i < Attribute_name.Length; i++)
|
||||
{
|
||||
PointName.SetAttribute(Attribute_name[i], Attribute_value[i]);
|
||||
root.AppendChild(PointName);
|
||||
}
|
||||
}
|
||||
else
|
||||
{//存在属性进行赋值
|
||||
XmlNode PointName = xml.SelectSingleNode("Root/" + NodeName);
|
||||
for (int i = 0; i < Attribute_name.Length; i++)
|
||||
{
|
||||
PointName.Attributes[Attribute_name[i]].Value = Attribute_value[i];
|
||||
}
|
||||
}
|
||||
xml.Save(path);
|
||||
}
|
||||
else
|
||||
{
|
||||
XmlDocument xml = new XmlDocument();
|
||||
XmlDeclaration dec = xml.CreateXmlDeclaration("1.0", "UTF-8", null);
|
||||
XmlElement root = xml.CreateElement("Root");
|
||||
xml.AppendChild(root);//根元素
|
||||
|
||||
XmlElement PointName = xml.CreateElement(NodeName);
|
||||
for (int i = 0; i < Attribute_name.Length; i++)
|
||||
{
|
||||
PointName.SetAttribute(Attribute_name[i], Attribute_value[i]);
|
||||
root.AppendChild(PointName);
|
||||
}
|
||||
xml.Save(path);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 单节点,单属性多集合存储
|
||||
/// </summary>
|
||||
/// <param name="NodeName">节点集合</param>
|
||||
/// <param name="Attribute_name">属性名集合</param>
|
||||
/// <param name="Attribute_value">属性值集合</param>
|
||||
public void AttributeStorage(string[] NodeName, string[] Attribute_name, string[] Attribute_value)
|
||||
{
|
||||
if ((Attribute_name.Length != Attribute_value.Length) && NodeName.Length != Attribute_name.Length)
|
||||
{
|
||||
Console.WriteLine("属性名数量和属性值数量不一致,无法储存");
|
||||
return;
|
||||
}
|
||||
if (File.Exists(path))
|
||||
{//存在Xml的文件
|
||||
XmlDocument xml = new XmlDocument();
|
||||
xml.Load(path);
|
||||
XmlElement root = xml.DocumentElement;
|
||||
XmlNodeList nodeList = root.ChildNodes;
|
||||
for (int i = 0; i < NodeName.Length; i++)
|
||||
{
|
||||
bool N = false;//节点变量
|
||||
foreach (XmlNode item in nodeList)
|
||||
{//判断是否存在该节点
|
||||
if (item.Name == NodeName[i])
|
||||
{
|
||||
N = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (N == false)
|
||||
{//不存在节点,属性,建立节点,属性
|
||||
XmlElement PointName = xml.CreateElement(NodeName[i]);
|
||||
|
||||
PointName.SetAttribute(Attribute_name[i], Attribute_value[i]);
|
||||
root.AppendChild(PointName);
|
||||
}
|
||||
else
|
||||
{//存在属性进行赋值
|
||||
XmlNode PointName = xml.SelectSingleNode("Root/" + NodeName);
|
||||
|
||||
PointName.Attributes[Attribute_name[i]].Value = Attribute_value[i];
|
||||
}
|
||||
xml.Save(path);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
XmlDocument xml = new XmlDocument();
|
||||
XmlDeclaration dec = xml.CreateXmlDeclaration("1.0", "UTF-8", null);
|
||||
XmlElement root = xml.CreateElement("Root");
|
||||
xml.AppendChild(root);//根元素
|
||||
for (int i = 0; i < NodeName.Length; i++)
|
||||
{
|
||||
XmlElement PointName = xml.CreateElement(NodeName[i]);
|
||||
PointName.SetAttribute(Attribute_name[i], Attribute_value[i]);
|
||||
root.AppendChild(PointName);
|
||||
|
||||
xml.Save(path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 多节点,多属性,多集合存储
|
||||
/// </summary>
|
||||
/// <param name="NodeName">节点集合</param>
|
||||
/// <param name="Attribute_name">属性集合</param>
|
||||
/// <param name="AttributeNumber">每个节点的属性数量</param>
|
||||
/// <param name="Attribute_value">属性值集合</param>
|
||||
public void AttributeStorage(string[] NodeName, string[] Attribute_name, int AttributeNumber, params string[][] Attribute_value)
|
||||
{
|
||||
if (File.Exists(path))
|
||||
{
|
||||
//存在Xml的文件
|
||||
XmlDocument xml = new XmlDocument();
|
||||
xml.Load(path);
|
||||
XmlElement root = xml.DocumentElement;
|
||||
XmlNodeList nodeList = root.ChildNodes;
|
||||
for (int i = 0; i < NodeName.Length; i++)
|
||||
{
|
||||
bool N = false;//节点变量
|
||||
foreach (XmlNode item in nodeList)
|
||||
{//判断是否存在该节点
|
||||
if (item.Name == NodeName[i])
|
||||
{
|
||||
N = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (N == false)
|
||||
{//不存在节点,属性,建立节点,属性
|
||||
XmlElement PointName = xml.CreateElement(NodeName[i]);
|
||||
for (int j = 0; j < AttributeNumber; j++)
|
||||
{
|
||||
PointName.SetAttribute(Attribute_name[j], Attribute_value[j][i]);
|
||||
}
|
||||
|
||||
root.AppendChild(PointName);
|
||||
}
|
||||
else
|
||||
{//存在属性进行赋值
|
||||
XmlNode PointName = xml.SelectSingleNode("Root/" + NodeName[i]);
|
||||
|
||||
for (int j = 0; j < AttributeNumber; j++)
|
||||
{
|
||||
PointName.Attributes[Attribute_name[j]].Value = Attribute_value[j][i];
|
||||
}
|
||||
}
|
||||
}
|
||||
xml.Save(path);
|
||||
}
|
||||
else
|
||||
{
|
||||
XmlDocument xml = new XmlDocument();
|
||||
XmlDeclaration dec = xml.CreateXmlDeclaration("1.0", "UTF-8", null);
|
||||
XmlElement root = xml.CreateElement("Root");
|
||||
xml.AppendChild(root);//根元素
|
||||
for (int i = 0; i < NodeName.Length; i++)
|
||||
{
|
||||
XmlElement PointName = xml.CreateElement(NodeName[i]);
|
||||
for (int j = 0; j < AttributeNumber; j++)
|
||||
{
|
||||
PointName.SetAttribute(Attribute_name[j], Attribute_value[j][i]);
|
||||
}
|
||||
root.AppendChild(PointName);
|
||||
|
||||
xml.Save(path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 节点值存储
|
||||
/// </summary>
|
||||
/// <param name="NodeName">节点名</param>
|
||||
/// <param name="Text">文本</param>
|
||||
public void NodeStorage(string NodeName, string Text)
|
||||
{
|
||||
if (File.Exists(path))
|
||||
{
|
||||
XmlDocument xml = new XmlDocument();
|
||||
xml.Load(path);
|
||||
XmlElement root = xml.DocumentElement;
|
||||
XmlNodeList nodeList = root.ChildNodes;
|
||||
bool n = false;
|
||||
foreach (XmlNode item in nodeList)
|
||||
{
|
||||
if (item.Name == NodeName)
|
||||
{
|
||||
item.InnerText = Text;
|
||||
n = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (n == false)
|
||||
{
|
||||
XmlElement other = xml.CreateElement(NodeName);
|
||||
other.InnerText = Text;
|
||||
root.AppendChild(other);
|
||||
}
|
||||
xml.Save(path);
|
||||
}
|
||||
else
|
||||
{
|
||||
XmlDocument doc = new XmlDocument();
|
||||
XmlDeclaration dec = doc.CreateXmlDeclaration("1.0", "UTF-8", null);
|
||||
XmlElement Root = doc.CreateElement("Root");
|
||||
doc.AppendChild(Root);//根元素
|
||||
|
||||
XmlElement Node = doc.CreateElement(NodeName);
|
||||
Node.InnerText = Text;
|
||||
Root.AppendChild(Node);
|
||||
|
||||
doc.Save(path);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion 存储
|
||||
|
||||
#region
|
||||
|
||||
/// <summary>
|
||||
/// 通过节点取值
|
||||
/// </summary>
|
||||
/// <param name="NodeName">节点名</param>
|
||||
/// <returns>取值失败返回null</returns>
|
||||
public string SearchNode(string NodeName)
|
||||
{
|
||||
if (File.Exists(path))
|
||||
{
|
||||
XmlDocument xml = new XmlDocument();
|
||||
xml.Load(path);
|
||||
XmlElement root = xml.DocumentElement;
|
||||
XmlNodeList nodeList = root.ChildNodes;
|
||||
foreach (XmlNode item in nodeList)
|
||||
{
|
||||
if (item.Name == NodeName)
|
||||
{
|
||||
return item.InnerText;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找数字
|
||||
/// </summary>
|
||||
/// <param name="NodeName">节点名</param>
|
||||
/// <param name="Attribute_name">属性名</param>
|
||||
/// <returns>取值失败返回0</returns>
|
||||
public int SearchNumber(string NodeName, string Attribute_name)
|
||||
{
|
||||
if (File.Exists(path))
|
||||
{
|
||||
XmlDocument xml = new XmlDocument();
|
||||
xml.Load(path);
|
||||
XmlElement root = xml.DocumentElement;
|
||||
XmlNodeList nodeList = root.ChildNodes;
|
||||
foreach (XmlNode item in nodeList)
|
||||
{
|
||||
if (item.Name == NodeName)
|
||||
{
|
||||
if (item.Attributes[Attribute_name] != null)
|
||||
{
|
||||
return Convert.ToInt32(item.Attributes[Attribute_name].Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找属性值
|
||||
/// </summary>
|
||||
/// <param name="NodeName">节点名</param>
|
||||
/// <param name="Attribute_name">属性名</param>
|
||||
/// <returns>取值失败返回null</returns>
|
||||
public string SearchWords(string NodeName, string Attribute_name)
|
||||
{
|
||||
if (File.Exists(path))
|
||||
{
|
||||
XmlDocument xml = new XmlDocument();
|
||||
xml.Load(path);
|
||||
XmlElement root = xml.DocumentElement;
|
||||
XmlNodeList nodeList = root.ChildNodes;
|
||||
foreach (XmlNode item in nodeList)
|
||||
{
|
||||
if (item.Name == NodeName)
|
||||
{
|
||||
if (item.Attributes[Attribute_name] != null)
|
||||
{
|
||||
return item.Attributes[Attribute_name].Value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找布尔值
|
||||
/// </summary>
|
||||
/// <param name="NodeName">节点名</param>
|
||||
/// <param name="Attribute_name">属性值</param>
|
||||
/// <returns>返回查找结果,查询失败返回false</returns>
|
||||
public bool SearchBoolean(string NodeName, string Attribute_name)
|
||||
{
|
||||
if (File.Exists(path))
|
||||
{
|
||||
XmlDocument xml = new XmlDocument();
|
||||
xml.Load(path);
|
||||
XmlElement root = xml.DocumentElement;
|
||||
XmlNodeList nodeList = root.ChildNodes;
|
||||
foreach (XmlNode item in nodeList)
|
||||
{
|
||||
if (item.Name == NodeName)
|
||||
{
|
||||
if (item.Attributes[Attribute_name] != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
return Convert.ToBoolean(item.Attributes[Attribute_name].Value);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找属性值集合
|
||||
/// </summary>
|
||||
/// <param name="NodeName">节点名集合</param>
|
||||
/// <param name="Attribute_name">属性名集合</param>
|
||||
/// <returns>文件不在返回null,单个属性不在返回“空”</returns>
|
||||
public string[] SearchWords(string[] NodeName, string[] Attribute_name)
|
||||
{
|
||||
if (File.Exists(path))
|
||||
{
|
||||
string[] s = new string[NodeName.Length];
|
||||
XmlDocument xml = new XmlDocument();
|
||||
xml.Load(path);
|
||||
XmlElement root = xml.DocumentElement;
|
||||
XmlNodeList nodeList = root.ChildNodes;
|
||||
for (int i = 0; i < NodeName.Length; i++)
|
||||
{
|
||||
foreach (XmlNode item in nodeList)
|
||||
{
|
||||
if (item.Name == NodeName[i])
|
||||
{
|
||||
if (item.Attributes[Attribute_name[i]] != null)
|
||||
{
|
||||
s[i] = item.Attributes[Attribute_name[i]].Value;
|
||||
}
|
||||
else
|
||||
{
|
||||
s[i] = "";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return s;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 通过确切属性值,属性名,查找其他属性值
|
||||
/// </summary>
|
||||
/// <param name="Attribute_name1">已知属性名</param>
|
||||
/// <param name="Attribute_value">已知属性值</param>
|
||||
/// <param name="Attribute_name2">待查属性名</param>
|
||||
/// <returns>待查属性值</returns>
|
||||
public string[] SearchWords(string Attribute_name1, string Attribute_value, string Attribute_name2)
|
||||
{
|
||||
List<string> values = new List<string>();
|
||||
if (File.Exists(path))
|
||||
{
|
||||
XmlDocument xml = new XmlDocument();
|
||||
xml.Load(path);
|
||||
XmlElement root = xml.DocumentElement;
|
||||
XmlNodeList nodeList = root.ChildNodes;
|
||||
foreach (XmlNode item in nodeList)
|
||||
{
|
||||
if (item.Attributes[Attribute_name1] != null)
|
||||
{
|
||||
if (item.Attributes[Attribute_name1].Value == Attribute_value)
|
||||
{
|
||||
if (item.Attributes[Attribute_name2] != null)
|
||||
{
|
||||
values.Add(item.Attributes[Attribute_name2].Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return values.ToArray();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找节点的所有属性值
|
||||
/// </summary>
|
||||
/// <param name="NodeName">节点 名</param>
|
||||
/// <returns>返回查找键值对,查询失败返回null</returns>
|
||||
public Dictionary<string, string> SearchAllAttributes(string NodeName)
|
||||
{
|
||||
Dictionary<string, string> Attributes = new Dictionary<string, string>();
|
||||
if (File.Exists(path))
|
||||
{
|
||||
XmlDocument xml = new XmlDocument();
|
||||
xml.Load(path);
|
||||
XmlElement root = xml.DocumentElement;
|
||||
XmlNodeList nodeList = root.ChildNodes;
|
||||
foreach (XmlNode item in nodeList)
|
||||
{
|
||||
if (item.Name == NodeName)
|
||||
{
|
||||
XmlAttributeCollection attributeCollection = item.Attributes;
|
||||
if (attributeCollection != null)
|
||||
{
|
||||
foreach (XmlAttribute attribute in attributeCollection)
|
||||
{
|
||||
Attributes.Add(attribute.Name, attribute.Value);
|
||||
}
|
||||
}
|
||||
return Attributes;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 通过确切属性值,属性名,查找其他属性的布尔值
|
||||
/// </summary>
|
||||
/// <param name="Attribute_name1">已知属性名</param>
|
||||
/// <param name="Attribute_value">已知属性值</param>
|
||||
/// <param name="Attribute_name2">待查属性名</param>
|
||||
/// <returns>待查布尔值,失败返回false</returns>
|
||||
public bool SearchBoolean(string Attribute_name1, string Attribute_value, string Attribute_name2)
|
||||
{
|
||||
if (File.Exists(path))
|
||||
{
|
||||
XmlDocument xml = new XmlDocument();
|
||||
xml.Load(path);
|
||||
XmlElement root = xml.DocumentElement;
|
||||
XmlNodeList nodeList = root.ChildNodes;
|
||||
foreach (XmlNode item in nodeList)
|
||||
{
|
||||
if (item.Attributes[Attribute_name1].Value == Attribute_value)
|
||||
{
|
||||
if (item.Attributes[Attribute_name2] != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
return Convert.ToBoolean(item.Attributes[Attribute_name2].Value);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// 按节点名移除节点
|
||||
/// </summary>
|
||||
/// <param name="NodeName">节点名</param>
|
||||
/// <returns>是否移除成功</returns>
|
||||
public bool RemoveNode(string NodeName)
|
||||
{
|
||||
if (File.Exists(path))
|
||||
{
|
||||
XmlDocument xml = new XmlDocument();
|
||||
xml.Load(path);
|
||||
XmlElement root = xml.DocumentElement;
|
||||
XmlNodeList nodeList = root.ChildNodes;
|
||||
foreach (XmlNode item in nodeList)
|
||||
{
|
||||
if (item.Name == NodeName)
|
||||
{
|
||||
root.RemoveChild(item);
|
||||
xml.Save(path);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 按确切的属性名,属性值删除节点
|
||||
/// </summary>
|
||||
/// <param name="Attribute_name">属性名</param>
|
||||
/// <param name="Attribute_value">属性值</param>
|
||||
/// <returns>是否移除成功</returns>
|
||||
public bool RemoveNode(string Attribute_name, string Attribute_value)
|
||||
{
|
||||
if (File.Exists(path))
|
||||
{
|
||||
XmlDocument xml = new XmlDocument();
|
||||
xml.Load(path);
|
||||
XmlElement root = xml.DocumentElement;
|
||||
XmlNodeList nodeList = root.ChildNodes;
|
||||
foreach (XmlNode item in nodeList)
|
||||
{
|
||||
if (item.Attributes[Attribute_name] != null)
|
||||
{
|
||||
if (item.Attributes[Attribute_name].Value == Attribute_value)
|
||||
{
|
||||
root.RemoveChild(item);
|
||||
xml.Save(path);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 如果节点中有日期属性,把日期之前的节点都删除
|
||||
/// </summary>
|
||||
/// <param name="Attribute_name">属性名</param>
|
||||
/// <param name="dateTime">截止时间</param>
|
||||
/// <returns>是否删除成功</returns>
|
||||
public bool RemoveNode(string Attribute_name, DateTime dateTime)
|
||||
{
|
||||
if (File.Exists(path))
|
||||
{
|
||||
XmlDocument xml = new XmlDocument();
|
||||
xml.Load(path);
|
||||
XmlElement root = xml.DocumentElement;
|
||||
XmlNodeList nodeList = root.ChildNodes;
|
||||
for (int i = 0; i < nodeList.Count; i++)
|
||||
{
|
||||
if (nodeList[i].Attributes[Attribute_name] != null)
|
||||
{
|
||||
DateTime dt = Convert.ToDateTime(nodeList[i].Attributes[Attribute_name].Value);
|
||||
if (DateTime.Compare(dt, dateTime) < 0)
|
||||
{
|
||||
root.RemoveChild(nodeList[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
xml.Save(path);
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 判断节点是否存在
|
||||
/// </summary>
|
||||
/// <param name="NodeName">节点名</param>
|
||||
/// <returns>返回结果</returns>
|
||||
public bool NodeExist(string NodeName)
|
||||
{
|
||||
if (File.Exists(path))
|
||||
{
|
||||
XmlDocument xml = new XmlDocument();
|
||||
xml.Load(path);
|
||||
XmlElement root = xml.DocumentElement;
|
||||
XmlNodeList nodeList = root.ChildNodes;
|
||||
foreach (XmlNode item in nodeList)
|
||||
{
|
||||
if (item.Name == NodeName)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 删除所有节点,不包含子节点
|
||||
/// </summary>
|
||||
/// <returns>返回删除是否成功</returns>
|
||||
public bool RemoveAllNode()
|
||||
{
|
||||
if (File.Exists(path))
|
||||
{
|
||||
XmlDocument xml = new XmlDocument();
|
||||
xml.Load(path);
|
||||
XmlElement root = xml.DocumentElement;
|
||||
root.RemoveAll();
|
||||
xml.Save(path);
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
23
RRQMCore/Dependency/Attribute/DataValidationAttribute.cs
Normal file
23
RRQMCore/Dependency/Attribute/DataValidationAttribute.cs
Normal file
@@ -0,0 +1,23 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权(除特别声明或在RRQMCore.XREF命名空间的代码)归作者本人若汝棋茗所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权
|
||||
// CSDN博客:https://blog.csdn.net/qq_40374647
|
||||
// 哔哩哔哩视频:https://space.bilibili.com/94253567
|
||||
// Gitee源代码仓库:https://gitee.com/RRQM_Home
|
||||
// Github源代码仓库:https://github.com/RRQM
|
||||
// 交流QQ群:234762506
|
||||
// 感谢您的下载和使用
|
||||
//------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------
|
||||
using System;
|
||||
|
||||
namespace RRQMCore.Dependency
|
||||
{
|
||||
/// <summary>
|
||||
/// 依赖属性数据验证
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)]
|
||||
public class DataValidationAttribute : Attribute
|
||||
{
|
||||
}
|
||||
}
|
||||
107
RRQMCore/Dependency/DependencyProperty.cs
Normal file
107
RRQMCore/Dependency/DependencyProperty.cs
Normal file
@@ -0,0 +1,107 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权(除特别声明或在RRQMCore.XREF命名空间的代码)归作者本人若汝棋茗所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权
|
||||
// CSDN博客:https://blog.csdn.net/qq_40374647
|
||||
// 哔哩哔哩视频:https://space.bilibili.com/94253567
|
||||
// Gitee源代码仓库:https://gitee.com/RRQM_Home
|
||||
// Github源代码仓库:https://github.com/RRQM
|
||||
// 交流QQ群:234762506
|
||||
// 感谢您的下载和使用
|
||||
//------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------
|
||||
using RRQMCore.Exceptions;
|
||||
using System;
|
||||
using System.Reflection;
|
||||
|
||||
namespace RRQMCore.Dependency
|
||||
{
|
||||
/// <summary>
|
||||
/// 依赖项属性
|
||||
/// </summary>
|
||||
public class DependencyProperty
|
||||
{
|
||||
private DependencyProperty()
|
||||
{
|
||||
}
|
||||
|
||||
private string name;
|
||||
|
||||
/// <summary>
|
||||
/// 属性名
|
||||
/// </summary>
|
||||
public string Name
|
||||
{
|
||||
get { return name; }
|
||||
}
|
||||
|
||||
private Type owner;
|
||||
|
||||
/// <summary>
|
||||
/// 所属类型
|
||||
/// </summary>
|
||||
public Type Owner
|
||||
{
|
||||
get { return owner; }
|
||||
}
|
||||
|
||||
private Type valueType;
|
||||
|
||||
/// <summary>
|
||||
/// 值类型
|
||||
/// </summary>
|
||||
public Type ValueType
|
||||
{
|
||||
get { return valueType; }
|
||||
}
|
||||
|
||||
private object value;
|
||||
|
||||
/// <summary>
|
||||
/// 默认值
|
||||
/// </summary>
|
||||
public object DefauleValue
|
||||
{
|
||||
get { return value; }
|
||||
}
|
||||
|
||||
internal void DataValidation(object value)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
if (typeof(ValueType).IsAssignableFrom(valueType))
|
||||
{
|
||||
throw new RRQMException($"属性“{this.name}”赋值类型不允许出现Null");
|
||||
}
|
||||
}
|
||||
else if (!valueType.IsAssignableFrom(value.GetType()))
|
||||
{
|
||||
throw new RRQMException($"属性“{this.name}”赋值类型与注册类型不一致,应当注入“{valueType}”类型");
|
||||
}
|
||||
}
|
||||
|
||||
internal void SetDefauleValue(object value)
|
||||
{
|
||||
this.DataValidation(value);
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 注册依赖项属性
|
||||
/// </summary>
|
||||
/// <param name="propertyName"></param>
|
||||
/// <param name="valueType"></param>
|
||||
/// <param name="owner"></param>
|
||||
/// <param name="value"></param>
|
||||
/// <returns></returns>
|
||||
public static DependencyProperty Register(string propertyName, Type valueType, Type owner, object value)
|
||||
{
|
||||
FieldInfo fieldInfo = owner.GetField($"{propertyName}Property");
|
||||
DependencyProperty dp = new DependencyProperty();
|
||||
dp.name = propertyName;
|
||||
dp.valueType = valueType;
|
||||
dp.owner = owner;
|
||||
dp.SetDefauleValue(value);
|
||||
return dp;
|
||||
}
|
||||
}
|
||||
}
|
||||
75
RRQMCore/Dependency/RRQMDependencyObject.cs
Normal file
75
RRQMCore/Dependency/RRQMDependencyObject.cs
Normal file
@@ -0,0 +1,75 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权(除特别声明或在RRQMCore.XREF命名空间的代码)归作者本人若汝棋茗所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权
|
||||
// CSDN博客:https://blog.csdn.net/qq_40374647
|
||||
// 哔哩哔哩视频:https://space.bilibili.com/94253567
|
||||
// Gitee源代码仓库:https://gitee.com/RRQM_Home
|
||||
// Github源代码仓库:https://github.com/RRQM
|
||||
// 交流QQ群:234762506
|
||||
// 感谢您的下载和使用
|
||||
//------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------
|
||||
using System.Collections.Concurrent;
|
||||
|
||||
namespace RRQMCore.Dependency
|
||||
{
|
||||
/// <summary>
|
||||
/// 依赖项对象
|
||||
/// </summary>
|
||||
public class RRQMDependencyObject
|
||||
{
|
||||
/// <summary>
|
||||
/// 构造函数
|
||||
/// </summary>
|
||||
public RRQMDependencyObject()
|
||||
{
|
||||
this.dp = new ConcurrentDictionary<DependencyProperty, object>();
|
||||
}
|
||||
|
||||
[System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)]
|
||||
private ConcurrentDictionary<DependencyProperty, object> dp;
|
||||
|
||||
/// <summary>
|
||||
/// 获取值
|
||||
/// </summary>
|
||||
/// <param name="dependencyProperty"></param>
|
||||
/// <returns></returns>
|
||||
public object GetValue(DependencyProperty dependencyProperty)
|
||||
{
|
||||
if (dp.TryGetValue(dependencyProperty, out object value))
|
||||
{
|
||||
return value;
|
||||
}
|
||||
else
|
||||
{
|
||||
return dependencyProperty.DefauleValue;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取值
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="dependencyProperty"></param>
|
||||
/// <returns></returns>
|
||||
public T GetValue<T>(DependencyProperty dependencyProperty)
|
||||
{
|
||||
return (T)this.GetValue(dependencyProperty);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置值
|
||||
/// </summary>
|
||||
/// <param name="dependencyProperty"></param>
|
||||
/// <param name="value"></param>
|
||||
public RRQMDependencyObject SetValue(DependencyProperty dependencyProperty, object value)
|
||||
{
|
||||
dependencyProperty.DataValidation(value);
|
||||
dp.AddOrUpdate(dependencyProperty, value, (DependencyProperty dp, object v) =>
|
||||
{
|
||||
return value;
|
||||
});
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
||||
47
RRQMCore/Diagnostics/TimeMeasurer.cs
Normal file
47
RRQMCore/Diagnostics/TimeMeasurer.cs
Normal file
@@ -0,0 +1,47 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权(除特别声明或在RRQMCore.XREF命名空间的代码)归作者本人若汝棋茗所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权
|
||||
// CSDN博客:https://blog.csdn.net/qq_40374647
|
||||
// 哔哩哔哩视频:https://space.bilibili.com/94253567
|
||||
// Gitee源代码仓库:https://gitee.com/RRQM_Home
|
||||
// Github源代码仓库:https://github.com/RRQM
|
||||
// 交流QQ群:234762506
|
||||
// 感谢您的下载和使用
|
||||
//------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace RRQMCore.Diagnostics
|
||||
{
|
||||
/// <summary>
|
||||
/// 时间测量器
|
||||
/// </summary>
|
||||
public class TimeMeasurer
|
||||
{
|
||||
/// <summary>
|
||||
/// 开始运行
|
||||
/// </summary>
|
||||
/// <param name="action"></param>
|
||||
/// <returns></returns>
|
||||
public static TimeSpan Run(Action action)
|
||||
{
|
||||
Stopwatch stopwatch = new Stopwatch();
|
||||
stopwatch.Start();
|
||||
action?.Invoke();
|
||||
stopwatch.Stop();
|
||||
return stopwatch.Elapsed;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 异步执行
|
||||
/// </summary>
|
||||
/// <param name="action"></param>
|
||||
/// <returns></returns>
|
||||
public static Task<TimeSpan> RunAsync(Action action)
|
||||
{
|
||||
return Task.Run(() => { return Run(action); });
|
||||
}
|
||||
}
|
||||
}
|
||||
23
RRQMCore/Event/RRQMEventAgrs.cs
Normal file
23
RRQMCore/Event/RRQMEventAgrs.cs
Normal file
@@ -0,0 +1,23 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权(除特别声明或在RRQMCore.XREF命名空间的代码)归作者本人若汝棋茗所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权
|
||||
// CSDN博客:https://blog.csdn.net/qq_40374647
|
||||
// 哔哩哔哩视频:https://space.bilibili.com/94253567
|
||||
// Gitee源代码仓库:https://gitee.com/RRQM_Home
|
||||
// Github源代码仓库:https://github.com/RRQM
|
||||
// 交流QQ群:234762506
|
||||
// 感谢您的下载和使用
|
||||
//------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
using System;
|
||||
|
||||
namespace RRQMCore.Event
|
||||
{
|
||||
/// <summary>
|
||||
/// 若汝棋茗所有事件基类
|
||||
/// </summary>
|
||||
public class RRQMEventArgs : EventArgs
|
||||
{
|
||||
}
|
||||
}
|
||||
45
RRQMCore/Exceptions/ErrorExceptionMapping.cs
Normal file
45
RRQMCore/Exceptions/ErrorExceptionMapping.cs
Normal file
@@ -0,0 +1,45 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权(除特别声明或在RRQMCore.XREF命名空间的代码)归作者本人若汝棋茗所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权
|
||||
// CSDN博客:https://blog.csdn.net/qq_40374647
|
||||
// 哔哩哔哩视频:https://space.bilibili.com/94253567
|
||||
// Gitee源代码仓库:https://gitee.com/RRQM_Home
|
||||
// Github源代码仓库:https://github.com/RRQM
|
||||
// 交流QQ群:234762506
|
||||
// 感谢您的下载和使用
|
||||
//------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace RRQMCore.Exceptions
|
||||
{
|
||||
/// <summary>
|
||||
/// 错误异常映射表
|
||||
/// </summary>
|
||||
public class ErrorExceptionMapping
|
||||
{
|
||||
private Dictionary<byte, string> codeInfo = new Dictionary<byte, string>();
|
||||
|
||||
/// <summary>
|
||||
/// 注册错误码信息
|
||||
/// </summary>
|
||||
/// <param name="code"></param>
|
||||
/// <param name="info"></param>
|
||||
public void RegisterCode(byte code, string info)
|
||||
{
|
||||
codeInfo.Add(code, info);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取代码信息
|
||||
/// </summary>
|
||||
/// <param name="code"></param>
|
||||
/// <returns></returns>
|
||||
public string GetCodeInfo(byte code)
|
||||
{
|
||||
string info;
|
||||
codeInfo.TryGetValue(code, out info);
|
||||
return info;
|
||||
}
|
||||
}
|
||||
}
|
||||
34
RRQMCore/Exceptions/MessageNotFoundException.cs
Normal file
34
RRQMCore/Exceptions/MessageNotFoundException.cs
Normal file
@@ -0,0 +1,34 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权(除特别声明或在RRQMCore.XREF命名空间的代码)归作者本人若汝棋茗所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权
|
||||
// CSDN博客:https://blog.csdn.net/qq_40374647
|
||||
// 哔哩哔哩视频:https://space.bilibili.com/94253567
|
||||
// Gitee源代码仓库:https://gitee.com/RRQM_Home
|
||||
// Github源代码仓库:https://github.com/RRQM
|
||||
// 交流QQ群:234762506
|
||||
// 感谢您的下载和使用
|
||||
//------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------
|
||||
using System;
|
||||
|
||||
namespace RRQMCore.Exceptions
|
||||
{
|
||||
/*
|
||||
若汝棋茗
|
||||
*/
|
||||
|
||||
/// <summary>
|
||||
/// 未找到消息异常类
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public class MessageNotFoundException : RRQMException
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="mes"></param>
|
||||
public MessageNotFoundException(string mes) : base(mes)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
34
RRQMCore/Exceptions/MessageRegisteredException.cs
Normal file
34
RRQMCore/Exceptions/MessageRegisteredException.cs
Normal file
@@ -0,0 +1,34 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权(除特别声明或在RRQMCore.XREF命名空间的代码)归作者本人若汝棋茗所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权
|
||||
// CSDN博客:https://blog.csdn.net/qq_40374647
|
||||
// 哔哩哔哩视频:https://space.bilibili.com/94253567
|
||||
// Gitee源代码仓库:https://gitee.com/RRQM_Home
|
||||
// Github源代码仓库:https://github.com/RRQM
|
||||
// 交流QQ群:234762506
|
||||
// 感谢您的下载和使用
|
||||
//------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------
|
||||
using System;
|
||||
|
||||
namespace RRQMCore.Exceptions
|
||||
{
|
||||
/*
|
||||
若汝棋茗
|
||||
*/
|
||||
|
||||
/// <summary>
|
||||
/// 消息已注册
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public class MessageRegisteredException : RRQMException
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="mes"></param>
|
||||
public MessageRegisteredException(string mes) : base(mes)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
48
RRQMCore/Exceptions/RRQMException.cs
Normal file
48
RRQMCore/Exceptions/RRQMException.cs
Normal file
@@ -0,0 +1,48 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权(除特别声明或在RRQMCore.XREF命名空间的代码)归作者本人若汝棋茗所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权
|
||||
// CSDN博客:https://blog.csdn.net/qq_40374647
|
||||
// 哔哩哔哩视频:https://space.bilibili.com/94253567
|
||||
// Gitee源代码仓库:https://gitee.com/RRQM_Home
|
||||
// Github源代码仓库:https://github.com/RRQM
|
||||
// 交流QQ群:234762506
|
||||
// 感谢您的下载和使用
|
||||
//------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------
|
||||
using System;
|
||||
|
||||
namespace RRQMCore.Exceptions
|
||||
{
|
||||
/// <summary>
|
||||
/// 若汝棋茗程序集异常类基类
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public class RRQMException : Exception
|
||||
{
|
||||
/// <summary>
|
||||
/// 构造函数
|
||||
/// </summary>
|
||||
public RRQMException() : base() { }
|
||||
|
||||
/// <summary>
|
||||
/// 构造函数
|
||||
/// </summary>
|
||||
/// <param name="message"></param>
|
||||
public RRQMException(string message) : base(message) { }
|
||||
|
||||
/// <summary>
|
||||
/// 构造函数
|
||||
/// </summary>
|
||||
/// <param name="message"></param>
|
||||
/// <param name="inner"></param>
|
||||
public RRQMException(string message, System.Exception inner) : base(message, inner) { }
|
||||
|
||||
/// <summary>
|
||||
/// 构造函数
|
||||
/// </summary>
|
||||
/// <param name="info"></param>
|
||||
/// <param name="context"></param>
|
||||
protected RRQMException(System.Runtime.Serialization.SerializationInfo info,
|
||||
System.Runtime.Serialization.StreamingContext context) : base(info, context) { }
|
||||
}
|
||||
}
|
||||
47
RRQMCore/Extensions/Tools/NetTools .cs
Normal file
47
RRQMCore/Extensions/Tools/NetTools .cs
Normal file
@@ -0,0 +1,47 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权(除特别声明或在RRQMCore.XREF命名空间的代码)归作者本人若汝棋茗所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权
|
||||
// CSDN博客:https://blog.csdn.net/qq_40374647
|
||||
// 哔哩哔哩视频:https://space.bilibili.com/94253567
|
||||
// Gitee源代码仓库:https://gitee.com/RRQM_Home
|
||||
// Github源代码仓库:https://github.com/RRQM
|
||||
// 交流QQ群:234762506
|
||||
// 感谢您的下载和使用
|
||||
//------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Net.NetworkInformation;
|
||||
|
||||
namespace RRQMCore.Extensions.Tools
|
||||
{
|
||||
/// <summary>
|
||||
/// 网络工具
|
||||
/// </summary>
|
||||
public static class NetTools
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取MAC地址
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static string[] GetMacByNetworkInterface()
|
||||
{
|
||||
try
|
||||
{
|
||||
NetworkInterface[] interfaces = NetworkInterface.GetAllNetworkInterfaces();
|
||||
|
||||
List<string> mac = new List<string>();
|
||||
|
||||
foreach (NetworkInterface ni in interfaces)
|
||||
{
|
||||
mac.Add(BitConverter.ToString(ni.GetPhysicalAddress().GetAddressBytes()));
|
||||
}
|
||||
return mac.ToArray();
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
}
|
||||
return new string[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
34
RRQMCore/Helper/ByteBlockHelper.cs
Normal file
34
RRQMCore/Helper/ByteBlockHelper.cs
Normal file
@@ -0,0 +1,34 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权(除特别声明或在RRQMCore.XREF命名空间的代码)归作者本人若汝棋茗所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权
|
||||
// CSDN博客:https://blog.csdn.net/qq_40374647
|
||||
// 哔哩哔哩视频:https://space.bilibili.com/94253567
|
||||
// Gitee源代码仓库:https://gitee.com/RRQM_Home
|
||||
// Github源代码仓库:https://github.com/RRQM
|
||||
// 交流QQ群:234762506
|
||||
// 感谢您的下载和使用
|
||||
//------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------
|
||||
using RRQMCore.ByteManager;
|
||||
using System.Text;
|
||||
|
||||
namespace RRQMCore.Helper
|
||||
{
|
||||
/// <summary>
|
||||
/// 字节块扩展
|
||||
/// </summary>
|
||||
public static class ByteBlockHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// 转utf-8字符串
|
||||
/// </summary>
|
||||
/// <param name="byteBlock"></param>
|
||||
/// <param name="offset"></param>
|
||||
/// <param name="length"></param>
|
||||
/// <returns></returns>
|
||||
public static string ToUtf8String(this ByteBlock byteBlock, int offset, int length)
|
||||
{
|
||||
return Encoding.UTF8.GetString(byteBlock.Buffer, offset, length);
|
||||
}
|
||||
}
|
||||
}
|
||||
91
RRQMCore/Helper/ByteHelper.cs
Normal file
91
RRQMCore/Helper/ByteHelper.cs
Normal file
@@ -0,0 +1,91 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权(除特别声明或在RRQMCore.XREF命名空间的代码)归作者本人若汝棋茗所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权
|
||||
// CSDN博客:https://blog.csdn.net/qq_40374647
|
||||
// 哔哩哔哩视频:https://space.bilibili.com/94253567
|
||||
// Gitee源代码仓库:https://gitee.com/RRQM_Home
|
||||
// Github源代码仓库:https://github.com/RRQM
|
||||
// 交流QQ群:234762506
|
||||
// 感谢您的下载和使用
|
||||
//------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace RRQMCore.Helper
|
||||
{
|
||||
/// <summary>
|
||||
/// Byte辅助扩展类
|
||||
/// </summary>
|
||||
public static class ByteHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取字节中的指定Bit的值
|
||||
/// </summary>
|
||||
/// <param name="this">字节</param>
|
||||
/// <param name="index">Bit的索引值(0-7)</param>
|
||||
/// <returns></returns>
|
||||
public static int GetBit(this byte @this, short index)
|
||||
{
|
||||
byte x = 1;
|
||||
switch (index)
|
||||
{
|
||||
case 0: { x = 0x01; } break;
|
||||
case 1: { x = 0x02; } break;
|
||||
case 2: { x = 0x04; } break;
|
||||
case 3: { x = 0x08; } break;
|
||||
case 4: { x = 0x10; } break;
|
||||
case 5: { x = 0x20; } break;
|
||||
case 6: { x = 0x40; } break;
|
||||
case 7: { x = 0x80; } break;
|
||||
default: { return 0; }
|
||||
}
|
||||
return (@this & x) == x ? 1 : 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置字节中的指定Bit的值
|
||||
/// </summary>
|
||||
/// <param name="this">字节</param>
|
||||
/// <param name="index">Bit的索引值(0-7)</param>
|
||||
/// <param name="bitvalue">Bit值(0,1)</param>
|
||||
/// <returns></returns>
|
||||
public static byte SetBit(this byte @this, short index, int bitvalue)
|
||||
{
|
||||
var _byte = @this;
|
||||
if (bitvalue == 1)
|
||||
{
|
||||
switch (index)
|
||||
{
|
||||
case 0: { return _byte |= 0x01; }
|
||||
case 1: { return _byte |= 0x02; }
|
||||
case 2: { return _byte |= 0x04; }
|
||||
case 3: { return _byte |= 0x08; }
|
||||
case 4: { return _byte |= 0x10; }
|
||||
case 5: { return _byte |= 0x20; }
|
||||
case 6: { return _byte |= 0x40; }
|
||||
case 7: { return _byte |= 0x80; }
|
||||
default: { return _byte; }
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (index)
|
||||
{
|
||||
case 0: { return _byte &= 0xFE; }
|
||||
case 1: { return _byte &= 0xFD; }
|
||||
case 2: { return _byte &= 0xFB; }
|
||||
case 3: { return _byte &= 0xF7; }
|
||||
case 4: { return _byte &= 0xEF; }
|
||||
case 5: { return _byte &= 0xDF; }
|
||||
case 6: { return _byte &= 0xBF; }
|
||||
case 7: { return _byte &= 0x7F; }
|
||||
default: { return _byte; }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
105
RRQMCore/Helper/BytesHelper.cs
Normal file
105
RRQMCore/Helper/BytesHelper.cs
Normal file
@@ -0,0 +1,105 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权(除特别声明或在RRQMCore.XREF命名空间的代码)归作者本人若汝棋茗所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权
|
||||
// CSDN博客:https://blog.csdn.net/qq_40374647
|
||||
// 哔哩哔哩视频:https://space.bilibili.com/94253567
|
||||
// Gitee源代码仓库:https://gitee.com/RRQM_Home
|
||||
// Github源代码仓库:https://github.com/RRQM
|
||||
// 交流QQ群:234762506
|
||||
// 感谢您的下载和使用
|
||||
//------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace RRQMCore.Helper
|
||||
{
|
||||
/// <summary>
|
||||
/// 字节数组扩展类
|
||||
/// </summary>
|
||||
public static class BytesHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// 索引包含数组
|
||||
/// </summary>
|
||||
/// <param name="srcByteArray"></param>
|
||||
/// <param name="offset"></param>
|
||||
/// <param name="length"></param>
|
||||
/// <param name="subByteArray"></param>
|
||||
/// <returns></returns>
|
||||
public static List<int> IndexOfInclude(this byte[] srcByteArray, int offset, int length, byte[] subByteArray)
|
||||
{
|
||||
int subByteArrayLen = subByteArray.Length;
|
||||
List<int> indexes = new List<int>();
|
||||
if (length < subByteArrayLen)
|
||||
{
|
||||
return indexes;
|
||||
}
|
||||
int hitLength = 0;
|
||||
for (int i = offset; i < length; i++)
|
||||
{
|
||||
if (srcByteArray[i] == subByteArray[hitLength])
|
||||
{
|
||||
hitLength++;
|
||||
}
|
||||
else
|
||||
{
|
||||
hitLength = 0;
|
||||
}
|
||||
|
||||
if (hitLength == subByteArray.Length)
|
||||
{
|
||||
hitLength = 0;
|
||||
indexes.Add(i);
|
||||
}
|
||||
}
|
||||
|
||||
return indexes;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 索引第一个包含数组
|
||||
/// </summary>
|
||||
/// <param name="srcByteArray"></param>
|
||||
/// <param name="offset"></param>
|
||||
/// <param name="length"></param>
|
||||
/// <param name="subByteArray"></param>
|
||||
/// <returns></returns>
|
||||
public static int IndexOfFirst(this byte[] srcByteArray, int offset, int length, byte[] subByteArray)
|
||||
{
|
||||
if (length < subByteArray.Length)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
int hitLength = 0;
|
||||
for (int i = offset; i < length; i++)
|
||||
{
|
||||
if (srcByteArray[i] == subByteArray[hitLength])
|
||||
{
|
||||
hitLength++;
|
||||
}
|
||||
else
|
||||
{
|
||||
hitLength = 0;
|
||||
}
|
||||
|
||||
if (hitLength == subByteArray.Length)
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 转Base64。
|
||||
/// </summary>
|
||||
/// <param name="data"></param>
|
||||
/// <returns></returns>
|
||||
public static string ToBase64(this byte[] data)
|
||||
{
|
||||
return Convert.ToBase64String(data);
|
||||
}
|
||||
}
|
||||
}
|
||||
37
RRQMCore/Helper/CollectionsHelper.cs
Normal file
37
RRQMCore/Helper/CollectionsHelper.cs
Normal file
@@ -0,0 +1,37 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权(除特别声明或在RRQMCore.XREF命名空间的代码)归作者本人若汝棋茗所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权
|
||||
// CSDN博客:https://blog.csdn.net/qq_40374647
|
||||
// 哔哩哔哩视频:https://space.bilibili.com/94253567
|
||||
// Gitee源代码仓库:https://gitee.com/RRQM_Home
|
||||
// Github源代码仓库:https://github.com/RRQM
|
||||
// 交流QQ群:234762506
|
||||
// 感谢您的下载和使用
|
||||
//------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------
|
||||
using System.Collections.Concurrent;
|
||||
|
||||
namespace RRQMCore.Helper
|
||||
{
|
||||
/// <summary>
|
||||
/// 集合助手
|
||||
/// </summary>
|
||||
public static class CollectionsHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// 清除所有成员
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="queue"></param>
|
||||
public static void Clear<T>(this ConcurrentQueue<T> queue)
|
||||
{
|
||||
#if NETCOREAPP3_1_OR_GREATER
|
||||
queue.Clear();
|
||||
#else
|
||||
while (queue.TryDequeue(out _))
|
||||
{
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
33
RRQMCore/Helper/DateTimeHelper.cs
Normal file
33
RRQMCore/Helper/DateTimeHelper.cs
Normal file
@@ -0,0 +1,33 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权(除特别声明或在RRQMCore.XREF命名空间的代码)归作者本人若汝棋茗所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权
|
||||
// CSDN博客:https://blog.csdn.net/qq_40374647
|
||||
// 哔哩哔哩视频:https://space.bilibili.com/94253567
|
||||
// Gitee源代码仓库:https://gitee.com/RRQM_Home
|
||||
// Github源代码仓库:https://github.com/RRQM
|
||||
// 交流QQ群:234762506
|
||||
// 感谢您的下载和使用
|
||||
//------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------
|
||||
using System;
|
||||
using System.Globalization;
|
||||
|
||||
namespace RRQMCore.Helper
|
||||
{
|
||||
/// <summary>
|
||||
/// 日期扩展
|
||||
/// </summary>
|
||||
public static class DateTimeHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// 格林尼治标准时间
|
||||
/// </summary>
|
||||
/// <param name="dt"></param>
|
||||
/// <param name="v"></param>
|
||||
/// <returns></returns>
|
||||
public static string ToGMTString(this DateTime dt, string v)
|
||||
{
|
||||
return dt.ToString("r", CultureInfo.InvariantCulture);
|
||||
}
|
||||
}
|
||||
}
|
||||
38
RRQMCore/Helper/EnumHelper.cs
Normal file
38
RRQMCore/Helper/EnumHelper.cs
Normal file
@@ -0,0 +1,38 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权(除特别声明或在RRQMCore.XREF命名空间的代码)归作者本人若汝棋茗所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权
|
||||
// CSDN博客:https://blog.csdn.net/qq_40374647
|
||||
// 哔哩哔哩视频:https://space.bilibili.com/94253567
|
||||
// Gitee源代码仓库:https://gitee.com/RRQM_Home
|
||||
// Github源代码仓库:https://github.com/RRQM
|
||||
// 交流QQ群:234762506
|
||||
// 感谢您的下载和使用
|
||||
//------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------
|
||||
using System;
|
||||
using System.Reflection;
|
||||
|
||||
namespace RRQMCore.Helper
|
||||
{
|
||||
/// <summary>
|
||||
/// 枚举
|
||||
/// </summary>
|
||||
public static class EnumHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取自定义attribute
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="enumObj"></param>
|
||||
/// <returns></returns>
|
||||
public static T GetAttribute<T>(this Enum enumObj) where T : Attribute
|
||||
{
|
||||
Type type = enumObj.GetType();
|
||||
Attribute attr = null;
|
||||
string enumName = Enum.GetName(type, enumObj); //获取对应的枚举名
|
||||
FieldInfo field = type.GetField(enumName);
|
||||
attr = field.GetCustomAttribute(typeof(T), false);
|
||||
return (T)attr;
|
||||
}
|
||||
}
|
||||
}
|
||||
35
RRQMCore/Helper/SerializationHelper.cs
Normal file
35
RRQMCore/Helper/SerializationHelper.cs
Normal file
@@ -0,0 +1,35 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权(除特别声明或在RRQMCore.XREF命名空间的代码)归作者本人若汝棋茗所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权
|
||||
// CSDN博客:https://blog.csdn.net/qq_40374647
|
||||
// 哔哩哔哩视频:https://space.bilibili.com/94253567
|
||||
// Gitee源代码仓库:https://gitee.com/RRQM_Home
|
||||
// Github源代码仓库:https://github.com/RRQM
|
||||
// 交流QQ群:234762506
|
||||
// 感谢您的下载和使用
|
||||
//------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------
|
||||
using RRQMCore.ByteManager;
|
||||
using RRQMCore.Serialization;
|
||||
|
||||
namespace RRQMCore.Helper
|
||||
{
|
||||
/// <summary>
|
||||
/// 序列化辅助
|
||||
/// </summary>
|
||||
public static class SerializationHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// 序列化成数据
|
||||
/// </summary>
|
||||
/// <param name="obj"></param>
|
||||
/// <param name="serializationType"></param>
|
||||
/// <returns></returns>
|
||||
public static byte[] ToBytes(this object obj, SerializationType serializationType = SerializationType.RRQMBinary)
|
||||
{
|
||||
ByteBlock byteBlock = new ByteBlock(1024 * 10);
|
||||
byteBlock.WriteObject(obj, serializationType);
|
||||
return byteBlock.ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
150
RRQMCore/Helper/StringHelper.cs
Normal file
150
RRQMCore/Helper/StringHelper.cs
Normal file
@@ -0,0 +1,150 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权(除特别声明或在RRQMCore.XREF命名空间的代码)归作者本人若汝棋茗所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权
|
||||
// CSDN博客:https://blog.csdn.net/qq_40374647
|
||||
// 哔哩哔哩视频:https://space.bilibili.com/94253567
|
||||
// Gitee源代码仓库:https://gitee.com/RRQM_Home
|
||||
// Github源代码仓库:https://github.com/RRQM
|
||||
// 交流QQ群:234762506
|
||||
// 感谢您的下载和使用
|
||||
//------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace RRQMCore.Helper
|
||||
{
|
||||
/// <summary>
|
||||
/// 字符串扩展
|
||||
/// </summary>
|
||||
public static class StringHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// 只按第一个匹配项分割
|
||||
/// </summary>
|
||||
/// <param name="str"></param>
|
||||
/// <param name="split"></param>
|
||||
/// <returns></returns>
|
||||
public static string[] SplitFirst(this string str, char split)
|
||||
{
|
||||
List<string> s = new List<string>();
|
||||
int index = str.IndexOf(split);
|
||||
if (index > 0)
|
||||
{
|
||||
s.Add(str.Substring(0, index).Trim());
|
||||
s.Add(str.Substring(index + 1, str.Length - index - 1).Trim());
|
||||
}
|
||||
|
||||
return s.ToArray();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 按字符串分割
|
||||
/// </summary>
|
||||
/// <param name="str"></param>
|
||||
/// <param name="pattern"></param>
|
||||
/// <returns></returns>
|
||||
public static string[] Split(this string str, string pattern)
|
||||
{
|
||||
return Regex.Split(str, pattern);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 只按最后一个匹配项分割
|
||||
/// </summary>
|
||||
/// <param name="str"></param>
|
||||
/// <param name="split"></param>
|
||||
/// <returns></returns>
|
||||
public static string[] SplitLast(this string str, char split)
|
||||
{
|
||||
List<string> s = new List<string>();
|
||||
int index = str.LastIndexOf(split);
|
||||
if (index > 0)
|
||||
{
|
||||
s.Add(str.Substring(0, index).Trim());
|
||||
s.Add(str.Substring(index + 1, str.Length - index - 1).Trim());
|
||||
}
|
||||
|
||||
return s.ToArray();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将字符串转换为指定类型
|
||||
/// </summary>
|
||||
/// <param name="str"></param>
|
||||
/// <param name="type"></param>
|
||||
/// <returns></returns>
|
||||
public static object ParseToType(this string str, Type type)
|
||||
{
|
||||
dynamic obj = null;
|
||||
if (type == RRQMReadonly.stringType)
|
||||
{
|
||||
obj = str;
|
||||
}
|
||||
else if (type == RRQMReadonly.byteType)
|
||||
{
|
||||
obj = byte.Parse(str);
|
||||
}
|
||||
else if (type == RRQMReadonly.boolType)
|
||||
{
|
||||
obj = bool.Parse(str);
|
||||
}
|
||||
else if (type == RRQMReadonly.shortType)
|
||||
{
|
||||
obj = short.Parse(str);
|
||||
}
|
||||
else if (type == RRQMReadonly.intType)
|
||||
{
|
||||
obj = int.Parse(str);
|
||||
}
|
||||
else if (type == RRQMReadonly.longType)
|
||||
{
|
||||
obj = long.Parse(str);
|
||||
}
|
||||
else if (type == RRQMReadonly.floatType)
|
||||
{
|
||||
obj = float.Parse(str);
|
||||
}
|
||||
else if (type == RRQMReadonly.doubleType)
|
||||
{
|
||||
obj = double.Parse(str);
|
||||
}
|
||||
else if (type == RRQMReadonly.decimalType)
|
||||
{
|
||||
obj = decimal.Parse(str);
|
||||
}
|
||||
else if (type == RRQMReadonly.dateTimeType)
|
||||
{
|
||||
obj = DateTime.Parse(str);
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 按格式填充
|
||||
/// </summary>
|
||||
/// <param name="str"></param>
|
||||
/// <param name="ps"></param>
|
||||
/// <returns></returns>
|
||||
public static string Format(this string str, params object[] ps)
|
||||
{
|
||||
return string.Format(str, ps);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 转换为SHA1。
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
/// <param name="encoding"></param>
|
||||
/// <returns></returns>
|
||||
public static byte[] ToSha1(this string value, Encoding encoding)
|
||||
{
|
||||
SHA1 sha1 = new SHA1CryptoServiceProvider();
|
||||
return sha1.ComputeHash(encoding.GetBytes(value));
|
||||
}
|
||||
}
|
||||
}
|
||||
76
RRQMCore/Helper/TypeHelper.cs
Normal file
76
RRQMCore/Helper/TypeHelper.cs
Normal file
@@ -0,0 +1,76 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权(除特别声明或在RRQMCore.XREF命名空间的代码)归作者本人若汝棋茗所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权
|
||||
// CSDN博客:https://blog.csdn.net/qq_40374647
|
||||
// 哔哩哔哩视频:https://space.bilibili.com/94253567
|
||||
// Gitee源代码仓库:https://gitee.com/RRQM_Home
|
||||
// Github源代码仓库:https://github.com/RRQM
|
||||
// 交流QQ群:234762506
|
||||
// 感谢您的下载和使用
|
||||
//------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------
|
||||
using RRQMCore.Exceptions;
|
||||
using System;
|
||||
using System.Reflection;
|
||||
|
||||
namespace RRQMCore.Helper
|
||||
{
|
||||
/// <summary>
|
||||
/// Type扩展累类
|
||||
/// </summary>
|
||||
public static class TypeHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取类型
|
||||
/// </summary>
|
||||
/// <param name="type"></param>
|
||||
/// <returns></returns>
|
||||
public static Type GetRefOutType(this Type type)
|
||||
{
|
||||
if (type.FullName.Contains("&"))
|
||||
{
|
||||
string typeName = type.FullName.Replace("&", string.Empty);
|
||||
Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
|
||||
foreach (var assembly in assemblies)
|
||||
{
|
||||
type = assembly.GetType(typeName);
|
||||
|
||||
if (type != null)
|
||||
{
|
||||
return type;
|
||||
}
|
||||
}
|
||||
|
||||
throw new RRQMException($"未能识别类型{typeName}");
|
||||
}
|
||||
else
|
||||
{
|
||||
return type;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取默认值
|
||||
/// </summary>
|
||||
/// <param name="targetType"></param>
|
||||
/// <returns></returns>
|
||||
public static object GetDefault(this Type targetType)
|
||||
{
|
||||
return targetType.IsValueType ? Activator.CreateInstance(targetType) : null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 判断为结构体
|
||||
/// </summary>
|
||||
/// <param name="targetType"></param>
|
||||
/// <returns></returns>
|
||||
public static bool IsStruct(this Type targetType)
|
||||
{
|
||||
if (!targetType.IsPrimitive && !targetType.IsClass && !targetType.IsEnum && targetType.IsValueType)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
146
RRQMCore/IO/FileControler.cs
Normal file
146
RRQMCore/IO/FileControler.cs
Normal file
@@ -0,0 +1,146 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权(除特别声明或在RRQMCore.XREF命名空间的代码)归作者本人若汝棋茗所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权
|
||||
// CSDN博客:https://blog.csdn.net/qq_40374647
|
||||
// 哔哩哔哩视频:https://space.bilibili.com/94253567
|
||||
// Gitee源代码仓库:https://gitee.com/RRQM_Home
|
||||
// Github源代码仓库:https://github.com/RRQM
|
||||
// 交流QQ群:234762506
|
||||
// 感谢您的下载和使用
|
||||
//------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security.Cryptography;
|
||||
|
||||
namespace RRQMCore.IO
|
||||
{
|
||||
/// <summary>
|
||||
/// 文件操作
|
||||
/// </summary>
|
||||
public static class FileControler
|
||||
{
|
||||
/// <summary>
|
||||
/// 获得文件Hash值
|
||||
/// </summary>
|
||||
/// <param name="filePath">文件路径</param>
|
||||
/// <returns></returns>
|
||||
public static string GetFileHash(string filePath)
|
||||
{
|
||||
try
|
||||
{
|
||||
HashAlgorithm hash = SHA256.Create();
|
||||
using (FileStream fileStream = File.OpenRead(filePath))
|
||||
{
|
||||
byte[] HashValue = hash.ComputeHash(fileStream);
|
||||
return BitConverter.ToString(HashValue).Replace("-", "");
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获得流Hash值
|
||||
/// </summary>
|
||||
/// <param name="stream"></param>
|
||||
/// <returns></returns>
|
||||
public static string GetStreamHash(Stream stream)
|
||||
{
|
||||
try
|
||||
{
|
||||
HashAlgorithm hash = SHA256.Create();
|
||||
byte[] HashValue = hash.ComputeHash(stream);
|
||||
return BitConverter.ToString(HashValue).Replace("-", "");
|
||||
}
|
||||
catch
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获得文件Hash值
|
||||
/// </summary>
|
||||
/// <param name="filePath">文件路径</param>
|
||||
/// <param name="hash"></param>
|
||||
/// <returns></returns>
|
||||
public static string GetFileHash(string filePath, HashAlgorithm hash)
|
||||
{
|
||||
try
|
||||
{
|
||||
using (FileStream fileStream = File.OpenRead(filePath))
|
||||
{
|
||||
byte[] HashValue = hash.ComputeHash(fileStream);
|
||||
return BitConverter.ToString(HashValue).Replace("-", "");
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获得流Hash值
|
||||
/// </summary>
|
||||
/// <param name="stream"></param>
|
||||
/// <param name="hash"></param>
|
||||
/// <returns></returns>
|
||||
public static string GetStreamHash(Stream stream, HashAlgorithm hash)
|
||||
{
|
||||
try
|
||||
{
|
||||
byte[] HashValue = hash.ComputeHash(stream);
|
||||
return BitConverter.ToString(HashValue).Replace("-", "");
|
||||
}
|
||||
catch
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
# if NET45_OR_GREATER
|
||||
|
||||
[DllImport("kernel32.dll")]
|
||||
private static extern IntPtr _lopen(string lpPathName, int iReadWrite);
|
||||
|
||||
[DllImport("kernel32.dll")]
|
||||
private static extern bool CloseHandle(IntPtr hObject);
|
||||
|
||||
private const int OF_READWRITE = 2;
|
||||
|
||||
private const int OF_SHARE_DENY_NONE = 0x40;
|
||||
|
||||
private static readonly IntPtr HFILE_ERROR = new IntPtr(-1);
|
||||
|
||||
/// <summary>
|
||||
/// 判断文件是否被已打开
|
||||
/// </summary>
|
||||
/// <param name="fileFullName"></param>
|
||||
/// <returns></returns>
|
||||
public static bool FileIsOpen(string fileFullName)
|
||||
{
|
||||
if (!File.Exists(fileFullName))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
IntPtr handle = _lopen(fileFullName, OF_READWRITE | OF_SHARE_DENY_NONE);
|
||||
|
||||
if (handle == HFILE_ERROR)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
CloseHandle(handle);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
}
|
||||
39
RRQMCore/Logger/ILog.cs
Normal file
39
RRQMCore/Logger/ILog.cs
Normal file
@@ -0,0 +1,39 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权(除特别声明或在RRQMCore.XREF命名空间的代码)归作者本人若汝棋茗所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权
|
||||
// CSDN博客:https://blog.csdn.net/qq_40374647
|
||||
// 哔哩哔哩视频:https://space.bilibili.com/94253567
|
||||
// Gitee源代码仓库:https://gitee.com/RRQM_Home
|
||||
// Github源代码仓库:https://github.com/RRQM
|
||||
// 交流QQ群:234762506
|
||||
// 感谢您的下载和使用
|
||||
//------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
using System;
|
||||
|
||||
namespace RRQMCore.Log
|
||||
{
|
||||
/// <summary>
|
||||
/// 日志接口
|
||||
/// </summary>
|
||||
public interface ILog
|
||||
{
|
||||
/// <summary>
|
||||
/// 日志记录
|
||||
/// </summary>
|
||||
/// <param name="logType"></param>
|
||||
/// <param name="source"></param>
|
||||
/// <param name="message"></param>
|
||||
/// <param name="exception"></param>
|
||||
void Debug(LogType logType, object source, string message, Exception exception);
|
||||
|
||||
/// <summary>
|
||||
/// 日志记录
|
||||
/// </summary>
|
||||
/// <param name="logType"></param>
|
||||
/// <param name="source"></param>
|
||||
/// <param name="message"></param>
|
||||
void Debug(LogType logType, object source, string message);
|
||||
}
|
||||
}
|
||||
35
RRQMCore/Logger/LogType.cs
Normal file
35
RRQMCore/Logger/LogType.cs
Normal file
@@ -0,0 +1,35 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权(除特别声明或在RRQMCore.XREF命名空间的代码)归作者本人若汝棋茗所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权
|
||||
// CSDN博客:https://blog.csdn.net/qq_40374647
|
||||
// 哔哩哔哩视频:https://space.bilibili.com/94253567
|
||||
// Gitee源代码仓库:https://gitee.com/RRQM_Home
|
||||
// Github源代码仓库:https://github.com/RRQM
|
||||
// 交流QQ群:234762506
|
||||
// 感谢您的下载和使用
|
||||
//------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace RRQMCore.Log
|
||||
{
|
||||
/// <summary>
|
||||
/// 日志类型
|
||||
/// </summary>
|
||||
public enum LogType
|
||||
{
|
||||
/// <summary>
|
||||
/// 一般消息
|
||||
/// </summary>
|
||||
Message,
|
||||
|
||||
/// <summary>
|
||||
/// 警示消息
|
||||
/// </summary>
|
||||
Warning,
|
||||
|
||||
/// <summary>
|
||||
/// 错误消息
|
||||
/// </summary>
|
||||
Error
|
||||
}
|
||||
}
|
||||
31
RRQMCore/Pool/ObjectPool/IObjectPool.cs
Normal file
31
RRQMCore/Pool/ObjectPool/IObjectPool.cs
Normal file
@@ -0,0 +1,31 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权(除特别声明或在RRQMCore.XREF命名空间的代码)归作者本人若汝棋茗所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权
|
||||
// CSDN博客:https://blog.csdn.net/qq_40374647
|
||||
// 哔哩哔哩视频:https://space.bilibili.com/94253567
|
||||
// Gitee源代码仓库:https://gitee.com/RRQM_Home
|
||||
// Github源代码仓库:https://github.com/RRQM
|
||||
// 交流QQ群:234762506
|
||||
// 感谢您的下载和使用
|
||||
//------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------
|
||||
using System;
|
||||
|
||||
namespace RRQMCore.Pool
|
||||
{
|
||||
/// <summary>
|
||||
/// 对象池接口
|
||||
/// </summary>
|
||||
public interface IObjectPool : IDisposable
|
||||
{
|
||||
/// <summary>
|
||||
/// 可使用数量
|
||||
/// </summary>
|
||||
int FreeSize { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 清空池中对象
|
||||
/// </summary>
|
||||
void Clear();
|
||||
}
|
||||
}
|
||||
40
RRQMCore/Pool/ObjectPool/IPoolObject.cs
Normal file
40
RRQMCore/Pool/ObjectPool/IPoolObject.cs
Normal file
@@ -0,0 +1,40 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权(除特别声明或在RRQMCore.XREF命名空间的代码)归作者本人若汝棋茗所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权
|
||||
// CSDN博客:https://blog.csdn.net/qq_40374647
|
||||
// 哔哩哔哩视频:https://space.bilibili.com/94253567
|
||||
// Gitee源代码仓库:https://gitee.com/RRQM_Home
|
||||
// Github源代码仓库:https://github.com/RRQM
|
||||
// 交流QQ群:234762506
|
||||
// 感谢您的下载和使用
|
||||
//------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace RRQMCore.Pool
|
||||
{
|
||||
/// <summary>
|
||||
/// 对象池单位接口
|
||||
/// </summary>
|
||||
public interface IPoolObject
|
||||
{
|
||||
/// <summary>
|
||||
/// 是否为新建对象
|
||||
/// </summary>
|
||||
bool NewCreate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 初创建对象
|
||||
/// </summary>
|
||||
void Create();
|
||||
|
||||
/// <summary>
|
||||
/// 重新创建对象
|
||||
/// </summary>
|
||||
void Recreate();
|
||||
|
||||
/// <summary>
|
||||
/// 销毁对象
|
||||
/// </summary>
|
||||
void Destroy();
|
||||
}
|
||||
}
|
||||
147
RRQMCore/Pool/ObjectPool/ObjectPool.cs
Normal file
147
RRQMCore/Pool/ObjectPool/ObjectPool.cs
Normal file
@@ -0,0 +1,147 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权(除特别声明或在RRQMCore.XREF命名空间的代码)归作者本人若汝棋茗所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权
|
||||
// CSDN博客:https://blog.csdn.net/qq_40374647
|
||||
// 哔哩哔哩视频:https://space.bilibili.com/94253567
|
||||
// Gitee源代码仓库:https://gitee.com/RRQM_Home
|
||||
// Github源代码仓库:https://github.com/RRQM
|
||||
// 交流QQ群:234762506
|
||||
// 感谢您的下载和使用
|
||||
//------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
|
||||
namespace RRQMCore.Pool
|
||||
{
|
||||
/// <summary>
|
||||
/// 对象池
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
public class ObjectPool<T> : IObjectPool where T : IPoolObject
|
||||
{
|
||||
/// <summary>
|
||||
/// 构造函数
|
||||
/// </summary>
|
||||
/// <param name="capacity"></param>
|
||||
public ObjectPool(int capacity)
|
||||
{
|
||||
this.Capacity = capacity;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 构造函数
|
||||
/// </summary>
|
||||
public ObjectPool()
|
||||
{
|
||||
}
|
||||
|
||||
private ConcurrentQueue<T> queue = new ConcurrentQueue<T>();
|
||||
|
||||
private bool autoCreate = true;
|
||||
|
||||
/// <summary>
|
||||
/// 是否自动生成
|
||||
/// </summary>
|
||||
public bool AutoCreate
|
||||
{
|
||||
get { return autoCreate; }
|
||||
set { autoCreate = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 对象池容量
|
||||
/// </summary>
|
||||
public int Capacity { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 可使用(创建)数量
|
||||
/// </summary>
|
||||
public int FreeSize
|
||||
{ get { return this.freeSize; } }
|
||||
|
||||
private int freeSize;
|
||||
|
||||
/// <summary>
|
||||
/// 清除池中所有对象
|
||||
/// </summary>
|
||||
public void Clear()
|
||||
{
|
||||
while (this.queue.TryDequeue(out _))
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取对象T
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public T GetObject()
|
||||
{
|
||||
T t;
|
||||
if (this.queue.TryDequeue(out t))
|
||||
{
|
||||
t.Recreate();
|
||||
t.NewCreate = false;
|
||||
Interlocked.Decrement(ref this.freeSize);
|
||||
return t;
|
||||
}
|
||||
if (this.autoCreate)
|
||||
{
|
||||
t = (T)Activator.CreateInstance(typeof(T));
|
||||
t.Create();
|
||||
t.NewCreate = true;
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取所有对象
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public T[] GetAllObject()
|
||||
{
|
||||
List<T> ts = new List<T>();
|
||||
while (this.queue.TryDequeue(out T t))
|
||||
{
|
||||
ts.Add(t);
|
||||
}
|
||||
return ts.ToArray();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 预获取
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public T PreviewGetObject()
|
||||
{
|
||||
T t;
|
||||
this.queue.TryPeek(out t);
|
||||
return t;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 注销对象
|
||||
/// </summary>
|
||||
/// <param name="t"></param>
|
||||
public void DestroyObject(T t)
|
||||
{
|
||||
t.Destroy();
|
||||
if (this.freeSize < this.Capacity)
|
||||
{
|
||||
Interlocked.Increment(ref this.freeSize);
|
||||
this.queue.Enqueue(t);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 释放对象
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
this.Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
BIN
RRQMCore/RRQM.ico
Normal file
BIN
RRQMCore/RRQM.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 244 KiB |
BIN
RRQMCore/RRQM.png
Normal file
BIN
RRQMCore/RRQM.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 121 KiB |
90
RRQMCore/RRQMCore.csproj
Normal file
90
RRQMCore/RRQMCore.csproj
Normal file
@@ -0,0 +1,90 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>net45;net5;netcoreapp3.1;netstandard2.0</TargetFrameworks>
|
||||
<Authors>若汝棋茗</Authors>
|
||||
<PackageIcon>RRQM.png</PackageIcon>
|
||||
<Copyright>Copyright © 2021 若汝棋茗</Copyright>
|
||||
<Version>6.3.0</Version>
|
||||
<LangVersion>9.0</LangVersion>
|
||||
<SignAssembly>true</SignAssembly>
|
||||
<Description>此程序集是RRQM的核心开源库,其中包含了内存池、高性能序列化、日志接口在内的很多基本内容。
|
||||
|
||||
更新内容:
|
||||
修复:RRQM序列化多数据bug。
|
||||
增加:大小端转换器RRQMBitConverter,其用法与BitConverter基本一致。
|
||||
|
||||
特别说明:本程序集在源码里内嵌了Newtonsoft.Json 11.0.3,但为防止冲突,已修改其命名空间。
|
||||
特此感谢其作者!!!
|
||||
附带其Github:https://github.com/JamesNK/Newtonsoft.Json</Description>
|
||||
<PackageProjectUrl>https://gitee.com/RRQM_OS/RRQMCore</PackageProjectUrl>
|
||||
<AssemblyOriginatorKeyFile>RRQM.pfx</AssemblyOriginatorKeyFile>
|
||||
<ApplicationIcon>RRQM.ico</ApplicationIcon>
|
||||
<PackageLicenseFile>LICENSE</PackageLicenseFile>
|
||||
<PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance>
|
||||
<PackageTags>MemoryPool,ObjectPool,Serialize,Tool</PackageTags>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Debug|netstandard2.0|AnyCPU'">
|
||||
<DocumentationFile>bin\Debug\netstandard2.0\RRQMCore.xml</DocumentationFile>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Release|netstandard2.0|AnyCPU'">
|
||||
<DocumentationFile>bin\Release\netstandard2.0\RRQMCore.xml</DocumentationFile>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Debug|net45|AnyCPU'">
|
||||
<DocumentationFile>bin\Debug\net45\RRQMCore.xml</DocumentationFile>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Release|net45|AnyCPU'">
|
||||
<DocumentationFile>bin\Release\net45\RRQMCore.xml</DocumentationFile>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Debug|net5|AnyCPU'">
|
||||
<DocumentationFile>bin\Debug\net5\RRQMCore.xml</DocumentationFile>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Release|net5|AnyCPU'">
|
||||
<DocumentationFile>bin\Release\net5\RRQMCore.xml</DocumentationFile>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Debug|netcoreapp3.1|AnyCPU'">
|
||||
<DocumentationFile>bin\Debug\netcoreapp3.1\RRQMCore.xml</DocumentationFile>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Release|netcoreapp3.1|AnyCPU'">
|
||||
<DocumentationFile>bin\Release\netcoreapp3.1\RRQMCore.xml</DocumentationFile>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Include="..\LICENSE">
|
||||
<Pack>True</Pack>
|
||||
<PackagePath></PackagePath>
|
||||
</None>
|
||||
<None Include="RRQM.png">
|
||||
<Pack>True</Pack>
|
||||
<PackagePath></PackagePath>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Update="Resource.Designer.cs">
|
||||
<DesignTime>True</DesignTime>
|
||||
<AutoGen>True</AutoGen>
|
||||
<DependentUpon>Resource.resx</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Update="RRQMCore\Resource.Designer.cs">
|
||||
<DesignTime>True</DesignTime>
|
||||
<AutoGen>True</AutoGen>
|
||||
<DependentUpon>Resource.resx</DependentUpon>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Update="Resource.resx">
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
<LastGenOutput>Resource.Designer.cs</LastGenOutput>
|
||||
<CustomToolNamespace>RRQMCore</CustomToolNamespace>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Update="RRQMCore\Resource.resx">
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
<LastGenOutput>Resource.Designer.cs</LastGenOutput>
|
||||
<CustomToolNamespace>RRQMCore</CustomToolNamespace>
|
||||
</EmbeddedResource>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
263
RRQMCore/Resource.Designer.cs
generated
Normal file
263
RRQMCore/Resource.Designer.cs
generated
Normal file
@@ -0,0 +1,263 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权(除特别声明或在RRQMCore.XREF命名空间的代码)归作者本人若汝棋茗所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权
|
||||
// CSDN博客:https://blog.csdn.net/qq_40374647
|
||||
// 哔哩哔哩视频:https://space.bilibili.com/94253567
|
||||
// Gitee源代码仓库:https://gitee.com/RRQM_Home
|
||||
// Github源代码仓库:https://github.com/RRQM
|
||||
// 交流QQ群:234762506
|
||||
// 感谢您的下载和使用
|
||||
//------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace RRQMCore {
|
||||
using System;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 一个强类型的资源类,用于查找本地化的字符串等。
|
||||
/// </summary>
|
||||
// 此类是由 StronglyTypedResourceBuilder
|
||||
// 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。
|
||||
// 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen
|
||||
// (以 /str 作为命令选项),或重新生成 VS 项目。
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
internal class Resource {
|
||||
|
||||
private static global::System.Resources.ResourceManager resourceMan;
|
||||
|
||||
private static global::System.Globalization.CultureInfo resourceCulture;
|
||||
|
||||
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||
internal Resource() {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 返回此类使用的缓存的 ResourceManager 实例。
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static global::System.Resources.ResourceManager ResourceManager {
|
||||
get {
|
||||
if (object.ReferenceEquals(resourceMan, null)) {
|
||||
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("RRQMCore.Resource", typeof(Resource).Assembly);
|
||||
resourceMan = temp;
|
||||
}
|
||||
return resourceMan;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 重写当前线程的 CurrentUICulture 属性,对
|
||||
/// 使用此强类型资源类的所有资源查找执行重写。
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static global::System.Globalization.CultureInfo Culture {
|
||||
get {
|
||||
return resourceCulture;
|
||||
}
|
||||
set {
|
||||
resourceCulture = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 参数‘{0}’为空。 的本地化字符串。
|
||||
/// </summary>
|
||||
internal static string ArgumentNull {
|
||||
get {
|
||||
return ResourceManager.GetString("ArgumentNull", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 取消操作 的本地化字符串。
|
||||
/// </summary>
|
||||
internal static string Canceled {
|
||||
get {
|
||||
return ResourceManager.GetString("Canceled", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 从‘{0}’创建写入流失败,信息:{1}。 的本地化字符串。
|
||||
/// </summary>
|
||||
internal static string CreateWriteStreamFail {
|
||||
get {
|
||||
return ResourceManager.GetString("CreateWriteStreamFail", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 默认设置值。 的本地化字符串。
|
||||
/// </summary>
|
||||
internal static string Default {
|
||||
get {
|
||||
return ResourceManager.GetString("Default", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 发生未知错误。 的本地化字符串。
|
||||
/// </summary>
|
||||
internal static string Error {
|
||||
get {
|
||||
return ResourceManager.GetString("Error", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 其他异常消息。 的本地化字符串。
|
||||
/// </summary>
|
||||
internal static string Exception {
|
||||
get {
|
||||
return ResourceManager.GetString("Exception", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 文件‘{0}’已存在。 的本地化字符串。
|
||||
/// </summary>
|
||||
internal static string FileExists {
|
||||
get {
|
||||
return ResourceManager.GetString("FileExists", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 事件操作器异常。 的本地化字符串。
|
||||
/// </summary>
|
||||
internal static string GetEventArgsFail {
|
||||
get {
|
||||
return ResourceManager.GetString("GetEventArgsFail", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 从‘{0}’路径加载流异常。 的本地化字符串。
|
||||
/// </summary>
|
||||
internal static string LoadStreamFail {
|
||||
get {
|
||||
return ResourceManager.GetString("LoadStreamFail", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 长时间没有响应。 的本地化字符串。
|
||||
/// </summary>
|
||||
internal static string NoResponse {
|
||||
get {
|
||||
return ResourceManager.GetString("NoResponse", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 没有找到路径‘{0}’对应的流文件。 的本地化字符串。
|
||||
/// </summary>
|
||||
internal static string NotFindStream {
|
||||
get {
|
||||
return ResourceManager.GetString("NotFindStream", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 操作超时 的本地化字符串。
|
||||
/// </summary>
|
||||
internal static string Overtime {
|
||||
get {
|
||||
return ResourceManager.GetString("Overtime", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 参数‘{0}’设置的路径‘{1}’不合法。 的本地化字符串。
|
||||
/// </summary>
|
||||
internal static string PathInvalid {
|
||||
get {
|
||||
return ResourceManager.GetString("PathInvalid", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 远程终端异常,信息:{0}。 的本地化字符串。
|
||||
/// </summary>
|
||||
internal static string RemoteException {
|
||||
get {
|
||||
return ResourceManager.GetString("RemoteException", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 远程文件‘{0}’不存在。 的本地化字符串。
|
||||
/// </summary>
|
||||
internal static string RemoteFileNotExists {
|
||||
get {
|
||||
return ResourceManager.GetString("RemoteFileNotExists", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 远程终端不支持响应该操作。 的本地化字符串。
|
||||
/// </summary>
|
||||
internal static string RemoteNotSupported {
|
||||
get {
|
||||
return ResourceManager.GetString("RemoteNotSupported", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 远程终端拒绝该操作,反馈信息:{0}。 的本地化字符串。
|
||||
/// </summary>
|
||||
internal static string RemoteRefuse {
|
||||
get {
|
||||
return ResourceManager.GetString("RemoteRefuse", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 通道设置失败。 的本地化字符串。
|
||||
/// </summary>
|
||||
internal static string SetChannelFail {
|
||||
get {
|
||||
return ResourceManager.GetString("SetChannelFail", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 接收流容器为空。 的本地化字符串。
|
||||
/// </summary>
|
||||
internal static string StreamBucketNull {
|
||||
get {
|
||||
return ResourceManager.GetString("StreamBucketNull", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 路径‘{0}’对应的流文件,仍然被‘{1}’对象应用。 的本地化字符串。
|
||||
/// </summary>
|
||||
internal static string StreamReferencing {
|
||||
get {
|
||||
return ResourceManager.GetString("StreamReferencing", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 操作成功。 的本地化字符串。
|
||||
/// </summary>
|
||||
internal static string Success {
|
||||
get {
|
||||
return ResourceManager.GetString("Success", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 未知原因。 的本地化字符串。
|
||||
/// </summary>
|
||||
internal static string Unknown {
|
||||
get {
|
||||
return ResourceManager.GetString("Unknown", resourceCulture);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
186
RRQMCore/Resource.resx
Normal file
186
RRQMCore/Resource.resx
Normal file
@@ -0,0 +1,186 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<data name="ArgumentNull" xml:space="preserve">
|
||||
<value>参数‘{0}’为空。</value>
|
||||
</data>
|
||||
<data name="Canceled" xml:space="preserve">
|
||||
<value>取消操作</value>
|
||||
</data>
|
||||
<data name="CreateWriteStreamFail" xml:space="preserve">
|
||||
<value>从‘{0}’创建写入流失败,信息:{1}。</value>
|
||||
</data>
|
||||
<data name="Default" xml:space="preserve">
|
||||
<value>默认设置值。</value>
|
||||
</data>
|
||||
<data name="Error" xml:space="preserve">
|
||||
<value>发生未知错误。</value>
|
||||
</data>
|
||||
<data name="Exception" xml:space="preserve">
|
||||
<value>其他异常消息。</value>
|
||||
</data>
|
||||
<data name="FileExists" xml:space="preserve">
|
||||
<value>文件‘{0}’已存在。</value>
|
||||
</data>
|
||||
<data name="GetEventArgsFail" xml:space="preserve">
|
||||
<value>事件操作器异常。</value>
|
||||
</data>
|
||||
<data name="LoadStreamFail" xml:space="preserve">
|
||||
<value>从‘{0}’路径加载流异常。</value>
|
||||
</data>
|
||||
<data name="NoResponse" xml:space="preserve">
|
||||
<value>长时间没有响应。</value>
|
||||
</data>
|
||||
<data name="NotFindStream" xml:space="preserve">
|
||||
<value>没有找到路径‘{0}’对应的流文件。</value>
|
||||
</data>
|
||||
<data name="Overtime" xml:space="preserve">
|
||||
<value>操作超时</value>
|
||||
</data>
|
||||
<data name="PathInvalid" xml:space="preserve">
|
||||
<value>参数‘{0}’设置的路径‘{1}’不合法。</value>
|
||||
</data>
|
||||
<data name="RemoteException" xml:space="preserve">
|
||||
<value>远程终端异常,信息:{0}。</value>
|
||||
</data>
|
||||
<data name="RemoteFileNotExists" xml:space="preserve">
|
||||
<value>远程文件‘{0}’不存在。</value>
|
||||
</data>
|
||||
<data name="RemoteNotSupported" xml:space="preserve">
|
||||
<value>远程终端不支持响应该操作。</value>
|
||||
</data>
|
||||
<data name="RemoteRefuse" xml:space="preserve">
|
||||
<value>远程终端拒绝该操作,反馈信息:{0}。</value>
|
||||
</data>
|
||||
<data name="SetChannelFail" xml:space="preserve">
|
||||
<value>通道设置失败。</value>
|
||||
</data>
|
||||
<data name="StreamBucketNull" xml:space="preserve">
|
||||
<value>接收流容器为空。</value>
|
||||
</data>
|
||||
<data name="StreamReferencing" xml:space="preserve">
|
||||
<value>路径‘{0}’对应的流文件,仍然被‘{1}’对象应用。</value>
|
||||
</data>
|
||||
<data name="Success" xml:space="preserve">
|
||||
<value>操作成功。</value>
|
||||
</data>
|
||||
<data name="Unknown" xml:space="preserve">
|
||||
<value>未知原因。</value>
|
||||
</data>
|
||||
</root>
|
||||
60
RRQMCore/Run/Action/EasyAction.cs
Normal file
60
RRQMCore/Run/Action/EasyAction.cs
Normal file
@@ -0,0 +1,60 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权(除特别声明或在RRQMCore.XREF命名空间的代码)归作者本人若汝棋茗所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权
|
||||
// CSDN博客:https://blog.csdn.net/qq_40374647
|
||||
// 哔哩哔哩视频:https://space.bilibili.com/94253567
|
||||
// Gitee源代码仓库:https://gitee.com/RRQM_Home
|
||||
// Github源代码仓库:https://github.com/RRQM
|
||||
// 交流QQ群:234762506
|
||||
// 感谢您的下载和使用
|
||||
//------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace RRQMCore.Run
|
||||
{
|
||||
/// <summary>
|
||||
/// 易用组件
|
||||
/// </summary>
|
||||
public class EasyAction
|
||||
{
|
||||
/// <summary>
|
||||
/// 延迟执行
|
||||
/// </summary>
|
||||
/// <param name="action"></param>
|
||||
/// <param name="timeSpan"></param>
|
||||
public static void DelayRun(TimeSpan timeSpan, Action action)
|
||||
{
|
||||
Task.Run(async () =>
|
||||
{
|
||||
await Task.Delay(timeSpan);
|
||||
action?.Invoke();
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 延迟执行
|
||||
/// </summary>
|
||||
/// <param name="action"></param>
|
||||
/// <param name="ticks"></param>
|
||||
public static void DelayRun(int ticks, Action action)
|
||||
{
|
||||
DelayRun(TimeSpan.FromMilliseconds(ticks), action);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Task异步
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="statu"></param>
|
||||
/// <param name="action"></param>
|
||||
public static void TaskRun<T>(T statu, Action<T> action)
|
||||
{
|
||||
Task.Run(() =>
|
||||
{
|
||||
action.Invoke(statu);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
273
RRQMCore/Run/Action/LoopAction.cs
Normal file
273
RRQMCore/Run/Action/LoopAction.cs
Normal file
@@ -0,0 +1,273 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权(除特别声明或在RRQMCore.XREF命名空间的代码)归作者本人若汝棋茗所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权
|
||||
// CSDN博客:https://blog.csdn.net/qq_40374647
|
||||
// 哔哩哔哩视频:https://space.bilibili.com/94253567
|
||||
// Gitee源代码仓库:https://gitee.com/RRQM_Home
|
||||
// Github源代码仓库:https://github.com/RRQM
|
||||
// 交流QQ群:234762506
|
||||
// 感谢您的下载和使用
|
||||
//------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------
|
||||
using RRQMCore.Exceptions;
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace RRQMCore.Run
|
||||
{
|
||||
/// <summary>
|
||||
/// 循环动作
|
||||
/// </summary>
|
||||
public class LoopAction : EasyAction, IDisposable
|
||||
{
|
||||
/// <summary>
|
||||
/// 析构函数
|
||||
/// </summary>
|
||||
~LoopAction()
|
||||
{
|
||||
this.Dispose();
|
||||
}
|
||||
|
||||
private int executedCount;
|
||||
|
||||
private TimeSpan interval;
|
||||
|
||||
private int loopCount;
|
||||
|
||||
private EventWaitHandle waitHandle;
|
||||
|
||||
private LoopAction(int count, TimeSpan interval, Action<LoopAction> action)
|
||||
{
|
||||
this.loopCount = count;
|
||||
this.action = action;
|
||||
this.interval = interval;
|
||||
this.waitHandle = new AutoResetEvent(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建可循环操作体
|
||||
/// </summary>
|
||||
/// <param name="count">循环次数,设为-1时一直循环</param>
|
||||
/// <param name="interval">每次循环间隔</param>
|
||||
/// <param name="action">执行委托</param>
|
||||
/// <returns></returns>
|
||||
public static LoopAction CreateLoopAction(int count, TimeSpan interval, Action<LoopAction> action)
|
||||
{
|
||||
return new LoopAction(count, interval, action);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建可循环操作体
|
||||
/// </summary>
|
||||
/// <param name="count">循环次数,设为-1时一直循环</param>
|
||||
/// <param name="intervalMS">每次循环间隔,毫秒</param>
|
||||
/// <param name="action">执行委托</param>
|
||||
/// <returns></returns>
|
||||
public static LoopAction CreateLoopAction(int count, int intervalMS, Action<LoopAction> action)
|
||||
{
|
||||
return new LoopAction(count, TimeSpan.FromMilliseconds(intervalMS), action);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建可循环操作体
|
||||
/// </summary>
|
||||
/// <param name="count">循环次数,设为-1时一直循环</param>
|
||||
/// <param name="action">执行委托</param>
|
||||
/// <returns></returns>
|
||||
public static LoopAction CreateLoopAction(int count, Action<LoopAction> action)
|
||||
{
|
||||
return CreateLoopAction(count, TimeSpan.Zero, action);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建可循环操作体
|
||||
/// </summary>
|
||||
/// <param name="interval">每次循环间隔</param>
|
||||
/// <param name="action">执行委托</param>
|
||||
/// <returns></returns>
|
||||
public static LoopAction CreateLoopAction(TimeSpan interval, Action<LoopAction> action)
|
||||
{
|
||||
return CreateLoopAction(-1, interval, action);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建可循环操作体
|
||||
/// </summary>
|
||||
/// <param name="action">执行委托</param>
|
||||
/// <returns></returns>
|
||||
public static LoopAction CreateLoopAction(Action<LoopAction> action)
|
||||
{
|
||||
return CreateLoopAction(-1, TimeSpan.Zero, action);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 已执行次数
|
||||
/// </summary>
|
||||
public int ExecutedCount
|
||||
{
|
||||
get { return executedCount; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 执行间隔
|
||||
/// </summary>
|
||||
public TimeSpan Interval
|
||||
{
|
||||
get { return interval; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 循环次数
|
||||
/// </summary>
|
||||
public int LoopCount
|
||||
{
|
||||
get { return loopCount; }
|
||||
}
|
||||
|
||||
private Action<LoopAction> action;
|
||||
|
||||
/// <summary>
|
||||
/// 执行委托
|
||||
/// </summary>
|
||||
public Action<LoopAction> ExecuteAction
|
||||
{
|
||||
get { return action; }
|
||||
}
|
||||
|
||||
private RunStatus runStatus;
|
||||
|
||||
/// <summary>
|
||||
/// 是否在运行
|
||||
/// </summary>
|
||||
public RunStatus RunStatus
|
||||
{
|
||||
get { return runStatus; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 运行
|
||||
/// </summary>
|
||||
public void Run()
|
||||
{
|
||||
if (this.runStatus == RunStatus.None)
|
||||
{
|
||||
this.runStatus = RunStatus.Running;
|
||||
if (loopCount >= 0)
|
||||
{
|
||||
for (int i = 0; i < loopCount; i++)
|
||||
{
|
||||
if (this.runStatus == RunStatus.Disposed)
|
||||
{
|
||||
return;
|
||||
}
|
||||
this.action.Invoke(this);
|
||||
this.executedCount++;
|
||||
if (this.runStatus == RunStatus.Paused)
|
||||
{
|
||||
this.waitHandle.WaitOne();
|
||||
}
|
||||
this.waitHandle.WaitOne(this.interval);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
if (this.runStatus == RunStatus.Disposed)
|
||||
{
|
||||
return;
|
||||
}
|
||||
this.action.Invoke(this);
|
||||
this.executedCount++;
|
||||
if (this.runStatus == RunStatus.Paused)
|
||||
{
|
||||
this.waitHandle.WaitOne();
|
||||
}
|
||||
this.waitHandle.WaitOne(this.interval);
|
||||
}
|
||||
}
|
||||
this.runStatus = RunStatus.Completed;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 重新运行
|
||||
/// </summary>
|
||||
public void Rerun()
|
||||
{
|
||||
if (this.runStatus == RunStatus.Disposed)
|
||||
{
|
||||
throw new RRQMException("无法利用已释放的资源");
|
||||
}
|
||||
this.runStatus = RunStatus.None;
|
||||
this.Run();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 以异步重新运行
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public Task RerunAsync()
|
||||
{
|
||||
if (this.runStatus == RunStatus.Disposed)
|
||||
{
|
||||
throw new RRQMException("无法利用已释放的资源");
|
||||
}
|
||||
this.runStatus = RunStatus.None;
|
||||
return this.RunAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 以异步运行
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public Task RunAsync()
|
||||
{
|
||||
return Task.Run(() =>
|
||||
{
|
||||
this.Run();
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 暂停
|
||||
/// </summary>
|
||||
public void Pause()
|
||||
{
|
||||
if (this.runStatus == RunStatus.Running)
|
||||
{
|
||||
this.waitHandle.Reset();
|
||||
this.runStatus = RunStatus.Paused;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 回复
|
||||
/// </summary>
|
||||
public void Resume()
|
||||
{
|
||||
if (this.runStatus == RunStatus.Paused)
|
||||
{
|
||||
this.runStatus = RunStatus.Running;
|
||||
this.waitHandle.Set();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 释放资源
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
if (this.runStatus == RunStatus.Disposed)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (this.runStatus == RunStatus.Completed)
|
||||
{
|
||||
this.waitHandle.Dispose();
|
||||
}
|
||||
this.runStatus = RunStatus.Disposed;
|
||||
}
|
||||
}
|
||||
}
|
||||
44
RRQMCore/Run/Action/RunStatus.cs
Normal file
44
RRQMCore/Run/Action/RunStatus.cs
Normal file
@@ -0,0 +1,44 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权(除特别声明或在RRQMCore.XREF命名空间的代码)归作者本人若汝棋茗所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权
|
||||
// CSDN博客:https://blog.csdn.net/qq_40374647
|
||||
// 哔哩哔哩视频:https://space.bilibili.com/94253567
|
||||
// Gitee源代码仓库:https://gitee.com/RRQM_Home
|
||||
// Github源代码仓库:https://github.com/RRQM
|
||||
// 交流QQ群:234762506
|
||||
// 感谢您的下载和使用
|
||||
//------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------
|
||||
namespace RRQMCore.Run
|
||||
{
|
||||
/// <summary>
|
||||
/// 运行状态
|
||||
/// </summary>
|
||||
public enum RunStatus : byte
|
||||
{
|
||||
/// <summary>
|
||||
/// None
|
||||
/// </summary>
|
||||
None,
|
||||
|
||||
/// <summary>
|
||||
/// Running
|
||||
/// </summary>
|
||||
Running,
|
||||
|
||||
/// <summary>
|
||||
/// Completed
|
||||
/// </summary>
|
||||
Completed,
|
||||
|
||||
/// <summary>
|
||||
/// Pause
|
||||
/// </summary>
|
||||
Paused,
|
||||
|
||||
/// <summary>
|
||||
/// Disposed
|
||||
/// </summary>
|
||||
Disposed
|
||||
}
|
||||
}
|
||||
283
RRQMCore/Run/Message/AppMessenger.cs
Normal file
283
RRQMCore/Run/Message/AppMessenger.cs
Normal file
@@ -0,0 +1,283 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权(除特别声明或在RRQMCore.XREF命名空间的代码)归作者本人若汝棋茗所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权
|
||||
// CSDN博客:https://blog.csdn.net/qq_40374647
|
||||
// 哔哩哔哩视频:https://space.bilibili.com/94253567
|
||||
// Gitee源代码仓库:https://gitee.com/RRQM_Home
|
||||
// Github源代码仓库:https://github.com/RRQM
|
||||
// 交流QQ群:234762506
|
||||
// 感谢您的下载和使用
|
||||
//------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------
|
||||
using RRQMCore.Exceptions;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
|
||||
namespace RRQMCore.Run
|
||||
{
|
||||
/*
|
||||
若汝棋茗
|
||||
*/
|
||||
|
||||
/// <summary>
|
||||
/// 消息通知类
|
||||
/// </summary>
|
||||
public class AppMessenger
|
||||
{
|
||||
/// <summary>
|
||||
/// 注册已加载程序集中直接或间接继承自IMassage接口的所有类,并创建新实例
|
||||
/// </summary>
|
||||
public void RegistAll()
|
||||
{
|
||||
var types = AppDomain.CurrentDomain.GetAssemblies()
|
||||
.SelectMany(a => a.GetTypes().Where(t => t.GetInterfaces().Contains(typeof(IMessage))))
|
||||
.ToArray();
|
||||
foreach (var v in types)
|
||||
{
|
||||
IMessage message = (IMessage)Activator.CreateInstance(v);
|
||||
MethodInfo[] methods = message.GetType().GetMethods();
|
||||
foreach (var item in methods)
|
||||
{
|
||||
RegistMethodAttribute attribute = item.GetCustomAttribute<RegistMethodAttribute>();
|
||||
if (attribute != null)
|
||||
{
|
||||
if (attribute.Token == null)
|
||||
{
|
||||
Default.Register(message, item.Name, item);
|
||||
}
|
||||
else
|
||||
{
|
||||
Default.Register(message, attribute.Token, item);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static AppMessenger instance;
|
||||
|
||||
/// <summary>
|
||||
/// 默认单例实例
|
||||
/// </summary>
|
||||
public static AppMessenger Default
|
||||
{
|
||||
get
|
||||
{
|
||||
if (instance == null)
|
||||
{
|
||||
instance = new AppMessenger();
|
||||
}
|
||||
|
||||
return instance;
|
||||
}
|
||||
}
|
||||
|
||||
private Dictionary<string, TokenInstance> tokenAndInstance = new Dictionary<string, TokenInstance>();
|
||||
|
||||
/// <summary>
|
||||
/// 注册消息
|
||||
/// </summary>
|
||||
/// <param name="messageObject"></param>
|
||||
/// <param name="token"></param>
|
||||
/// <param name="action"></param>
|
||||
/// <exception cref="MessageRegisteredException"></exception>
|
||||
public void Register(IMessage messageObject, string token, Action action)
|
||||
{
|
||||
TokenInstance tokenInstance = new TokenInstance();
|
||||
tokenInstance.MessageObject = messageObject;
|
||||
tokenInstance.MethodInfo = action.Method;
|
||||
try
|
||||
{
|
||||
tokenAndInstance.Add(token, tokenInstance);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
throw new MessageRegisteredException("该Token消息已注册");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 注册消息
|
||||
/// </summary>
|
||||
/// <param name="messageObject"></param>
|
||||
public void Register(IMessage messageObject)
|
||||
{
|
||||
MethodInfo[] methods = messageObject.GetType().GetMethods();
|
||||
foreach (var item in methods)
|
||||
{
|
||||
RegistMethodAttribute attribute = item.GetCustomAttribute<RegistMethodAttribute>();
|
||||
if (attribute != null)
|
||||
{
|
||||
if (attribute.Token == null)
|
||||
{
|
||||
Default.Register(messageObject, item.Name, item);
|
||||
}
|
||||
else
|
||||
{
|
||||
Default.Register(messageObject, attribute.Token, item);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 注册消息
|
||||
/// </summary>
|
||||
/// <param name="messageObject"></param>
|
||||
/// <param name="token"></param>
|
||||
/// <param name="methodInfo"></param>
|
||||
/// <exception cref="MessageRegisteredException"></exception>
|
||||
public void Register(IMessage messageObject, string token, MethodInfo methodInfo)
|
||||
{
|
||||
TokenInstance tokenInstance = new TokenInstance();
|
||||
tokenInstance.MessageObject = messageObject;
|
||||
tokenInstance.MethodInfo = methodInfo;
|
||||
try
|
||||
{
|
||||
tokenAndInstance.Add(token, tokenInstance);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
throw new MessageRegisteredException("该Token消息已注册");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 注册消息
|
||||
/// </summary>
|
||||
/// <typeparam name="T">参数类型</typeparam>
|
||||
/// <param name="messageObject"></param>
|
||||
/// <param name="token"></param>
|
||||
/// <param name="action"></param>
|
||||
/// <exception cref="MessageRegisteredException"></exception>
|
||||
public void Register<T>(IMessage messageObject, string token, Action<T> action)
|
||||
{
|
||||
TokenInstance tokenInstance = new TokenInstance();
|
||||
tokenInstance.MessageObject = messageObject;
|
||||
tokenInstance.MethodInfo = action.Method;
|
||||
try
|
||||
{
|
||||
tokenAndInstance.Add(token, tokenInstance);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
throw new MessageRegisteredException("该Token消息已注册");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 注册
|
||||
/// </summary>
|
||||
/// <typeparam name="T">参数类型</typeparam>
|
||||
/// <typeparam name="TReturn">返回值类型</typeparam>
|
||||
/// <param name="messageObject"></param>
|
||||
/// <param name="token"></param>
|
||||
/// <param name="action"></param>
|
||||
public void Register<T, TReturn>(IMessage messageObject, string token, Func<T, TReturn> action)
|
||||
{
|
||||
TokenInstance tokenInstance = new TokenInstance();
|
||||
tokenInstance.MessageObject = messageObject;
|
||||
tokenInstance.MethodInfo = action.Method;
|
||||
try
|
||||
{
|
||||
tokenAndInstance.Add(token, tokenInstance);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
throw new MessageRegisteredException("该Token消息已注册");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 注册
|
||||
/// </summary>
|
||||
/// <typeparam name="TReturn">返回值类型</typeparam>
|
||||
/// <param name="messageObject"></param>
|
||||
/// <param name="token"></param>
|
||||
/// <param name="action"></param>
|
||||
public void Register<TReturn>(IMessage messageObject, string token, Func<TReturn> action)
|
||||
{
|
||||
TokenInstance tokenInstance = new TokenInstance();
|
||||
tokenInstance.MessageObject = messageObject;
|
||||
tokenInstance.MethodInfo = action.Method;
|
||||
try
|
||||
{
|
||||
tokenAndInstance.Add(token, tokenInstance);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
throw new MessageRegisteredException("该Token消息已注册");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 卸载消息
|
||||
/// </summary>
|
||||
/// <param name="messageObject"></param>
|
||||
public void Unregister(IMessage messageObject)
|
||||
{
|
||||
List<string> key = new List<string>();
|
||||
|
||||
foreach (var item in tokenAndInstance.Keys)
|
||||
{
|
||||
if (messageObject == tokenAndInstance[item].MessageObject)
|
||||
{
|
||||
key.Add(item);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var item in key)
|
||||
{
|
||||
tokenAndInstance.Remove(item);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 清除所有消息
|
||||
/// </summary>
|
||||
public void Clear()
|
||||
{
|
||||
tokenAndInstance.Clear();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 发送消息
|
||||
/// </summary>
|
||||
/// <param name="token"></param>
|
||||
/// <param name="parameters"></param>
|
||||
/// <exception cref="MessageNotFoundException"></exception>
|
||||
public void Send(string token, params object[] parameters)
|
||||
{
|
||||
try
|
||||
{
|
||||
tokenAndInstance[token].MethodInfo.Invoke(tokenAndInstance[token].MessageObject, parameters);
|
||||
}
|
||||
catch (KeyNotFoundException)
|
||||
{
|
||||
throw new MessageNotFoundException("未找到该消息");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 发送消息
|
||||
/// </summary>
|
||||
/// <typeparam name="T">返回值类型</typeparam>
|
||||
/// <param name="token"></param>
|
||||
/// <param name="parameters"></param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="MessageNotFoundException"></exception>
|
||||
public T Send<T>(string token, params object[] parameters)
|
||||
{
|
||||
try
|
||||
{
|
||||
return (T)tokenAndInstance[token].MethodInfo.Invoke(tokenAndInstance[token].MessageObject, parameters);
|
||||
}
|
||||
catch (KeyNotFoundException)
|
||||
{
|
||||
throw new MessageNotFoundException("未找到该消息");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
21
RRQMCore/Run/Message/IMessage.cs
Normal file
21
RRQMCore/Run/Message/IMessage.cs
Normal file
@@ -0,0 +1,21 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权(除特别声明或在RRQMCore.XREF命名空间的代码)归作者本人若汝棋茗所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权
|
||||
// CSDN博客:https://blog.csdn.net/qq_40374647
|
||||
// 哔哩哔哩视频:https://space.bilibili.com/94253567
|
||||
// Gitee源代码仓库:https://gitee.com/RRQM_Home
|
||||
// Github源代码仓库:https://github.com/RRQM
|
||||
// 交流QQ群:234762506
|
||||
// 感谢您的下载和使用
|
||||
//------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace RRQMCore.Run
|
||||
{
|
||||
/// <summary>
|
||||
/// 消息接口
|
||||
/// </summary>
|
||||
public interface IMessage
|
||||
{
|
||||
}
|
||||
}
|
||||
47
RRQMCore/Run/Message/RegistMethodAttribute.cs
Normal file
47
RRQMCore/Run/Message/RegistMethodAttribute.cs
Normal file
@@ -0,0 +1,47 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权(除特别声明或在RRQMCore.XREF命名空间的代码)归作者本人若汝棋茗所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权
|
||||
// CSDN博客:https://blog.csdn.net/qq_40374647
|
||||
// 哔哩哔哩视频:https://space.bilibili.com/94253567
|
||||
// Gitee源代码仓库:https://gitee.com/RRQM_Home
|
||||
// Github源代码仓库:https://github.com/RRQM
|
||||
// 交流QQ群:234762506
|
||||
// 感谢您的下载和使用
|
||||
//------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------
|
||||
using System;
|
||||
|
||||
namespace RRQMCore.Run
|
||||
{
|
||||
/*
|
||||
若汝棋茗
|
||||
*/
|
||||
|
||||
/// <summary>
|
||||
/// 注册为消息
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Method, Inherited = false, AllowMultiple = false)]
|
||||
public sealed class RegistMethodAttribute : Attribute
|
||||
{
|
||||
/// <summary>
|
||||
/// 构造函数
|
||||
/// </summary>
|
||||
public RegistMethodAttribute()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 构造函数
|
||||
/// </summary>
|
||||
/// <param name="token"></param>
|
||||
public RegistMethodAttribute(string token)
|
||||
{
|
||||
this.Token = token;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 标识
|
||||
/// </summary>
|
||||
public string Token { get; set; }
|
||||
}
|
||||
}
|
||||
21
RRQMCore/Run/Message/TokenInstance.cs
Normal file
21
RRQMCore/Run/Message/TokenInstance.cs
Normal file
@@ -0,0 +1,21 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权(除特别声明或在RRQMCore.XREF命名空间的代码)归作者本人若汝棋茗所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权
|
||||
// CSDN博客:https://blog.csdn.net/qq_40374647
|
||||
// 哔哩哔哩视频:https://space.bilibili.com/94253567
|
||||
// Gitee源代码仓库:https://gitee.com/RRQM_Home
|
||||
// Github源代码仓库:https://github.com/RRQM
|
||||
// 交流QQ群:234762506
|
||||
// 感谢您的下载和使用
|
||||
//------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------
|
||||
using System.Reflection;
|
||||
|
||||
namespace RRQMCore.Run
|
||||
{
|
||||
internal class TokenInstance
|
||||
{
|
||||
internal IMessage MessageObject { get; set; }
|
||||
internal MethodInfo MethodInfo { get; set; }
|
||||
}
|
||||
}
|
||||
35
RRQMCore/Run/WaitPool/IWaitResult.cs
Normal file
35
RRQMCore/Run/WaitPool/IWaitResult.cs
Normal file
@@ -0,0 +1,35 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权(除特别声明或在RRQMCore.XREF命名空间的代码)归作者本人若汝棋茗所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权
|
||||
// CSDN博客:https://blog.csdn.net/qq_40374647
|
||||
// 哔哩哔哩视频:https://space.bilibili.com/94253567
|
||||
// Gitee源代码仓库:https://gitee.com/RRQM_Home
|
||||
// Github源代码仓库:https://github.com/RRQM
|
||||
// 交流QQ群:234762506
|
||||
// 感谢您的下载和使用
|
||||
//------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace RRQMCore.Run
|
||||
{
|
||||
/// <summary>
|
||||
/// 等待返回类
|
||||
/// </summary>
|
||||
public interface IWaitResult
|
||||
{
|
||||
/// <summary>
|
||||
/// 消息
|
||||
/// </summary>
|
||||
string Message { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 标记
|
||||
/// </summary>
|
||||
int Sign { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 状态
|
||||
/// </summary>
|
||||
byte Status { get; set; }
|
||||
}
|
||||
}
|
||||
141
RRQMCore/Run/WaitPool/RRQMWaitHandlePool.cs
Normal file
141
RRQMCore/Run/WaitPool/RRQMWaitHandlePool.cs
Normal file
@@ -0,0 +1,141 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权(除特别声明或在RRQMCore.XREF命名空间的代码)归作者本人若汝棋茗所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权
|
||||
// CSDN博客:https://blog.csdn.net/qq_40374647
|
||||
// 哔哩哔哩视频:https://space.bilibili.com/94253567
|
||||
// Gitee源代码仓库:https://gitee.com/RRQM_Home
|
||||
// Github源代码仓库:https://github.com/RRQM
|
||||
// 交流QQ群:234762506
|
||||
// 感谢您的下载和使用
|
||||
//------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------
|
||||
using RRQMCore.Exceptions;
|
||||
using RRQMCore.Helper;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Threading;
|
||||
|
||||
namespace RRQMCore.Run
|
||||
{
|
||||
/// <summary>
|
||||
/// 等待处理数据
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
public class RRQMWaitHandlePool<T> : IDisposable where T : IWaitResult
|
||||
{
|
||||
private int signCount;
|
||||
|
||||
private ConcurrentDictionary<int, WaitData<T>> waitDic;
|
||||
|
||||
private ConcurrentQueue<WaitData<T>> waitQueue;
|
||||
|
||||
/// <summary>
|
||||
/// 构造函数
|
||||
/// </summary>
|
||||
public RRQMWaitHandlePool()
|
||||
{
|
||||
this.waitDic = new ConcurrentDictionary<int, WaitData<T>>();
|
||||
this.waitQueue = new ConcurrentQueue<WaitData<T>>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 销毁
|
||||
/// </summary>
|
||||
/// <param name="waitData"></param>
|
||||
public void Destroy(WaitData<T> waitData)
|
||||
{
|
||||
if (waitData._dispose)
|
||||
{
|
||||
throw new RRQMException("waitData已销毁");
|
||||
}
|
||||
if (this.waitDic.TryRemove(waitData.WaitResult.Sign, out _))
|
||||
{
|
||||
waitData.Reset();
|
||||
this.waitQueue.Enqueue(waitData);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 释放
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
foreach (var item in waitDic.Values)
|
||||
{
|
||||
item.Dispose();
|
||||
}
|
||||
foreach (var item in this.waitQueue)
|
||||
{
|
||||
item.Dispose();
|
||||
}
|
||||
this.waitDic.Clear();
|
||||
|
||||
this.waitQueue.Clear();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取一个可等待对象
|
||||
/// </summary>
|
||||
public WaitData<T> GetWaitData(T result)
|
||||
{
|
||||
if (signCount == int.MaxValue)
|
||||
{
|
||||
signCount = 0;
|
||||
}
|
||||
WaitData<T> waitData;
|
||||
if (this.waitQueue.TryDequeue(out waitData))
|
||||
{
|
||||
result.Sign = Interlocked.Increment(ref signCount);
|
||||
waitData.SetResult(result);
|
||||
this.waitDic.TryAdd(result.Sign, waitData);
|
||||
return waitData;
|
||||
}
|
||||
|
||||
waitData = new WaitData<T>();
|
||||
result.Sign = Interlocked.Increment(ref signCount);
|
||||
waitData.SetResult(result);
|
||||
this.waitDic.TryAdd(result.Sign, waitData);
|
||||
return waitData;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 让等待对象恢复运行
|
||||
/// </summary>
|
||||
/// <param name="sign"></param>
|
||||
public void SetRun(int sign)
|
||||
{
|
||||
WaitData<T> waitData;
|
||||
if (this.waitDic.TryGetValue(sign, out waitData))
|
||||
{
|
||||
waitData.Set();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 让等待对象恢复运行
|
||||
/// </summary>
|
||||
/// <param name="sign"></param>
|
||||
/// <param name="waitResult"></param>
|
||||
public void SetRun(int sign, T waitResult)
|
||||
{
|
||||
WaitData<T> waitData;
|
||||
if (this.waitDic.TryGetValue(sign, out waitData))
|
||||
{
|
||||
waitData.Set(waitResult);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 让等待对象恢复运行
|
||||
/// </summary>
|
||||
/// <param name="waitResult"></param>
|
||||
public void SetRun(T waitResult)
|
||||
{
|
||||
WaitData<T> waitData;
|
||||
if (this.waitDic.TryGetValue(waitResult.Sign, out waitData))
|
||||
{
|
||||
waitData.Set(waitResult);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
149
RRQMCore/Run/WaitPool/WaitData.cs
Normal file
149
RRQMCore/Run/WaitPool/WaitData.cs
Normal file
@@ -0,0 +1,149 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权(除特别声明或在RRQMCore.XREF命名空间的代码)归作者本人若汝棋茗所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权
|
||||
// CSDN博客:https://blog.csdn.net/qq_40374647
|
||||
// 哔哩哔哩视频:https://space.bilibili.com/94253567
|
||||
// Gitee源代码仓库:https://gitee.com/RRQM_Home
|
||||
// Github源代码仓库:https://github.com/RRQM
|
||||
// 交流QQ群:234762506
|
||||
// 感谢您的下载和使用
|
||||
//------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------
|
||||
using System;
|
||||
using System.Threading;
|
||||
|
||||
namespace RRQMCore.Run
|
||||
{
|
||||
/// <summary>
|
||||
/// 等待数据对象
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
public class WaitData<T> : IDisposable
|
||||
{
|
||||
internal bool _dispose;
|
||||
|
||||
private WaitDataStatus status;
|
||||
|
||||
private AutoResetEvent waitHandle;
|
||||
|
||||
private T waitResult;
|
||||
|
||||
/// <summary>
|
||||
/// 构造函数
|
||||
/// </summary>
|
||||
public WaitData()
|
||||
{
|
||||
this.waitHandle = new AutoResetEvent(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 析构函数
|
||||
/// </summary>
|
||||
~WaitData()
|
||||
{
|
||||
if (!this._dispose)
|
||||
{
|
||||
this.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 状态
|
||||
/// </summary>
|
||||
public WaitDataStatus Status { get => status; }
|
||||
|
||||
/// <summary>
|
||||
/// 等待数据结果
|
||||
/// </summary>
|
||||
public T WaitResult
|
||||
{
|
||||
get { return waitResult; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 取消任务
|
||||
/// </summary>
|
||||
public void Cancel()
|
||||
{
|
||||
this.status = WaitDataStatus.Canceled;
|
||||
this.waitHandle.Set();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 回收
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
this.status = WaitDataStatus.Disposed;
|
||||
this._dispose = true;
|
||||
this.waitResult = default;
|
||||
this.waitHandle.Dispose();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reset
|
||||
/// </summary>
|
||||
public bool Reset()
|
||||
{
|
||||
this.status = WaitDataStatus.Default;
|
||||
this.waitResult = default;
|
||||
return this.waitHandle.Reset();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 使等待的线程继续执行
|
||||
/// </summary>
|
||||
public void Set()
|
||||
{
|
||||
this.status = WaitDataStatus.SetRunning;
|
||||
this.waitHandle.Set();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 使等待的线程继续执行
|
||||
/// </summary>
|
||||
/// <param name="waitResult">等待结果</param>
|
||||
public void Set(T waitResult)
|
||||
{
|
||||
this.waitResult = waitResult;
|
||||
this.status = WaitDataStatus.SetRunning;
|
||||
this.waitHandle.Set();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 加载取消令箭
|
||||
/// </summary>
|
||||
/// <param name="cancellationToken"></param>
|
||||
public void SetCancellationToken(CancellationToken cancellationToken)
|
||||
{
|
||||
if (cancellationToken.CanBeCanceled)
|
||||
{
|
||||
cancellationToken.Register(() =>
|
||||
{
|
||||
this.Cancel();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 载入结果
|
||||
/// </summary>
|
||||
public void SetResult(T result)
|
||||
{
|
||||
this.waitResult = result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 等待指定毫秒
|
||||
/// </summary>
|
||||
/// <param name="millisecond"></param>
|
||||
public WaitDataStatus Wait(int millisecond)
|
||||
{
|
||||
if (!this.waitHandle.WaitOne(millisecond))
|
||||
{
|
||||
this.status = WaitDataStatus.Overtime;
|
||||
}
|
||||
return this.status;
|
||||
}
|
||||
}
|
||||
}
|
||||
44
RRQMCore/Run/WaitPool/WaitDataStatus.cs
Normal file
44
RRQMCore/Run/WaitPool/WaitDataStatus.cs
Normal file
@@ -0,0 +1,44 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权(除特别声明或在RRQMCore.XREF命名空间的代码)归作者本人若汝棋茗所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权
|
||||
// CSDN博客:https://blog.csdn.net/qq_40374647
|
||||
// 哔哩哔哩视频:https://space.bilibili.com/94253567
|
||||
// Gitee源代码仓库:https://gitee.com/RRQM_Home
|
||||
// Github源代码仓库:https://github.com/RRQM
|
||||
// 交流QQ群:234762506
|
||||
// 感谢您的下载和使用
|
||||
//------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------
|
||||
namespace RRQMCore.Run
|
||||
{
|
||||
/// <summary>
|
||||
/// 等待数据状态
|
||||
/// </summary>
|
||||
public enum WaitDataStatus : byte
|
||||
{
|
||||
/// <summary>
|
||||
/// 默认
|
||||
/// </summary>
|
||||
Default,
|
||||
|
||||
/// <summary>
|
||||
/// 收到信号运行
|
||||
/// </summary>
|
||||
SetRunning,
|
||||
|
||||
/// <summary>
|
||||
/// 超时
|
||||
/// </summary>
|
||||
Overtime,
|
||||
|
||||
/// <summary>
|
||||
/// 已取消
|
||||
/// </summary>
|
||||
Canceled,
|
||||
|
||||
/// <summary>
|
||||
/// 已释放
|
||||
/// </summary>
|
||||
Disposed
|
||||
}
|
||||
}
|
||||
64
RRQMCore/Run/WaitPool/WaitResult.cs
Normal file
64
RRQMCore/Run/WaitPool/WaitResult.cs
Normal file
@@ -0,0 +1,64 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权(除特别声明或在RRQMCore.XREF命名空间的代码)归作者本人若汝棋茗所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权
|
||||
// CSDN博客:https://blog.csdn.net/qq_40374647
|
||||
// 哔哩哔哩视频:https://space.bilibili.com/94253567
|
||||
// Gitee源代码仓库:https://gitee.com/RRQM_Home
|
||||
// Github源代码仓库:https://github.com/RRQM
|
||||
// 交流QQ群:234762506
|
||||
// 感谢您的下载和使用
|
||||
//------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------
|
||||
using System;
|
||||
|
||||
namespace RRQMCore.Run
|
||||
{
|
||||
/// <summary>
|
||||
/// 等待返回类
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public class WaitResult : IWaitResult
|
||||
{
|
||||
/// <summary>
|
||||
/// 消息
|
||||
/// </summary>
|
||||
protected string message;
|
||||
|
||||
/// <summary>
|
||||
/// 标记号
|
||||
/// </summary>
|
||||
protected int sign;
|
||||
|
||||
/// <summary>
|
||||
/// 状态
|
||||
/// </summary>
|
||||
protected byte status;
|
||||
|
||||
/// <summary>
|
||||
/// 消息
|
||||
/// </summary>
|
||||
public string Message
|
||||
{
|
||||
get { return message; }
|
||||
set { message = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 标记号
|
||||
/// </summary>
|
||||
public int Sign
|
||||
{
|
||||
get { return sign; }
|
||||
set { sign = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 状态
|
||||
/// </summary>
|
||||
public byte Status
|
||||
{
|
||||
get { return status; }
|
||||
set { status = value; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权(除特别声明或在RRQMCore.XREF命名空间的代码)归作者本人若汝棋茗所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权
|
||||
// CSDN博客:https://blog.csdn.net/qq_40374647
|
||||
// 哔哩哔哩视频:https://space.bilibili.com/94253567
|
||||
// Gitee源代码仓库:https://gitee.com/RRQM_Home
|
||||
// Github源代码仓库:https://github.com/RRQM
|
||||
// 交流QQ群:234762506
|
||||
// 感谢您的下载和使用
|
||||
//------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------
|
||||
using System;
|
||||
|
||||
namespace RRQMCore.Serialization
|
||||
{
|
||||
/// <summary>
|
||||
/// 忽略的RRQN序列化
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Property)]
|
||||
public class RRQMNonSerializedAttribute : Attribute
|
||||
{
|
||||
}
|
||||
}
|
||||
31
RRQMCore/Serialization/InstanceObject.cs
Normal file
31
RRQMCore/Serialization/InstanceObject.cs
Normal file
@@ -0,0 +1,31 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权(除特别声明或在RRQMCore.XREF命名空间的代码)归作者本人若汝棋茗所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权
|
||||
// CSDN博客:https://blog.csdn.net/qq_40374647
|
||||
// 哔哩哔哩视频:https://space.bilibili.com/94253567
|
||||
// Gitee源代码仓库:https://gitee.com/RRQM_Home
|
||||
// Github源代码仓库:https://github.com/RRQM
|
||||
// 交流QQ群:234762506
|
||||
// 感谢您的下载和使用
|
||||
//------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------
|
||||
using System;
|
||||
using System.Reflection;
|
||||
|
||||
namespace RRQMCore.Serialization
|
||||
{
|
||||
internal class InstanceObject
|
||||
{
|
||||
internal InstanceType instanceType;
|
||||
internal Type Type;
|
||||
internal object GetInstance()
|
||||
{
|
||||
return Activator.CreateInstance(Type);
|
||||
}
|
||||
internal Type[] ArgTypes;
|
||||
internal Type ArrayType;
|
||||
internal Type[] ProTypes;
|
||||
internal PropertyInfo[] Properties;
|
||||
internal MethodInfo AddMethod;
|
||||
}
|
||||
}
|
||||
22
RRQMCore/Serialization/InstanceType.cs
Normal file
22
RRQMCore/Serialization/InstanceType.cs
Normal file
@@ -0,0 +1,22 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权(除特别声明或在RRQMCore.XREF命名空间的代码)归作者本人若汝棋茗所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权
|
||||
// CSDN博客:https://blog.csdn.net/qq_40374647
|
||||
// 哔哩哔哩视频:https://space.bilibili.com/94253567
|
||||
// Gitee源代码仓库:https://gitee.com/RRQM_Home
|
||||
// Github源代码仓库:https://github.com/RRQM
|
||||
// 交流QQ群:234762506
|
||||
// 感谢您的下载和使用
|
||||
//------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace RRQMCore.Serialization
|
||||
{
|
||||
internal enum InstanceType
|
||||
{
|
||||
Class,
|
||||
List,
|
||||
Array,
|
||||
Dictionary
|
||||
}
|
||||
}
|
||||
549
RRQMCore/Serialization/RRQMBinaryFormatter.cs
Normal file
549
RRQMCore/Serialization/RRQMBinaryFormatter.cs
Normal file
@@ -0,0 +1,549 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权(除特别声明或在RRQMCore.XREF命名空间的代码)归作者本人若汝棋茗所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权
|
||||
// CSDN博客:https://blog.csdn.net/qq_40374647
|
||||
// 哔哩哔哩视频:https://space.bilibili.com/94253567
|
||||
// Gitee源代码仓库:https://gitee.com/RRQM_Home
|
||||
// Github源代码仓库:https://github.com/RRQM
|
||||
// 交流QQ群:234762506
|
||||
// 感谢您的下载和使用
|
||||
//------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------
|
||||
using RRQMCore.ByteManager;
|
||||
using RRQMCore.Helper;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
|
||||
namespace RRQMCore.Serialization
|
||||
{
|
||||
/// <summary>
|
||||
/// 该序列化以二进制方式进行,但是不支持接口、抽象类、继承类等成员的序列化。
|
||||
/// </summary>
|
||||
public class RRQMBinaryFormatter
|
||||
{
|
||||
#region Serialize
|
||||
|
||||
/// <summary>
|
||||
/// 序列化对象
|
||||
/// </summary>
|
||||
/// <param name="stream">流</param>
|
||||
/// <param name="graph">对象</param>
|
||||
public void Serialize(ByteBlock stream, object graph)
|
||||
{
|
||||
stream.Position = 1;
|
||||
SerializeObject(stream, graph);
|
||||
stream.Buffer[0] = 1;
|
||||
stream.SetLength(stream.Position);
|
||||
}
|
||||
|
||||
private int SerializeObject(ByteBlock stream, object graph)
|
||||
{
|
||||
int len = 0;
|
||||
byte[] data = null;
|
||||
|
||||
long startPosition = stream.Position;
|
||||
long endPosition;
|
||||
if (graph != null)
|
||||
{
|
||||
if (graph is string str)
|
||||
{
|
||||
data = Encoding.UTF8.GetBytes(str);
|
||||
}
|
||||
else if (graph is byte by)
|
||||
{
|
||||
data = new byte[] { by };
|
||||
}
|
||||
else if (graph is sbyte sby)
|
||||
{
|
||||
data = RRQMBitConverter.Default.GetBytes((short)sby);
|
||||
}
|
||||
else if (graph is bool b)
|
||||
{
|
||||
data = RRQMBitConverter.Default.GetBytes(b);
|
||||
}
|
||||
else if (graph is short s)
|
||||
{
|
||||
data = RRQMBitConverter.Default.GetBytes(s);
|
||||
}
|
||||
else if (graph is ushort us)
|
||||
{
|
||||
data = RRQMBitConverter.Default.GetBytes(us);
|
||||
}
|
||||
else if (graph is int i)
|
||||
{
|
||||
data = RRQMBitConverter.Default.GetBytes(i);
|
||||
}
|
||||
else if (graph is uint ui)
|
||||
{
|
||||
data = RRQMBitConverter.Default.GetBytes(ui);
|
||||
}
|
||||
else if (graph is long l)
|
||||
{
|
||||
data = RRQMBitConverter.Default.GetBytes(l);
|
||||
}
|
||||
else if (graph is ulong ul)
|
||||
{
|
||||
data = RRQMBitConverter.Default.GetBytes(ul);
|
||||
}
|
||||
else if (graph is float f)
|
||||
{
|
||||
data = RRQMBitConverter.Default.GetBytes(f);
|
||||
}
|
||||
else if (graph is double d)
|
||||
{
|
||||
data = RRQMBitConverter.Default.GetBytes(d);
|
||||
}
|
||||
else if (graph is DateTime time)
|
||||
{
|
||||
data = Encoding.UTF8.GetBytes(time.Ticks.ToString());
|
||||
}
|
||||
else if (graph is char c)
|
||||
{
|
||||
data = RRQMBitConverter.Default.GetBytes(c);
|
||||
}
|
||||
else if (graph is Enum)
|
||||
{
|
||||
var enumValType = Enum.GetUnderlyingType(graph.GetType());
|
||||
|
||||
if (enumValType == RRQMReadonly.byteType)
|
||||
{
|
||||
data = new byte[] { (byte)graph };
|
||||
}
|
||||
else if (enumValType == RRQMReadonly.shortType)
|
||||
{
|
||||
data = RRQMBitConverter.Default.GetBytes((short)graph);
|
||||
}
|
||||
else if (enumValType == RRQMReadonly.intType)
|
||||
{
|
||||
data = RRQMBitConverter.Default.GetBytes((int)graph);
|
||||
}
|
||||
else
|
||||
{
|
||||
data = RRQMBitConverter.Default.GetBytes((long)graph);
|
||||
}
|
||||
}
|
||||
else if (graph is byte[])
|
||||
{
|
||||
data = (byte[])graph;
|
||||
}
|
||||
else
|
||||
{
|
||||
stream.Position += 4;
|
||||
Type type = graph.GetType();
|
||||
|
||||
if (typeof(IEnumerable).IsAssignableFrom(type))
|
||||
{
|
||||
len += SerializeIEnumerable(stream, (IEnumerable)graph);
|
||||
}
|
||||
else
|
||||
{
|
||||
len += SerializeClass(stream, graph, type);
|
||||
}
|
||||
}
|
||||
|
||||
if (data != null)
|
||||
{
|
||||
len = data.Length;
|
||||
endPosition = len + startPosition + 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
endPosition = stream.Position;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
endPosition = startPosition + 4;
|
||||
}
|
||||
|
||||
byte[] lenBuffer = RRQMBitConverter.Default.GetBytes(len);
|
||||
stream.Position = startPosition;
|
||||
stream.Write(lenBuffer, 0, lenBuffer.Length);
|
||||
|
||||
if (data != null)
|
||||
{
|
||||
stream.Write(data, 0, data.Length);
|
||||
}
|
||||
stream.Position = endPosition;
|
||||
return len + 4;
|
||||
}
|
||||
|
||||
private int SerializeClass(ByteBlock stream, object obj, Type type)
|
||||
{
|
||||
int len = 0;
|
||||
if (obj != null)
|
||||
{
|
||||
PropertyInfo[] propertyInfos = GetProperties(type);
|
||||
foreach (PropertyInfo property in propertyInfos)
|
||||
{
|
||||
if (property.GetCustomAttribute<RRQMNonSerializedAttribute>() != null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
byte[] propertyBytes = Encoding.UTF8.GetBytes(property.Name);
|
||||
if (propertyBytes.Length > byte.MaxValue)
|
||||
{
|
||||
throw new Exceptions.RRQMException($"属性名:{property.Name}超长");
|
||||
}
|
||||
byte lenBytes = (byte)propertyBytes.Length;
|
||||
stream.Write(lenBytes);
|
||||
stream.Write(propertyBytes, 0, propertyBytes.Length);
|
||||
len += propertyBytes.Length + 1;
|
||||
len += SerializeObject(stream, property.GetValue(obj, null));
|
||||
}
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
private int SerializeIEnumerable(ByteBlock stream, IEnumerable param)
|
||||
{
|
||||
int len = 0;
|
||||
if (param != null)
|
||||
{
|
||||
long oldPosition = stream.Position;
|
||||
stream.Position += 4;
|
||||
len += 4;
|
||||
uint paramLen = 0;
|
||||
|
||||
foreach (object item in param)
|
||||
{
|
||||
paramLen++;
|
||||
len += SerializeObject(stream, item);
|
||||
}
|
||||
long newPosition = stream.Position;
|
||||
stream.Position = oldPosition;
|
||||
stream.Write(RRQMBitConverter.Default.GetBytes(paramLen));
|
||||
stream.Position = newPosition;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
#endregion Serialize
|
||||
|
||||
#region Deserialize
|
||||
|
||||
/// <summary>
|
||||
/// 反序列化
|
||||
/// </summary>
|
||||
/// <param name="data"></param>
|
||||
/// <param name="offset"></param>
|
||||
/// <param name="type"></param>
|
||||
/// <returns></returns>
|
||||
public object Deserialize(byte[] data, int offset, Type type)
|
||||
{
|
||||
if (data[offset] != 1)
|
||||
{
|
||||
throw new Exceptions.RRQMException("数据流解析错误");
|
||||
}
|
||||
offset += 1;
|
||||
return Deserialize(type, data, ref offset);
|
||||
}
|
||||
|
||||
private dynamic Deserialize(Type type, byte[] datas, ref int offset)
|
||||
{
|
||||
dynamic obj;
|
||||
int len = RRQMBitConverter.Default.ToInt32(datas, offset);
|
||||
offset += 4;
|
||||
if (len > 0)
|
||||
{
|
||||
if (type == RRQMReadonly.stringType)
|
||||
{
|
||||
obj = Encoding.UTF8.GetString(datas, offset, len);
|
||||
}
|
||||
else if (type == RRQMReadonly.byteType)
|
||||
{
|
||||
obj = datas[offset];
|
||||
}
|
||||
else if (type == RRQMReadonly.sbyteType)
|
||||
{
|
||||
obj = (sbyte)(RRQMBitConverter.Default.ToInt16(datas, offset));
|
||||
}
|
||||
else if (type == RRQMReadonly.boolType)
|
||||
{
|
||||
obj = (RRQMBitConverter.Default.ToBoolean(datas, offset));
|
||||
}
|
||||
else if (type == RRQMReadonly.shortType)
|
||||
{
|
||||
obj = (RRQMBitConverter.Default.ToInt16(datas, offset));
|
||||
}
|
||||
else if (type == RRQMReadonly.ushortType)
|
||||
{
|
||||
obj = (RRQMBitConverter.Default.ToUInt16(datas, offset));
|
||||
}
|
||||
else if (type == RRQMReadonly.intType)
|
||||
{
|
||||
obj = (RRQMBitConverter.Default.ToInt32(datas, offset));
|
||||
}
|
||||
else if (type == RRQMReadonly.uintType)
|
||||
{
|
||||
obj = (RRQMBitConverter.Default.ToUInt32(datas, offset));
|
||||
}
|
||||
else if (type == RRQMReadonly.longType)
|
||||
{
|
||||
obj = (RRQMBitConverter.Default.ToInt64(datas, offset));
|
||||
}
|
||||
else if (type == RRQMReadonly.ulongType)
|
||||
{
|
||||
obj = (RRQMBitConverter.Default.ToUInt64(datas, offset));
|
||||
}
|
||||
else if (type == RRQMReadonly.floatType)
|
||||
{
|
||||
obj = (RRQMBitConverter.Default.ToSingle(datas, offset));
|
||||
}
|
||||
else if (type == RRQMReadonly.doubleType)
|
||||
{
|
||||
obj = (RRQMBitConverter.Default.ToDouble(datas, offset));
|
||||
}
|
||||
else if (type == RRQMReadonly.decimalType)
|
||||
{
|
||||
obj = (RRQMBitConverter.Default.ToDouble(datas, offset));
|
||||
}
|
||||
else if (type == RRQMReadonly.charType)
|
||||
{
|
||||
obj = (RRQMBitConverter.Default.ToChar(datas, offset));
|
||||
}
|
||||
else if (type == RRQMReadonly.dateTimeType)
|
||||
{
|
||||
obj = (new DateTime(long.Parse(Encoding.UTF8.GetString(datas, offset, len))));
|
||||
}
|
||||
else if (type.BaseType == typeof(Enum))
|
||||
{
|
||||
Type enumType = Enum.GetUnderlyingType(type);
|
||||
|
||||
if (enumType == typeof(byte))
|
||||
{
|
||||
obj = Enum.ToObject(type, datas[offset]);
|
||||
}
|
||||
else if (enumType == typeof(short))
|
||||
{
|
||||
obj = Enum.ToObject(type, RRQMBitConverter.Default.ToInt16(datas, offset));
|
||||
}
|
||||
else if (enumType == typeof(int))
|
||||
{
|
||||
obj = Enum.ToObject(type, RRQMBitConverter.Default.ToInt32(datas, offset));
|
||||
}
|
||||
else
|
||||
{
|
||||
obj = Enum.ToObject(type, RRQMBitConverter.Default.ToInt64(datas, offset));
|
||||
}
|
||||
}
|
||||
else if (type == RRQMReadonly.bytesType)
|
||||
{
|
||||
byte[] data = new byte[len];
|
||||
Buffer.BlockCopy(datas, offset, data, 0, len);
|
||||
obj = data;
|
||||
}
|
||||
else if (type.IsClass || type.IsStruct())
|
||||
{
|
||||
obj = DeserializeClass(type, datas, offset, len);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception("未定义的类型:" + type.ToString());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
obj = type.GetDefault();
|
||||
}
|
||||
offset += len;
|
||||
return obj;
|
||||
}
|
||||
|
||||
private dynamic DeserializeClass(Type type, byte[] datas, int offset, int length)
|
||||
{
|
||||
InstanceObject instanceObject = GetOrAddInstance(type);
|
||||
|
||||
object instance;
|
||||
switch (instanceObject.instanceType)
|
||||
{
|
||||
case InstanceType.Class:
|
||||
{
|
||||
instance = instanceObject.GetInstance();
|
||||
int index = offset;
|
||||
while (offset - index < length && (length >= 4))
|
||||
{
|
||||
int len = datas[offset];
|
||||
string propertyName = Encoding.UTF8.GetString(datas, offset + 1, len);
|
||||
offset += len + 1;
|
||||
PropertyInfo propertyInfo = type.GetProperty(propertyName, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
|
||||
if (propertyInfo == null)
|
||||
{
|
||||
int pLen = RRQMBitConverter.Default.ToInt32(datas, offset);
|
||||
offset += 4;
|
||||
offset += pLen;
|
||||
continue;
|
||||
}
|
||||
object obj = Deserialize(propertyInfo.PropertyType, datas, ref offset);
|
||||
propertyInfo.SetValue(instance, obj);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case InstanceType.List:
|
||||
{
|
||||
instance = instanceObject.GetInstance();
|
||||
if (length > 0)
|
||||
{
|
||||
uint paramLen = RRQMBitConverter.Default.ToUInt32(datas, offset);
|
||||
offset += 4;
|
||||
for (uint i = 0; i < paramLen; i++)
|
||||
{
|
||||
object obj = Deserialize(instanceObject.ArgTypes[0], datas, ref offset);
|
||||
instanceObject.AddMethod.Invoke(instance, new object[] { obj });
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
instance = null;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case InstanceType.Array:
|
||||
{
|
||||
if (length > 0)
|
||||
{
|
||||
uint paramLen = RRQMBitConverter.Default.ToUInt32(datas, offset);
|
||||
Array array = Array.CreateInstance(instanceObject.ArrayType, paramLen);
|
||||
|
||||
offset += 4;
|
||||
for (uint i = 0; i < paramLen; i++)
|
||||
{
|
||||
object obj = Deserialize(instanceObject.ArrayType, datas, ref offset);
|
||||
array.SetValue(obj, i);
|
||||
}
|
||||
instance = array;
|
||||
}
|
||||
else
|
||||
{
|
||||
instance = null;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case InstanceType.Dictionary:
|
||||
{
|
||||
instance = instanceObject.GetInstance();
|
||||
if (length > 0)
|
||||
{
|
||||
uint paramLen = RRQMBitConverter.Default.ToUInt32(datas, offset);
|
||||
offset += 4;
|
||||
for (uint i = 0; i < paramLen; i++)
|
||||
{
|
||||
offset += 4;
|
||||
offset += datas[offset] + 1;
|
||||
object key = Deserialize(instanceObject.ArgTypes[0], datas, ref offset);
|
||||
|
||||
offset += datas[offset] + 1;
|
||||
object value = Deserialize(instanceObject.ArgTypes[1], datas, ref offset);
|
||||
if (key != null)
|
||||
{
|
||||
instanceObject.AddMethod.Invoke(instance, new object[] { key, value });
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
instance = null;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
instance = null;
|
||||
break;
|
||||
}
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
#endregion Deserialize
|
||||
|
||||
private static PropertyInfo[] GetProperties(Type type)
|
||||
{
|
||||
return type.GetProperties(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
|
||||
}
|
||||
|
||||
private static readonly ConcurrentDictionary<string, InstanceObject> InstanceCache = new ConcurrentDictionary<string, InstanceObject>();
|
||||
|
||||
private static InstanceObject GetOrAddInstance(Type type)
|
||||
{
|
||||
if (InstanceCache.TryGetValue(type.FullName, out InstanceObject instance))
|
||||
{
|
||||
return instance;
|
||||
}
|
||||
|
||||
if (type.IsArray && !type.IsGenericType)//数组
|
||||
{
|
||||
InstanceObject typeInfo = InstanceCache.GetOrAdd(type.FullName, (v) =>
|
||||
{
|
||||
InstanceObject instanceObject = new InstanceObject();
|
||||
instanceObject.Type = type;
|
||||
instanceObject.ArrayType = type.GetElementType();
|
||||
instanceObject.instanceType = InstanceType.Array;
|
||||
instanceObject.Properties = GetProperties(type);
|
||||
instanceObject.ProTypes = instanceObject.Properties.Select(a => a.PropertyType).ToArray();
|
||||
return instanceObject;
|
||||
});
|
||||
return typeInfo;
|
||||
}
|
||||
else if (type.IsClass || type.IsStruct())
|
||||
{
|
||||
InstanceObject typeInfo = InstanceCache.GetOrAdd(type.FullName, (v) =>
|
||||
{
|
||||
InstanceObject instanceObject = new InstanceObject();
|
||||
instanceObject.Type = type;
|
||||
instanceObject.Properties = GetProperties(type);
|
||||
instanceObject.ProTypes = instanceObject.Properties.Select(a => a.PropertyType).ToArray();
|
||||
|
||||
if (type.IsGenericType)
|
||||
{
|
||||
instanceObject.AddMethod = type.GetMethod("Add");
|
||||
instanceObject.ArgTypes = type.GetGenericArguments();
|
||||
type = type.GetGenericTypeDefinition().MakeGenericType(instanceObject.ArgTypes);
|
||||
|
||||
if (instanceObject.ArgTypes.Length == 1)
|
||||
{
|
||||
instanceObject.instanceType = InstanceType.List;
|
||||
}
|
||||
else
|
||||
{
|
||||
instanceObject.instanceType = InstanceType.Dictionary;
|
||||
}
|
||||
}
|
||||
else if (RRQMReadonly.listType.IsAssignableFrom(type))
|
||||
{
|
||||
Type baseType = type.BaseType;
|
||||
while (!baseType.IsGenericType)
|
||||
{
|
||||
baseType = baseType.BaseType;
|
||||
}
|
||||
instanceObject.ArgTypes = baseType.GetGenericArguments();
|
||||
|
||||
instanceObject.AddMethod = type.GetMethod("Add");
|
||||
instanceObject.instanceType = InstanceType.List;
|
||||
}
|
||||
else if (RRQMReadonly.dicType.IsAssignableFrom(type))
|
||||
{
|
||||
Type baseType = type.BaseType;
|
||||
while (!baseType.IsGenericType)
|
||||
{
|
||||
baseType = baseType.BaseType;
|
||||
}
|
||||
instanceObject.ArgTypes = baseType.GetGenericArguments();
|
||||
instanceObject.AddMethod = type.GetMethod("Add");
|
||||
instanceObject.instanceType = InstanceType.Dictionary;
|
||||
}
|
||||
else
|
||||
{
|
||||
instanceObject.instanceType = InstanceType.Class;
|
||||
}
|
||||
return instanceObject;
|
||||
});
|
||||
return typeInfo;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
35
RRQMCore/Serialization/SerializationType.cs
Normal file
35
RRQMCore/Serialization/SerializationType.cs
Normal file
@@ -0,0 +1,35 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权(除特别声明或在RRQMCore.XREF命名空间的代码)归作者本人若汝棋茗所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权
|
||||
// CSDN博客:https://blog.csdn.net/qq_40374647
|
||||
// 哔哩哔哩视频:https://space.bilibili.com/94253567
|
||||
// Gitee源代码仓库:https://gitee.com/RRQM_Home
|
||||
// Github源代码仓库:https://github.com/RRQM
|
||||
// 交流QQ群:234762506
|
||||
// 感谢您的下载和使用
|
||||
//------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace RRQMCore.Serialization
|
||||
{
|
||||
/// <summary>
|
||||
/// 序列化类型
|
||||
/// </summary>
|
||||
public enum SerializationType : byte
|
||||
{
|
||||
/// <summary>
|
||||
/// 若汝棋茗内置
|
||||
/// </summary>
|
||||
RRQMBinary,
|
||||
|
||||
/// <summary>
|
||||
/// Json
|
||||
/// </summary>
|
||||
Json,
|
||||
|
||||
/// <summary>
|
||||
/// Xml
|
||||
/// </summary>
|
||||
Xml
|
||||
}
|
||||
}
|
||||
378
RRQMCore/Serialization/SerializeConvert.cs
Normal file
378
RRQMCore/Serialization/SerializeConvert.cs
Normal file
@@ -0,0 +1,378 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权(除特别声明或在RRQMCore.XREF命名空间的代码)归作者本人若汝棋茗所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权
|
||||
// CSDN博客:https://blog.csdn.net/qq_40374647
|
||||
// 哔哩哔哩视频:https://space.bilibili.com/94253567
|
||||
// Gitee源代码仓库:https://gitee.com/RRQM_Home
|
||||
// Github源代码仓库:https://github.com/RRQM
|
||||
// 交流QQ群:234762506
|
||||
// 感谢您的下载和使用
|
||||
//------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------
|
||||
using RRQMCore.ByteManager;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Runtime.Serialization.Formatters.Binary;
|
||||
using System.Text;
|
||||
using System.Xml.Serialization;
|
||||
|
||||
namespace RRQMCore.Serialization
|
||||
{
|
||||
/// <summary>
|
||||
/// 高性能序列化器
|
||||
/// </summary>
|
||||
public static class SerializeConvert
|
||||
{
|
||||
#if NET45_OR_GREATER
|
||||
|
||||
#region 普通二进制序列化
|
||||
|
||||
/// <summary>
|
||||
/// 普通二进制序列化对象
|
||||
/// </summary>
|
||||
/// <param name="obj">数据对象</param>
|
||||
/// <returns></returns>
|
||||
public static byte[] BinarySerialize(object obj)
|
||||
{
|
||||
using (MemoryStream serializeStream = new MemoryStream())
|
||||
{
|
||||
BinaryFormatter bf = new BinaryFormatter();
|
||||
bf.Serialize(serializeStream, obj);
|
||||
return serializeStream.ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 二进制序列化对象至文件
|
||||
/// </summary>
|
||||
/// <param name="obj">数据对象</param>
|
||||
/// <param name="path">路径</param>
|
||||
public static void BinarySerializeToFile(object obj, string path)
|
||||
{
|
||||
using (FileStream serializeStream = new FileStream(path, FileMode.OpenOrCreate, FileAccess.ReadWrite))
|
||||
{
|
||||
BinaryFormatter bf = new BinaryFormatter();
|
||||
bf.Serialize(serializeStream, obj);
|
||||
serializeStream.Close();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 二进制序列化对象
|
||||
/// </summary>
|
||||
/// <param name="stream"></param>
|
||||
/// <param name="obj"></param>
|
||||
public static void BinarySerialize(Stream stream, object obj)
|
||||
{
|
||||
BinaryFormatter bf = new BinaryFormatter();
|
||||
bf.Serialize(stream, obj);
|
||||
}
|
||||
|
||||
#endregion 普通二进制序列化
|
||||
|
||||
#region 普通二进制反序列化
|
||||
|
||||
/// <summary>
|
||||
/// 从Byte[]中反序列化
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="data"></param>
|
||||
/// <param name="offset"></param>
|
||||
/// <param name="length"></param>
|
||||
/// <param name="binder"></param>
|
||||
/// <returns></returns>
|
||||
public static T BinaryDeserialize<T>(byte[] data, int offset, int length, SerializationBinder binder = null)
|
||||
{
|
||||
using (MemoryStream DeserializeStream = new MemoryStream(data, offset, length))
|
||||
{
|
||||
DeserializeStream.Position = 0;
|
||||
BinaryFormatter bf = new BinaryFormatter();
|
||||
if (binder != null)
|
||||
{
|
||||
bf.Binder = binder;
|
||||
}
|
||||
return (T)bf.Deserialize(DeserializeStream);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 反序列化
|
||||
/// </summary>
|
||||
/// <param name="data"></param>
|
||||
/// <param name="offset"></param>
|
||||
/// <param name="length"></param>
|
||||
/// <param name="binder"></param>
|
||||
/// <returns></returns>
|
||||
public static object BinaryDeserialize(byte[] data, int offset, int length, SerializationBinder binder = null)
|
||||
{
|
||||
using (MemoryStream DeserializeStream = new MemoryStream(data, offset, length))
|
||||
{
|
||||
DeserializeStream.Position = 0;
|
||||
BinaryFormatter bf = new BinaryFormatter();
|
||||
if (binder != null)
|
||||
{
|
||||
bf.Binder = binder;
|
||||
}
|
||||
return bf.Deserialize(DeserializeStream);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 从Stream中反序列化
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="stream"></param>
|
||||
/// <param name="binder"></param>
|
||||
/// <returns></returns>
|
||||
public static T BinaryDeserialize<T>(Stream stream, SerializationBinder binder = null)
|
||||
{
|
||||
BinaryFormatter bf = new BinaryFormatter();
|
||||
if (binder != null)
|
||||
{
|
||||
bf.Binder = binder;
|
||||
}
|
||||
return (T)bf.Deserialize(stream);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将二进制文件数据反序列化为指定类型对象
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="path"></param>
|
||||
/// <returns></returns>
|
||||
public static T BinaryDeserializeFromFile<T>(string path)
|
||||
{
|
||||
using (FileStream serializeStream = new FileStream(path, FileMode.Open, FileAccess.Read))
|
||||
{
|
||||
BinaryFormatter bf = new BinaryFormatter();
|
||||
return (T)bf.Deserialize(serializeStream);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将二进制数据反序列化为指定类型对象
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="data"></param>
|
||||
/// <returns></returns>
|
||||
public static T BinaryDeserialize<T>(byte[] data)
|
||||
{
|
||||
return BinaryDeserialize<T>(data, 0, data.Length);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 从Byte[]中反序列化
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="data"></param>
|
||||
/// <param name="binder"></param>
|
||||
/// <returns></returns>
|
||||
public static T BinaryDeserialize<T>(byte[] data, SerializationBinder binder = null)
|
||||
{
|
||||
return BinaryDeserialize<T>(data, 0, data.Length, binder);
|
||||
}
|
||||
|
||||
#endregion 普通二进制反序列化
|
||||
|
||||
#endif
|
||||
|
||||
#region RRQM二进制序列化
|
||||
|
||||
/// <summary>
|
||||
/// RRQM二进制序列化对象
|
||||
/// </summary>
|
||||
/// <param name="stream"></param>
|
||||
/// <param name="obj"></param>
|
||||
/// <returns></returns>
|
||||
public static void RRQMBinarySerialize(ByteBlock stream, object obj)
|
||||
{
|
||||
RRQMBinaryFormatter bf = new RRQMBinaryFormatter();
|
||||
bf.Serialize(stream, obj);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// RRQM二进制序列化对象
|
||||
/// </summary>
|
||||
/// <param name="obj"></param>
|
||||
/// <returns></returns>
|
||||
public static byte[] RRQMBinarySerialize(object obj)
|
||||
{
|
||||
using (ByteBlock byteBlock = new ByteBlock())
|
||||
{
|
||||
RRQMBinarySerialize(byteBlock, obj);
|
||||
return byteBlock.ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion RRQM二进制序列化
|
||||
|
||||
#region RRQM二进制反序列化
|
||||
|
||||
/// <summary>
|
||||
/// 反序列化
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="data"></param>
|
||||
/// <param name="offset"></param>
|
||||
/// <returns></returns>
|
||||
public static T RRQMBinaryDeserialize<T>(byte[] data, int offset)
|
||||
{
|
||||
RRQMBinaryFormatter bf = new RRQMBinaryFormatter();
|
||||
return (T)bf.Deserialize(data, offset, typeof(T));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 反序列化
|
||||
/// </summary>
|
||||
/// <param name="data"></param>
|
||||
/// <param name="offset"></param>
|
||||
/// <param name="type"></param>
|
||||
/// <returns></returns>
|
||||
public static object RRQMBinaryDeserialize(byte[] data, int offset, Type type)
|
||||
{
|
||||
RRQMBinaryFormatter bf = new RRQMBinaryFormatter();
|
||||
return bf.Deserialize(data, offset, type);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 从Byte[]中反序列化
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="data"></param>
|
||||
/// <returns></returns>
|
||||
public static T RRQMBinaryDeserialize<T>(byte[] data)
|
||||
{
|
||||
return RRQMBinaryDeserialize<T>(data, 0);
|
||||
}
|
||||
|
||||
#endregion RRQM二进制反序列化
|
||||
|
||||
#region Xml序列化和反序列化
|
||||
|
||||
/// <summary>
|
||||
/// Xml序列化数据对象
|
||||
/// </summary>
|
||||
/// <param name="obj">数据对象</param>
|
||||
/// <param name="encoding">编码格式</param>
|
||||
/// <returns></returns>
|
||||
public static string XmlSerializeToString(object obj, Encoding encoding)
|
||||
{
|
||||
return encoding.GetString(XmlSerializeToBytes(obj));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Xml序列化数据对象
|
||||
/// </summary>
|
||||
/// <param name="obj">数据对象</param>
|
||||
/// <returns></returns>
|
||||
public static string XmlSerializeToString(object obj)
|
||||
{
|
||||
return XmlSerializeToString(obj, Encoding.UTF8);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Xml序列化数据对象
|
||||
/// </summary>
|
||||
/// <param name="obj">数据对象</param>
|
||||
/// <returns></returns>
|
||||
public static byte[] XmlSerializeToBytes(object obj)
|
||||
{
|
||||
using (MemoryStream fileStream = new MemoryStream())
|
||||
{
|
||||
XmlSerializer xml = new XmlSerializer(obj.GetType());
|
||||
xml.Serialize(fileStream, obj);
|
||||
return fileStream.ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Xml序列化至文件
|
||||
/// </summary>
|
||||
/// <param name="obj"></param>
|
||||
/// <param name="path"></param>
|
||||
public static void XmlSerializeToFile(object obj, string path)
|
||||
{
|
||||
using (FileStream fileStream = new FileStream(path, FileMode.OpenOrCreate, FileAccess.ReadWrite))
|
||||
{
|
||||
XmlSerializer xml = new XmlSerializer(obj.GetType());
|
||||
xml.Serialize(fileStream, obj);
|
||||
fileStream.Close();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Xml反序列化
|
||||
/// </summary>
|
||||
/// <typeparam name="T">反序列化类型</typeparam>
|
||||
/// <param name="datas">数据</param>
|
||||
/// <returns></returns>
|
||||
public static T XmlDeserializeFromBytes<T>(byte[] datas)
|
||||
{
|
||||
XmlSerializer xmlserializer = new XmlSerializer(typeof(T));
|
||||
using (Stream xmlstream = new MemoryStream(datas))
|
||||
{
|
||||
return (T)xmlserializer.Deserialize(xmlstream);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Xml反序列化
|
||||
/// </summary>
|
||||
/// <param name="datas"></param>
|
||||
/// <param name="type"></param>
|
||||
/// <returns></returns>
|
||||
public static object XmlDeserializeFromBytes(byte[] datas, Type type)
|
||||
{
|
||||
XmlSerializer xmlserializer = new XmlSerializer(type);
|
||||
using (Stream xmlstream = new MemoryStream(datas))
|
||||
{
|
||||
return xmlserializer.Deserialize(xmlstream);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Xml反序列化
|
||||
/// </summary>
|
||||
/// <typeparam name="T">类型</typeparam>
|
||||
/// <param name="xmlString">xml字符串</param>
|
||||
/// <param name="encoding">编码格式</param>
|
||||
/// <returns></returns>
|
||||
public static T XmlDeserializeFromString<T>(string xmlString, Encoding encoding)
|
||||
{
|
||||
XmlSerializer xmlserializer = new XmlSerializer(typeof(T));
|
||||
using (Stream xmlstream = new MemoryStream(encoding.GetBytes(xmlString)))
|
||||
{
|
||||
return (T)xmlserializer.Deserialize(xmlstream);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Xml反序列化
|
||||
/// </summary>
|
||||
/// <typeparam name="T">类型</typeparam>
|
||||
/// <param name="xmlString">xml字符串</param>
|
||||
/// <returns></returns>
|
||||
public static T XmlDeserializeFromString<T>(string xmlString)
|
||||
{
|
||||
return XmlDeserializeFromString<T>(xmlString, Encoding.UTF8);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Xml反序列化
|
||||
/// </summary>
|
||||
/// <typeparam name="T">反序列化类型</typeparam>
|
||||
/// <param name="path">文件路径</param>
|
||||
/// <returns></returns>
|
||||
public static T XmlDeserializeFromFile<T>(string path)
|
||||
{
|
||||
using (Stream xmlstream = new FileStream(path, FileMode.Open, FileAccess.Read))
|
||||
{
|
||||
XmlSerializer xmlserializer = new XmlSerializer(typeof(T));
|
||||
return (T)xmlserializer.Deserialize(xmlstream);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion Xml序列化和反序列化
|
||||
}
|
||||
}
|
||||
59
RRQMCore/XREF/Newtonsoft.Json/Bson/BsonBinaryType.cs
Normal file
59
RRQMCore/XREF/Newtonsoft.Json/Bson/BsonBinaryType.cs
Normal file
@@ -0,0 +1,59 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权(除特别声明或在RRQMCore.XREF命名空间的代码)归作者本人若汝棋茗所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权
|
||||
// CSDN博客:https://blog.csdn.net/qq_40374647
|
||||
// 哔哩哔哩视频:https://space.bilibili.com/94253567
|
||||
// Gitee源代码仓库:https://gitee.com/RRQM_Home
|
||||
// Github源代码仓库:https://github.com/RRQM
|
||||
// 交流QQ群:234762506
|
||||
// 感谢您的下载和使用
|
||||
//------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#region License
|
||||
|
||||
// Copyright (c) 2007 James Newton-King
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the "Software"), to deal in the Software without
|
||||
// restriction, including without limitation the rights to use,
|
||||
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following
|
||||
// conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
// OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#endregion License
|
||||
|
||||
using System;
|
||||
|
||||
namespace RRQMCore.XREF.Newtonsoft.Json.Bson
|
||||
{
|
||||
internal enum BsonBinaryType : byte
|
||||
{
|
||||
Binary = 0x00,
|
||||
Function = 0x01,
|
||||
|
||||
[Obsolete("This type has been deprecated in the BSON specification. Use Binary instead.")]
|
||||
BinaryOld = 0x02,
|
||||
|
||||
[Obsolete("This type has been deprecated in the BSON specification. Use Uuid instead.")]
|
||||
UuidOld = 0x03,
|
||||
|
||||
Uuid = 0x04,
|
||||
Md5 = 0x05,
|
||||
UserDefined = 0x80
|
||||
}
|
||||
}
|
||||
362
RRQMCore/XREF/Newtonsoft.Json/Bson/BsonBinaryWriter.cs
Normal file
362
RRQMCore/XREF/Newtonsoft.Json/Bson/BsonBinaryWriter.cs
Normal file
@@ -0,0 +1,362 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权(除特别声明或在RRQMCore.XREF命名空间的代码)归作者本人若汝棋茗所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权
|
||||
// CSDN博客:https://blog.csdn.net/qq_40374647
|
||||
// 哔哩哔哩视频:https://space.bilibili.com/94253567
|
||||
// Gitee源代码仓库:https://gitee.com/RRQM_Home
|
||||
// Github源代码仓库:https://github.com/RRQM
|
||||
// 交流QQ群:234762506
|
||||
// 感谢您的下载和使用
|
||||
//------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#region License
|
||||
|
||||
// Copyright (c) 2007 James Newton-King
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the "Software"), to deal in the Software without
|
||||
// restriction, including without limitation the rights to use,
|
||||
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following
|
||||
// conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
// OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#endregion License
|
||||
|
||||
using RRQMCore.XREF.Newtonsoft.Json.Utilities;
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
|
||||
namespace RRQMCore.XREF.Newtonsoft.Json.Bson
|
||||
{
|
||||
internal class BsonBinaryWriter
|
||||
{
|
||||
private static readonly Encoding Encoding = new UTF8Encoding(false);
|
||||
|
||||
private readonly BinaryWriter _writer;
|
||||
|
||||
private byte[] _largeByteBuffer;
|
||||
|
||||
public DateTimeKind DateTimeKindHandling { get; set; }
|
||||
|
||||
public BsonBinaryWriter(BinaryWriter writer)
|
||||
{
|
||||
DateTimeKindHandling = DateTimeKind.Utc;
|
||||
_writer = writer;
|
||||
}
|
||||
|
||||
public void Flush()
|
||||
{
|
||||
_writer.Flush();
|
||||
}
|
||||
|
||||
public void Close()
|
||||
{
|
||||
#if HAVE_STREAM_READER_WRITER_CLOSE
|
||||
_writer.Close();
|
||||
#else
|
||||
_writer.Dispose();
|
||||
#endif
|
||||
}
|
||||
|
||||
public void WriteToken(BsonToken t)
|
||||
{
|
||||
CalculateSize(t);
|
||||
WriteTokenInternal(t);
|
||||
}
|
||||
|
||||
private void WriteTokenInternal(BsonToken t)
|
||||
{
|
||||
switch (t.Type)
|
||||
{
|
||||
case BsonType.Object:
|
||||
{
|
||||
BsonObject value = (BsonObject)t;
|
||||
_writer.Write(value.CalculatedSize);
|
||||
foreach (BsonProperty property in value)
|
||||
{
|
||||
_writer.Write((sbyte)property.Value.Type);
|
||||
WriteString((string)property.Name.Value, property.Name.ByteCount, null);
|
||||
WriteTokenInternal(property.Value);
|
||||
}
|
||||
_writer.Write((byte)0);
|
||||
}
|
||||
break;
|
||||
|
||||
case BsonType.Array:
|
||||
{
|
||||
BsonArray value = (BsonArray)t;
|
||||
_writer.Write(value.CalculatedSize);
|
||||
ulong index = 0;
|
||||
foreach (BsonToken c in value)
|
||||
{
|
||||
_writer.Write((sbyte)c.Type);
|
||||
WriteString(index.ToString(CultureInfo.InvariantCulture), MathUtils.IntLength(index), null);
|
||||
WriteTokenInternal(c);
|
||||
index++;
|
||||
}
|
||||
_writer.Write((byte)0);
|
||||
}
|
||||
break;
|
||||
|
||||
case BsonType.Integer:
|
||||
{
|
||||
BsonValue value = (BsonValue)t;
|
||||
_writer.Write(Convert.ToInt32(value.Value, CultureInfo.InvariantCulture));
|
||||
}
|
||||
break;
|
||||
|
||||
case BsonType.Long:
|
||||
{
|
||||
BsonValue value = (BsonValue)t;
|
||||
_writer.Write(Convert.ToInt64(value.Value, CultureInfo.InvariantCulture));
|
||||
}
|
||||
break;
|
||||
|
||||
case BsonType.Number:
|
||||
{
|
||||
BsonValue value = (BsonValue)t;
|
||||
_writer.Write(Convert.ToDouble(value.Value, CultureInfo.InvariantCulture));
|
||||
}
|
||||
break;
|
||||
|
||||
case BsonType.String:
|
||||
{
|
||||
BsonString value = (BsonString)t;
|
||||
WriteString((string)value.Value, value.ByteCount, value.CalculatedSize - 4);
|
||||
}
|
||||
break;
|
||||
|
||||
case BsonType.Boolean:
|
||||
_writer.Write(t == BsonBoolean.True);
|
||||
break;
|
||||
|
||||
case BsonType.Null:
|
||||
case BsonType.Undefined:
|
||||
break;
|
||||
|
||||
case BsonType.Date:
|
||||
{
|
||||
BsonValue value = (BsonValue)t;
|
||||
|
||||
long ticks = 0;
|
||||
|
||||
if (value.Value is DateTime)
|
||||
{
|
||||
DateTime dateTime = (DateTime)value.Value;
|
||||
if (DateTimeKindHandling == DateTimeKind.Utc)
|
||||
{
|
||||
dateTime = dateTime.ToUniversalTime();
|
||||
}
|
||||
else if (DateTimeKindHandling == DateTimeKind.Local)
|
||||
{
|
||||
dateTime = dateTime.ToLocalTime();
|
||||
}
|
||||
|
||||
ticks = DateTimeUtils.ConvertDateTimeToJavaScriptTicks(dateTime, false);
|
||||
}
|
||||
#if HAVE_DATE_TIME_OFFSET
|
||||
else
|
||||
{
|
||||
DateTimeOffset dateTimeOffset = (DateTimeOffset)value.Value;
|
||||
ticks = DateTimeUtils.ConvertDateTimeToJavaScriptTicks(dateTimeOffset.UtcDateTime, dateTimeOffset.Offset);
|
||||
}
|
||||
#endif
|
||||
|
||||
_writer.Write(ticks);
|
||||
}
|
||||
break;
|
||||
|
||||
case BsonType.Binary:
|
||||
{
|
||||
BsonBinary value = (BsonBinary)t;
|
||||
|
||||
byte[] data = (byte[])value.Value;
|
||||
_writer.Write(data.Length);
|
||||
_writer.Write((byte)value.BinaryType);
|
||||
_writer.Write(data);
|
||||
}
|
||||
break;
|
||||
|
||||
case BsonType.Oid:
|
||||
{
|
||||
BsonValue value = (BsonValue)t;
|
||||
|
||||
byte[] data = (byte[])value.Value;
|
||||
_writer.Write(data);
|
||||
}
|
||||
break;
|
||||
|
||||
case BsonType.Regex:
|
||||
{
|
||||
BsonRegex value = (BsonRegex)t;
|
||||
|
||||
WriteString((string)value.Pattern.Value, value.Pattern.ByteCount, null);
|
||||
WriteString((string)value.Options.Value, value.Options.ByteCount, null);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException(nameof(t), "Unexpected token when writing BSON: {0}".FormatWith(CultureInfo.InvariantCulture, t.Type));
|
||||
}
|
||||
}
|
||||
|
||||
private void WriteString(string s, int byteCount, int? calculatedlengthPrefix)
|
||||
{
|
||||
if (calculatedlengthPrefix != null)
|
||||
{
|
||||
_writer.Write(calculatedlengthPrefix.GetValueOrDefault());
|
||||
}
|
||||
|
||||
WriteUtf8Bytes(s, byteCount);
|
||||
|
||||
_writer.Write((byte)0);
|
||||
}
|
||||
|
||||
public void WriteUtf8Bytes(string s, int byteCount)
|
||||
{
|
||||
if (s != null)
|
||||
{
|
||||
if (byteCount <= 256)
|
||||
{
|
||||
if (_largeByteBuffer == null)
|
||||
{
|
||||
_largeByteBuffer = new byte[256];
|
||||
}
|
||||
|
||||
Encoding.GetBytes(s, 0, s.Length, _largeByteBuffer, 0);
|
||||
_writer.Write(_largeByteBuffer, 0, byteCount);
|
||||
}
|
||||
else
|
||||
{
|
||||
byte[] bytes = Encoding.GetBytes(s);
|
||||
_writer.Write(bytes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private int CalculateSize(int stringByteCount)
|
||||
{
|
||||
return stringByteCount + 1;
|
||||
}
|
||||
|
||||
private int CalculateSizeWithLength(int stringByteCount, bool includeSize)
|
||||
{
|
||||
int baseSize = (includeSize)
|
||||
? 5 // size bytes + terminator
|
||||
: 1; // terminator
|
||||
|
||||
return baseSize + stringByteCount;
|
||||
}
|
||||
|
||||
private int CalculateSize(BsonToken t)
|
||||
{
|
||||
switch (t.Type)
|
||||
{
|
||||
case BsonType.Object:
|
||||
{
|
||||
BsonObject value = (BsonObject)t;
|
||||
|
||||
int bases = 4;
|
||||
foreach (BsonProperty p in value)
|
||||
{
|
||||
int size = 1;
|
||||
size += CalculateSize(p.Name);
|
||||
size += CalculateSize(p.Value);
|
||||
|
||||
bases += size;
|
||||
}
|
||||
bases += 1;
|
||||
value.CalculatedSize = bases;
|
||||
return bases;
|
||||
}
|
||||
case BsonType.Array:
|
||||
{
|
||||
BsonArray value = (BsonArray)t;
|
||||
|
||||
int size = 4;
|
||||
ulong index = 0;
|
||||
foreach (BsonToken c in value)
|
||||
{
|
||||
size += 1;
|
||||
size += CalculateSize(MathUtils.IntLength(index));
|
||||
size += CalculateSize(c);
|
||||
index++;
|
||||
}
|
||||
size += 1;
|
||||
value.CalculatedSize = size;
|
||||
|
||||
return value.CalculatedSize;
|
||||
}
|
||||
case BsonType.Integer:
|
||||
return 4;
|
||||
|
||||
case BsonType.Long:
|
||||
return 8;
|
||||
|
||||
case BsonType.Number:
|
||||
return 8;
|
||||
|
||||
case BsonType.String:
|
||||
{
|
||||
BsonString value = (BsonString)t;
|
||||
string s = (string)value.Value;
|
||||
value.ByteCount = (s != null) ? Encoding.GetByteCount(s) : 0;
|
||||
value.CalculatedSize = CalculateSizeWithLength(value.ByteCount, value.IncludeLength);
|
||||
|
||||
return value.CalculatedSize;
|
||||
}
|
||||
case BsonType.Boolean:
|
||||
return 1;
|
||||
|
||||
case BsonType.Null:
|
||||
case BsonType.Undefined:
|
||||
return 0;
|
||||
|
||||
case BsonType.Date:
|
||||
return 8;
|
||||
|
||||
case BsonType.Binary:
|
||||
{
|
||||
BsonBinary value = (BsonBinary)t;
|
||||
|
||||
byte[] data = (byte[])value.Value;
|
||||
value.CalculatedSize = 4 + 1 + data.Length;
|
||||
|
||||
return value.CalculatedSize;
|
||||
}
|
||||
case BsonType.Oid:
|
||||
return 12;
|
||||
|
||||
case BsonType.Regex:
|
||||
{
|
||||
BsonRegex value = (BsonRegex)t;
|
||||
int size = 0;
|
||||
size += CalculateSize(value.Pattern);
|
||||
size += CalculateSize(value.Options);
|
||||
value.CalculatedSize = size;
|
||||
|
||||
return value.CalculatedSize;
|
||||
}
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException(nameof(t), "Unexpected token when writing BSON: {0}".FormatWith(CultureInfo.InvariantCulture, t.Type));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
72
RRQMCore/XREF/Newtonsoft.Json/Bson/BsonObjectId.cs
Normal file
72
RRQMCore/XREF/Newtonsoft.Json/Bson/BsonObjectId.cs
Normal file
@@ -0,0 +1,72 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权(除特别声明或在RRQMCore.XREF命名空间的代码)归作者本人若汝棋茗所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权
|
||||
// CSDN博客:https://blog.csdn.net/qq_40374647
|
||||
// 哔哩哔哩视频:https://space.bilibili.com/94253567
|
||||
// Gitee源代码仓库:https://gitee.com/RRQM_Home
|
||||
// Github源代码仓库:https://github.com/RRQM
|
||||
// 交流QQ群:234762506
|
||||
// 感谢您的下载和使用
|
||||
//------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#region License
|
||||
|
||||
// Copyright (c) 2007 James Newton-King
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the "Software"), to deal in the Software without
|
||||
// restriction, including without limitation the rights to use,
|
||||
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following
|
||||
// conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
// OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#endregion License
|
||||
|
||||
using RRQMCore.XREF.Newtonsoft.Json.Utilities;
|
||||
using System;
|
||||
|
||||
namespace RRQMCore.XREF.Newtonsoft.Json.Bson
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a BSON Oid (object id).
|
||||
/// </summary>
|
||||
[Obsolete("BSON reading and writing has been moved to its own package. See https://www.nuget.org/packages/RRQMCore.XREF.Newtonsoft.Json.Bson for more details.")]
|
||||
public class BsonObjectId
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the value of the Oid.
|
||||
/// </summary>
|
||||
/// <value>The value of the Oid.</value>
|
||||
public byte[] Value { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="BsonObjectId"/> class.
|
||||
/// </summary>
|
||||
/// <param name="value">The Oid value.</param>
|
||||
public BsonObjectId(byte[] value)
|
||||
{
|
||||
ValidationUtils.ArgumentNotNull(value, nameof(value));
|
||||
if (value.Length != 12)
|
||||
{
|
||||
throw new ArgumentException("An ObjectId must be 12 bytes", nameof(value));
|
||||
}
|
||||
|
||||
Value = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
870
RRQMCore/XREF/Newtonsoft.Json/Bson/BsonReader.cs
Normal file
870
RRQMCore/XREF/Newtonsoft.Json/Bson/BsonReader.cs
Normal file
@@ -0,0 +1,870 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权(除特别声明或在RRQMCore.XREF命名空间的代码)归作者本人若汝棋茗所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权
|
||||
// CSDN博客:https://blog.csdn.net/qq_40374647
|
||||
// 哔哩哔哩视频:https://space.bilibili.com/94253567
|
||||
// Gitee源代码仓库:https://gitee.com/RRQM_Home
|
||||
// Github源代码仓库:https://github.com/RRQM
|
||||
// 交流QQ群:234762506
|
||||
// 感谢您的下载和使用
|
||||
//------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#region License
|
||||
|
||||
// Copyright (c) 2007 James Newton-King
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the "Software"), to deal in the Software without
|
||||
// restriction, including without limitation the rights to use,
|
||||
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following
|
||||
// conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
// OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#endregion License
|
||||
|
||||
using RRQMCore.XREF.Newtonsoft.Json.Serialization;
|
||||
using RRQMCore.XREF.Newtonsoft.Json.Utilities;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
|
||||
namespace RRQMCore.XREF.Newtonsoft.Json.Bson
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a reader that provides fast, non-cached, forward-only access to serialized BSON data.
|
||||
/// </summary>
|
||||
[Obsolete("BSON reading and writing has been moved to its own package. See https://www.nuget.org/packages/RRQMCore.XREF.Newtonsoft.Json.Bson for more details.")]
|
||||
public class BsonReader : JsonReader
|
||||
{
|
||||
private const int MaxCharBytesSize = 128;
|
||||
private static readonly byte[] SeqRange1 = new byte[] { 0, 127 }; // range of 1-byte sequence
|
||||
private static readonly byte[] SeqRange2 = new byte[] { 194, 223 }; // range of 2-byte sequence
|
||||
private static readonly byte[] SeqRange3 = new byte[] { 224, 239 }; // range of 3-byte sequence
|
||||
private static readonly byte[] SeqRange4 = new byte[] { 240, 244 }; // range of 4-byte sequence
|
||||
|
||||
private readonly BinaryReader _reader;
|
||||
private readonly List<ContainerContext> _stack;
|
||||
|
||||
private byte[] _byteBuffer;
|
||||
private char[] _charBuffer;
|
||||
|
||||
private BsonType _currentElementType;
|
||||
private BsonReaderState _bsonReaderState;
|
||||
private ContainerContext _currentContext;
|
||||
|
||||
private bool _readRootValueAsArray;
|
||||
private bool _jsonNet35BinaryCompatibility;
|
||||
private DateTimeKind _dateTimeKindHandling;
|
||||
|
||||
private enum BsonReaderState
|
||||
{
|
||||
Normal = 0,
|
||||
ReferenceStart = 1,
|
||||
ReferenceRef = 2,
|
||||
ReferenceId = 3,
|
||||
CodeWScopeStart = 4,
|
||||
CodeWScopeCode = 5,
|
||||
CodeWScopeScope = 6,
|
||||
CodeWScopeScopeObject = 7,
|
||||
CodeWScopeScopeEnd = 8
|
||||
}
|
||||
|
||||
private class ContainerContext
|
||||
{
|
||||
public readonly BsonType Type;
|
||||
public int Length;
|
||||
public int Position;
|
||||
|
||||
public ContainerContext(BsonType type)
|
||||
{
|
||||
Type = type;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether binary data reading should be compatible with incorrect Json.NET 3.5 written binary.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// <c>true</c> if binary data reading will be compatible with incorrect Json.NET 3.5 written binary; otherwise, <c>false</c>.
|
||||
/// </value>
|
||||
[Obsolete("JsonNet35BinaryCompatibility will be removed in a future version of Json.NET.")]
|
||||
public bool JsonNet35BinaryCompatibility
|
||||
{
|
||||
get => _jsonNet35BinaryCompatibility;
|
||||
set => _jsonNet35BinaryCompatibility = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether the root object will be read as a JSON array.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// <c>true</c> if the root object will be read as a JSON array; otherwise, <c>false</c>.
|
||||
/// </value>
|
||||
public bool ReadRootValueAsArray
|
||||
{
|
||||
get => _readRootValueAsArray;
|
||||
set => _readRootValueAsArray = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the <see cref="DateTimeKind" /> used when reading <see cref="DateTime"/> values from BSON.
|
||||
/// </summary>
|
||||
/// <value>The <see cref="DateTimeKind" /> used when reading <see cref="DateTime"/> values from BSON.</value>
|
||||
public DateTimeKind DateTimeKindHandling
|
||||
{
|
||||
get => _dateTimeKindHandling;
|
||||
set => _dateTimeKindHandling = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="BsonReader"/> class.
|
||||
/// </summary>
|
||||
/// <param name="stream">The <see cref="Stream"/> containing the BSON data to read.</param>
|
||||
public BsonReader(Stream stream)
|
||||
: this(stream, false, DateTimeKind.Local)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="BsonReader"/> class.
|
||||
/// </summary>
|
||||
/// <param name="reader">The <see cref="BinaryReader"/> containing the BSON data to read.</param>
|
||||
public BsonReader(BinaryReader reader)
|
||||
: this(reader, false, DateTimeKind.Local)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="BsonReader"/> class.
|
||||
/// </summary>
|
||||
/// <param name="stream">The <see cref="Stream"/> containing the BSON data to read.</param>
|
||||
/// <param name="readRootValueAsArray">if set to <c>true</c> the root object will be read as a JSON array.</param>
|
||||
/// <param name="dateTimeKindHandling">The <see cref="DateTimeKind" /> used when reading <see cref="DateTime"/> values from BSON.</param>
|
||||
public BsonReader(Stream stream, bool readRootValueAsArray, DateTimeKind dateTimeKindHandling)
|
||||
{
|
||||
ValidationUtils.ArgumentNotNull(stream, nameof(stream));
|
||||
_reader = new BinaryReader(stream);
|
||||
_stack = new List<ContainerContext>();
|
||||
_readRootValueAsArray = readRootValueAsArray;
|
||||
_dateTimeKindHandling = dateTimeKindHandling;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="BsonReader"/> class.
|
||||
/// </summary>
|
||||
/// <param name="reader">The <see cref="BinaryReader"/> containing the BSON data to read.</param>
|
||||
/// <param name="readRootValueAsArray">if set to <c>true</c> the root object will be read as a JSON array.</param>
|
||||
/// <param name="dateTimeKindHandling">The <see cref="DateTimeKind" /> used when reading <see cref="DateTime"/> values from BSON.</param>
|
||||
public BsonReader(BinaryReader reader, bool readRootValueAsArray, DateTimeKind dateTimeKindHandling)
|
||||
{
|
||||
ValidationUtils.ArgumentNotNull(reader, nameof(reader));
|
||||
_reader = reader;
|
||||
_stack = new List<ContainerContext>();
|
||||
_readRootValueAsArray = readRootValueAsArray;
|
||||
_dateTimeKindHandling = dateTimeKindHandling;
|
||||
}
|
||||
|
||||
private string ReadElement()
|
||||
{
|
||||
_currentElementType = ReadType();
|
||||
string elementName = ReadString();
|
||||
return elementName;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads the next JSON token from the underlying <see cref="Stream"/>.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// <c>true</c> if the next token was read successfully; <c>false</c> if there are no more tokens to read.
|
||||
/// </returns>
|
||||
public override bool Read()
|
||||
{
|
||||
try
|
||||
{
|
||||
bool success;
|
||||
|
||||
switch (_bsonReaderState)
|
||||
{
|
||||
case BsonReaderState.Normal:
|
||||
success = ReadNormal();
|
||||
break;
|
||||
|
||||
case BsonReaderState.ReferenceStart:
|
||||
case BsonReaderState.ReferenceRef:
|
||||
case BsonReaderState.ReferenceId:
|
||||
success = ReadReference();
|
||||
break;
|
||||
|
||||
case BsonReaderState.CodeWScopeStart:
|
||||
case BsonReaderState.CodeWScopeCode:
|
||||
case BsonReaderState.CodeWScopeScope:
|
||||
case BsonReaderState.CodeWScopeScopeObject:
|
||||
case BsonReaderState.CodeWScopeScopeEnd:
|
||||
success = ReadCodeWScope();
|
||||
break;
|
||||
|
||||
default:
|
||||
throw JsonReaderException.Create(this, "Unexpected state: {0}".FormatWith(CultureInfo.InvariantCulture, _bsonReaderState));
|
||||
}
|
||||
|
||||
if (!success)
|
||||
{
|
||||
SetToken(JsonToken.None);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (EndOfStreamException)
|
||||
{
|
||||
SetToken(JsonToken.None);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Changes the reader's state to <see cref="JsonReader.State.Closed"/>.
|
||||
/// If <see cref="JsonReader.CloseInput"/> is set to <c>true</c>, the underlying <see cref="Stream"/> is also closed.
|
||||
/// </summary>
|
||||
public override void Close()
|
||||
{
|
||||
base.Close();
|
||||
|
||||
if (CloseInput)
|
||||
{
|
||||
#if HAVE_STREAM_READER_WRITER_CLOSE
|
||||
_reader?.Close();
|
||||
#else
|
||||
_reader?.Dispose();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
private bool ReadCodeWScope()
|
||||
{
|
||||
switch (_bsonReaderState)
|
||||
{
|
||||
case BsonReaderState.CodeWScopeStart:
|
||||
SetToken(JsonToken.PropertyName, "$code");
|
||||
_bsonReaderState = BsonReaderState.CodeWScopeCode;
|
||||
return true;
|
||||
|
||||
case BsonReaderState.CodeWScopeCode:
|
||||
// total CodeWScope size - not used
|
||||
ReadInt32();
|
||||
|
||||
SetToken(JsonToken.String, ReadLengthString());
|
||||
_bsonReaderState = BsonReaderState.CodeWScopeScope;
|
||||
return true;
|
||||
|
||||
case BsonReaderState.CodeWScopeScope:
|
||||
if (CurrentState == State.PostValue)
|
||||
{
|
||||
SetToken(JsonToken.PropertyName, "$scope");
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
SetToken(JsonToken.StartObject);
|
||||
_bsonReaderState = BsonReaderState.CodeWScopeScopeObject;
|
||||
|
||||
ContainerContext newContext = new ContainerContext(BsonType.Object);
|
||||
PushContext(newContext);
|
||||
newContext.Length = ReadInt32();
|
||||
|
||||
return true;
|
||||
}
|
||||
case BsonReaderState.CodeWScopeScopeObject:
|
||||
bool result = ReadNormal();
|
||||
if (result && TokenType == JsonToken.EndObject)
|
||||
{
|
||||
_bsonReaderState = BsonReaderState.CodeWScopeScopeEnd;
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
case BsonReaderState.CodeWScopeScopeEnd:
|
||||
SetToken(JsonToken.EndObject);
|
||||
_bsonReaderState = BsonReaderState.Normal;
|
||||
return true;
|
||||
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
}
|
||||
|
||||
private bool ReadReference()
|
||||
{
|
||||
switch (CurrentState)
|
||||
{
|
||||
case State.ObjectStart:
|
||||
{
|
||||
SetToken(JsonToken.PropertyName, JsonTypeReflector.RefPropertyName);
|
||||
_bsonReaderState = BsonReaderState.ReferenceRef;
|
||||
return true;
|
||||
}
|
||||
case State.Property:
|
||||
{
|
||||
if (_bsonReaderState == BsonReaderState.ReferenceRef)
|
||||
{
|
||||
SetToken(JsonToken.String, ReadLengthString());
|
||||
return true;
|
||||
}
|
||||
else if (_bsonReaderState == BsonReaderState.ReferenceId)
|
||||
{
|
||||
SetToken(JsonToken.Bytes, ReadBytes(12));
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw JsonReaderException.Create(this, "Unexpected state when reading BSON reference: " + _bsonReaderState);
|
||||
}
|
||||
}
|
||||
case State.PostValue:
|
||||
{
|
||||
if (_bsonReaderState == BsonReaderState.ReferenceRef)
|
||||
{
|
||||
SetToken(JsonToken.PropertyName, JsonTypeReflector.IdPropertyName);
|
||||
_bsonReaderState = BsonReaderState.ReferenceId;
|
||||
return true;
|
||||
}
|
||||
else if (_bsonReaderState == BsonReaderState.ReferenceId)
|
||||
{
|
||||
SetToken(JsonToken.EndObject);
|
||||
_bsonReaderState = BsonReaderState.Normal;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw JsonReaderException.Create(this, "Unexpected state when reading BSON reference: " + _bsonReaderState);
|
||||
}
|
||||
}
|
||||
default:
|
||||
throw JsonReaderException.Create(this, "Unexpected state when reading BSON reference: " + CurrentState);
|
||||
}
|
||||
}
|
||||
|
||||
private bool ReadNormal()
|
||||
{
|
||||
switch (CurrentState)
|
||||
{
|
||||
case State.Start:
|
||||
{
|
||||
JsonToken token = (!_readRootValueAsArray) ? JsonToken.StartObject : JsonToken.StartArray;
|
||||
BsonType type = (!_readRootValueAsArray) ? BsonType.Object : BsonType.Array;
|
||||
|
||||
SetToken(token);
|
||||
ContainerContext newContext = new ContainerContext(type);
|
||||
PushContext(newContext);
|
||||
newContext.Length = ReadInt32();
|
||||
return true;
|
||||
}
|
||||
case State.Complete:
|
||||
case State.Closed:
|
||||
return false;
|
||||
|
||||
case State.Property:
|
||||
{
|
||||
ReadType(_currentElementType);
|
||||
return true;
|
||||
}
|
||||
case State.ObjectStart:
|
||||
case State.ArrayStart:
|
||||
case State.PostValue:
|
||||
ContainerContext context = _currentContext;
|
||||
if (context == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
int lengthMinusEnd = context.Length - 1;
|
||||
|
||||
if (context.Position < lengthMinusEnd)
|
||||
{
|
||||
if (context.Type == BsonType.Array)
|
||||
{
|
||||
ReadElement();
|
||||
ReadType(_currentElementType);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
SetToken(JsonToken.PropertyName, ReadElement());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (context.Position == lengthMinusEnd)
|
||||
{
|
||||
if (ReadByte() != 0)
|
||||
{
|
||||
throw JsonReaderException.Create(this, "Unexpected end of object byte value.");
|
||||
}
|
||||
|
||||
PopContext();
|
||||
if (_currentContext != null)
|
||||
{
|
||||
MovePosition(context.Length);
|
||||
}
|
||||
|
||||
JsonToken endToken = (context.Type == BsonType.Object) ? JsonToken.EndObject : JsonToken.EndArray;
|
||||
SetToken(endToken);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw JsonReaderException.Create(this, "Read past end of current container context.");
|
||||
}
|
||||
case State.ConstructorStart:
|
||||
break;
|
||||
|
||||
case State.Constructor:
|
||||
break;
|
||||
|
||||
case State.Error:
|
||||
break;
|
||||
|
||||
case State.Finished:
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private void PopContext()
|
||||
{
|
||||
_stack.RemoveAt(_stack.Count - 1);
|
||||
if (_stack.Count == 0)
|
||||
{
|
||||
_currentContext = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
_currentContext = _stack[_stack.Count - 1];
|
||||
}
|
||||
}
|
||||
|
||||
private void PushContext(ContainerContext newContext)
|
||||
{
|
||||
_stack.Add(newContext);
|
||||
_currentContext = newContext;
|
||||
}
|
||||
|
||||
private byte ReadByte()
|
||||
{
|
||||
MovePosition(1);
|
||||
return _reader.ReadByte();
|
||||
}
|
||||
|
||||
private void ReadType(BsonType type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case BsonType.Number:
|
||||
double d = ReadDouble();
|
||||
|
||||
if (_floatParseHandling == FloatParseHandling.Decimal)
|
||||
{
|
||||
SetToken(JsonToken.Float, Convert.ToDecimal(d, CultureInfo.InvariantCulture));
|
||||
}
|
||||
else
|
||||
{
|
||||
SetToken(JsonToken.Float, d);
|
||||
}
|
||||
break;
|
||||
|
||||
case BsonType.String:
|
||||
case BsonType.Symbol:
|
||||
SetToken(JsonToken.String, ReadLengthString());
|
||||
break;
|
||||
|
||||
case BsonType.Object:
|
||||
{
|
||||
SetToken(JsonToken.StartObject);
|
||||
|
||||
ContainerContext newContext = new ContainerContext(BsonType.Object);
|
||||
PushContext(newContext);
|
||||
newContext.Length = ReadInt32();
|
||||
break;
|
||||
}
|
||||
case BsonType.Array:
|
||||
{
|
||||
SetToken(JsonToken.StartArray);
|
||||
|
||||
ContainerContext newContext = new ContainerContext(BsonType.Array);
|
||||
PushContext(newContext);
|
||||
newContext.Length = ReadInt32();
|
||||
break;
|
||||
}
|
||||
case BsonType.Binary:
|
||||
BsonBinaryType binaryType;
|
||||
byte[] data = ReadBinary(out binaryType);
|
||||
|
||||
object value = (binaryType != BsonBinaryType.Uuid)
|
||||
? data
|
||||
: (object)new Guid(data);
|
||||
|
||||
SetToken(JsonToken.Bytes, value);
|
||||
break;
|
||||
|
||||
case BsonType.Undefined:
|
||||
SetToken(JsonToken.Undefined);
|
||||
break;
|
||||
|
||||
case BsonType.Oid:
|
||||
byte[] oid = ReadBytes(12);
|
||||
SetToken(JsonToken.Bytes, oid);
|
||||
break;
|
||||
|
||||
case BsonType.Boolean:
|
||||
bool b = Convert.ToBoolean(ReadByte());
|
||||
SetToken(JsonToken.Boolean, b);
|
||||
break;
|
||||
|
||||
case BsonType.Date:
|
||||
long ticks = ReadInt64();
|
||||
DateTime utcDateTime = DateTimeUtils.ConvertJavaScriptTicksToDateTime(ticks);
|
||||
|
||||
DateTime dateTime;
|
||||
switch (DateTimeKindHandling)
|
||||
{
|
||||
case DateTimeKind.Unspecified:
|
||||
dateTime = DateTime.SpecifyKind(utcDateTime, DateTimeKind.Unspecified);
|
||||
break;
|
||||
|
||||
case DateTimeKind.Local:
|
||||
dateTime = utcDateTime.ToLocalTime();
|
||||
break;
|
||||
|
||||
default:
|
||||
dateTime = utcDateTime;
|
||||
break;
|
||||
}
|
||||
|
||||
SetToken(JsonToken.Date, dateTime);
|
||||
break;
|
||||
|
||||
case BsonType.Null:
|
||||
SetToken(JsonToken.Null);
|
||||
break;
|
||||
|
||||
case BsonType.Regex:
|
||||
string expression = ReadString();
|
||||
string modifiers = ReadString();
|
||||
|
||||
string regex = @"/" + expression + @"/" + modifiers;
|
||||
SetToken(JsonToken.String, regex);
|
||||
break;
|
||||
|
||||
case BsonType.Reference:
|
||||
SetToken(JsonToken.StartObject);
|
||||
_bsonReaderState = BsonReaderState.ReferenceStart;
|
||||
break;
|
||||
|
||||
case BsonType.Code:
|
||||
SetToken(JsonToken.String, ReadLengthString());
|
||||
break;
|
||||
|
||||
case BsonType.CodeWScope:
|
||||
SetToken(JsonToken.StartObject);
|
||||
_bsonReaderState = BsonReaderState.CodeWScopeStart;
|
||||
break;
|
||||
|
||||
case BsonType.Integer:
|
||||
SetToken(JsonToken.Integer, (long)ReadInt32());
|
||||
break;
|
||||
|
||||
case BsonType.TimeStamp:
|
||||
case BsonType.Long:
|
||||
SetToken(JsonToken.Integer, ReadInt64());
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException(nameof(type), "Unexpected BsonType value: " + type);
|
||||
}
|
||||
}
|
||||
|
||||
private byte[] ReadBinary(out BsonBinaryType binaryType)
|
||||
{
|
||||
int dataLength = ReadInt32();
|
||||
|
||||
binaryType = (BsonBinaryType)ReadByte();
|
||||
|
||||
#pragma warning disable 612,618
|
||||
// the old binary type has the data length repeated in the data for some reason
|
||||
if (binaryType == BsonBinaryType.BinaryOld && !_jsonNet35BinaryCompatibility)
|
||||
{
|
||||
dataLength = ReadInt32();
|
||||
}
|
||||
#pragma warning restore 612,618
|
||||
|
||||
return ReadBytes(dataLength);
|
||||
}
|
||||
|
||||
private string ReadString()
|
||||
{
|
||||
EnsureBuffers();
|
||||
|
||||
StringBuilder builder = null;
|
||||
|
||||
int totalBytesRead = 0;
|
||||
// used in case of left over multibyte characters in the buffer
|
||||
int offset = 0;
|
||||
while (true)
|
||||
{
|
||||
int count = offset;
|
||||
byte b;
|
||||
while (count < MaxCharBytesSize && (b = _reader.ReadByte()) > 0)
|
||||
{
|
||||
_byteBuffer[count++] = b;
|
||||
}
|
||||
int byteCount = count - offset;
|
||||
totalBytesRead += byteCount;
|
||||
|
||||
if (count < MaxCharBytesSize && builder == null)
|
||||
{
|
||||
// pref optimization to avoid reading into a string builder
|
||||
// if string is smaller than the buffer then return it directly
|
||||
int length = Encoding.UTF8.GetChars(_byteBuffer, 0, byteCount, _charBuffer, 0);
|
||||
|
||||
MovePosition(totalBytesRead + 1);
|
||||
return new string(_charBuffer, 0, length);
|
||||
}
|
||||
else
|
||||
{
|
||||
// calculate the index of the end of the last full character in the buffer
|
||||
int lastFullCharStop = GetLastFullCharStop(count - 1);
|
||||
|
||||
int charCount = Encoding.UTF8.GetChars(_byteBuffer, 0, lastFullCharStop + 1, _charBuffer, 0);
|
||||
|
||||
if (builder == null)
|
||||
{
|
||||
builder = new StringBuilder(MaxCharBytesSize * 2);
|
||||
}
|
||||
|
||||
builder.Append(_charBuffer, 0, charCount);
|
||||
|
||||
if (lastFullCharStop < byteCount - 1)
|
||||
{
|
||||
offset = byteCount - lastFullCharStop - 1;
|
||||
// copy left over multi byte characters to beginning of buffer for next iteration
|
||||
Array.Copy(_byteBuffer, lastFullCharStop + 1, _byteBuffer, 0, offset);
|
||||
}
|
||||
else
|
||||
{
|
||||
// reached end of string
|
||||
if (count < MaxCharBytesSize)
|
||||
{
|
||||
MovePosition(totalBytesRead + 1);
|
||||
return builder.ToString();
|
||||
}
|
||||
|
||||
offset = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private string ReadLengthString()
|
||||
{
|
||||
int length = ReadInt32();
|
||||
|
||||
MovePosition(length);
|
||||
|
||||
string s = GetString(length - 1);
|
||||
_reader.ReadByte();
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
private string GetString(int length)
|
||||
{
|
||||
if (length == 0)
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
EnsureBuffers();
|
||||
|
||||
StringBuilder builder = null;
|
||||
|
||||
int totalBytesRead = 0;
|
||||
|
||||
// used in case of left over multibyte characters in the buffer
|
||||
int offset = 0;
|
||||
do
|
||||
{
|
||||
int count = ((length - totalBytesRead) > MaxCharBytesSize - offset)
|
||||
? MaxCharBytesSize - offset
|
||||
: length - totalBytesRead;
|
||||
|
||||
int byteCount = _reader.Read(_byteBuffer, offset, count);
|
||||
|
||||
if (byteCount == 0)
|
||||
{
|
||||
throw new EndOfStreamException("Unable to read beyond the end of the stream.");
|
||||
}
|
||||
|
||||
totalBytesRead += byteCount;
|
||||
|
||||
// Above, byteCount is how many bytes we read this time.
|
||||
// Below, byteCount is how many bytes are in the _byteBuffer.
|
||||
byteCount += offset;
|
||||
|
||||
if (byteCount == length)
|
||||
{
|
||||
// pref optimization to avoid reading into a string builder
|
||||
// first iteration and all bytes read then return string directly
|
||||
int charCount = Encoding.UTF8.GetChars(_byteBuffer, 0, byteCount, _charBuffer, 0);
|
||||
return new string(_charBuffer, 0, charCount);
|
||||
}
|
||||
else
|
||||
{
|
||||
int lastFullCharStop = GetLastFullCharStop(byteCount - 1);
|
||||
|
||||
if (builder == null)
|
||||
{
|
||||
builder = new StringBuilder(length);
|
||||
}
|
||||
|
||||
int charCount = Encoding.UTF8.GetChars(_byteBuffer, 0, lastFullCharStop + 1, _charBuffer, 0);
|
||||
builder.Append(_charBuffer, 0, charCount);
|
||||
|
||||
if (lastFullCharStop < byteCount - 1)
|
||||
{
|
||||
offset = byteCount - lastFullCharStop - 1;
|
||||
// copy left over multi byte characters to beginning of buffer for next iteration
|
||||
Array.Copy(_byteBuffer, lastFullCharStop + 1, _byteBuffer, 0, offset);
|
||||
}
|
||||
else
|
||||
{
|
||||
offset = 0;
|
||||
}
|
||||
}
|
||||
} while (totalBytesRead < length);
|
||||
|
||||
return builder.ToString();
|
||||
}
|
||||
|
||||
private int GetLastFullCharStop(int start)
|
||||
{
|
||||
int lookbackPos = start;
|
||||
int bis = 0;
|
||||
while (lookbackPos >= 0)
|
||||
{
|
||||
bis = BytesInSequence(_byteBuffer[lookbackPos]);
|
||||
if (bis == 0)
|
||||
{
|
||||
lookbackPos--;
|
||||
continue;
|
||||
}
|
||||
else if (bis == 1)
|
||||
{
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
lookbackPos--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (bis == start - lookbackPos)
|
||||
{
|
||||
//Full character.
|
||||
return start;
|
||||
}
|
||||
else
|
||||
{
|
||||
return lookbackPos;
|
||||
}
|
||||
}
|
||||
|
||||
private int BytesInSequence(byte b)
|
||||
{
|
||||
if (b <= SeqRange1[1])
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
if (b >= SeqRange2[0] && b <= SeqRange2[1])
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
if (b >= SeqRange3[0] && b <= SeqRange3[1])
|
||||
{
|
||||
return 3;
|
||||
}
|
||||
if (b >= SeqRange4[0] && b <= SeqRange4[1])
|
||||
{
|
||||
return 4;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
private void EnsureBuffers()
|
||||
{
|
||||
if (_byteBuffer == null)
|
||||
{
|
||||
_byteBuffer = new byte[MaxCharBytesSize];
|
||||
}
|
||||
if (_charBuffer == null)
|
||||
{
|
||||
int charBufferSize = Encoding.UTF8.GetMaxCharCount(MaxCharBytesSize);
|
||||
_charBuffer = new char[charBufferSize];
|
||||
}
|
||||
}
|
||||
|
||||
private double ReadDouble()
|
||||
{
|
||||
MovePosition(8);
|
||||
return _reader.ReadDouble();
|
||||
}
|
||||
|
||||
private int ReadInt32()
|
||||
{
|
||||
MovePosition(4);
|
||||
return _reader.ReadInt32();
|
||||
}
|
||||
|
||||
private long ReadInt64()
|
||||
{
|
||||
MovePosition(8);
|
||||
return _reader.ReadInt64();
|
||||
}
|
||||
|
||||
private BsonType ReadType()
|
||||
{
|
||||
MovePosition(1);
|
||||
return (BsonType)_reader.ReadSByte();
|
||||
}
|
||||
|
||||
private void MovePosition(int count)
|
||||
{
|
||||
_currentContext.Position += count;
|
||||
}
|
||||
|
||||
private byte[] ReadBytes(int count)
|
||||
{
|
||||
MovePosition(count);
|
||||
return _reader.ReadBytes(count);
|
||||
}
|
||||
}
|
||||
}
|
||||
180
RRQMCore/XREF/Newtonsoft.Json/Bson/BsonToken.cs
Normal file
180
RRQMCore/XREF/Newtonsoft.Json/Bson/BsonToken.cs
Normal file
@@ -0,0 +1,180 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权(除特别声明或在RRQMCore.XREF命名空间的代码)归作者本人若汝棋茗所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权
|
||||
// CSDN博客:https://blog.csdn.net/qq_40374647
|
||||
// 哔哩哔哩视频:https://space.bilibili.com/94253567
|
||||
// Gitee源代码仓库:https://gitee.com/RRQM_Home
|
||||
// Github源代码仓库:https://github.com/RRQM
|
||||
// 交流QQ群:234762506
|
||||
// 感谢您的下载和使用
|
||||
//------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#region License
|
||||
|
||||
// Copyright (c) 2007 James Newton-King
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the "Software"), to deal in the Software without
|
||||
// restriction, including without limitation the rights to use,
|
||||
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following
|
||||
// conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
// OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#endregion License
|
||||
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace RRQMCore.XREF.Newtonsoft.Json.Bson
|
||||
{
|
||||
internal abstract class BsonToken
|
||||
{
|
||||
public abstract BsonType Type { get; }
|
||||
public BsonToken Parent { get; set; }
|
||||
public int CalculatedSize { get; set; }
|
||||
}
|
||||
|
||||
internal class BsonObject : BsonToken, IEnumerable<BsonProperty>
|
||||
{
|
||||
private readonly List<BsonProperty> _children = new List<BsonProperty>();
|
||||
|
||||
public void Add(string name, BsonToken token)
|
||||
{
|
||||
_children.Add(new BsonProperty { Name = new BsonString(name, false), Value = token });
|
||||
token.Parent = this;
|
||||
}
|
||||
|
||||
public override BsonType Type => BsonType.Object;
|
||||
|
||||
public IEnumerator<BsonProperty> GetEnumerator()
|
||||
{
|
||||
return _children.GetEnumerator();
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return GetEnumerator();
|
||||
}
|
||||
}
|
||||
|
||||
internal class BsonArray : BsonToken, IEnumerable<BsonToken>
|
||||
{
|
||||
private readonly List<BsonToken> _children = new List<BsonToken>();
|
||||
|
||||
public void Add(BsonToken token)
|
||||
{
|
||||
_children.Add(token);
|
||||
token.Parent = this;
|
||||
}
|
||||
|
||||
public override BsonType Type => BsonType.Array;
|
||||
|
||||
public IEnumerator<BsonToken> GetEnumerator()
|
||||
{
|
||||
return _children.GetEnumerator();
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return GetEnumerator();
|
||||
}
|
||||
}
|
||||
|
||||
internal class BsonEmpty : BsonToken
|
||||
{
|
||||
public static readonly BsonToken Null = new BsonEmpty(BsonType.Null);
|
||||
public static readonly BsonToken Undefined = new BsonEmpty(BsonType.Undefined);
|
||||
|
||||
private BsonEmpty(BsonType type)
|
||||
{
|
||||
Type = type;
|
||||
}
|
||||
|
||||
public override BsonType Type { get; }
|
||||
}
|
||||
|
||||
internal class BsonValue : BsonToken
|
||||
{
|
||||
private readonly object _value;
|
||||
private readonly BsonType _type;
|
||||
|
||||
public BsonValue(object value, BsonType type)
|
||||
{
|
||||
_value = value;
|
||||
_type = type;
|
||||
}
|
||||
|
||||
public object Value => _value;
|
||||
|
||||
public override BsonType Type => _type;
|
||||
}
|
||||
|
||||
internal class BsonBoolean : BsonValue
|
||||
{
|
||||
public static readonly BsonBoolean False = new BsonBoolean(false);
|
||||
public static readonly BsonBoolean True = new BsonBoolean(true);
|
||||
|
||||
private BsonBoolean(bool value)
|
||||
: base(value, BsonType.Boolean)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
internal class BsonString : BsonValue
|
||||
{
|
||||
public int ByteCount { get; set; }
|
||||
public bool IncludeLength { get; }
|
||||
|
||||
public BsonString(object value, bool includeLength)
|
||||
: base(value, BsonType.String)
|
||||
{
|
||||
IncludeLength = includeLength;
|
||||
}
|
||||
}
|
||||
|
||||
internal class BsonBinary : BsonValue
|
||||
{
|
||||
public BsonBinaryType BinaryType { get; set; }
|
||||
|
||||
public BsonBinary(byte[] value, BsonBinaryType binaryType)
|
||||
: base(value, BsonType.Binary)
|
||||
{
|
||||
BinaryType = binaryType;
|
||||
}
|
||||
}
|
||||
|
||||
internal class BsonRegex : BsonToken
|
||||
{
|
||||
public BsonString Pattern { get; set; }
|
||||
public BsonString Options { get; set; }
|
||||
|
||||
public BsonRegex(string pattern, string options)
|
||||
{
|
||||
Pattern = new BsonString(pattern, false);
|
||||
Options = new BsonString(options, false);
|
||||
}
|
||||
|
||||
public override BsonType Type => BsonType.Regex;
|
||||
}
|
||||
|
||||
internal class BsonProperty
|
||||
{
|
||||
public BsonString Name { get; set; }
|
||||
public BsonToken Value { get; set; }
|
||||
}
|
||||
}
|
||||
65
RRQMCore/XREF/Newtonsoft.Json/Bson/BsonType.cs
Normal file
65
RRQMCore/XREF/Newtonsoft.Json/Bson/BsonType.cs
Normal file
@@ -0,0 +1,65 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权(除特别声明或在RRQMCore.XREF命名空间的代码)归作者本人若汝棋茗所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权
|
||||
// CSDN博客:https://blog.csdn.net/qq_40374647
|
||||
// 哔哩哔哩视频:https://space.bilibili.com/94253567
|
||||
// Gitee源代码仓库:https://gitee.com/RRQM_Home
|
||||
// Github源代码仓库:https://github.com/RRQM
|
||||
// 交流QQ群:234762506
|
||||
// 感谢您的下载和使用
|
||||
//------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#region License
|
||||
|
||||
// Copyright (c) 2007 James Newton-King
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the "Software"), to deal in the Software without
|
||||
// restriction, including without limitation the rights to use,
|
||||
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following
|
||||
// conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
// OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#endregion License
|
||||
|
||||
namespace RRQMCore.XREF.Newtonsoft.Json.Bson
|
||||
{
|
||||
internal enum BsonType : sbyte
|
||||
{
|
||||
Number = 1,
|
||||
String = 2,
|
||||
Object = 3,
|
||||
Array = 4,
|
||||
Binary = 5,
|
||||
Undefined = 6,
|
||||
Oid = 7,
|
||||
Boolean = 8,
|
||||
Date = 9,
|
||||
Null = 10,
|
||||
Regex = 11,
|
||||
Reference = 12,
|
||||
Code = 13,
|
||||
Symbol = 14,
|
||||
CodeWScope = 15,
|
||||
Integer = 16,
|
||||
TimeStamp = 17,
|
||||
Long = 18,
|
||||
MinKey = -1,
|
||||
MaxKey = 127
|
||||
}
|
||||
}
|
||||
552
RRQMCore/XREF/Newtonsoft.Json/Bson/BsonWriter.cs
Normal file
552
RRQMCore/XREF/Newtonsoft.Json/Bson/BsonWriter.cs
Normal file
@@ -0,0 +1,552 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权(除特别声明或在RRQMCore.XREF命名空间的代码)归作者本人若汝棋茗所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权
|
||||
// CSDN博客:https://blog.csdn.net/qq_40374647
|
||||
// 哔哩哔哩视频:https://space.bilibili.com/94253567
|
||||
// Gitee源代码仓库:https://gitee.com/RRQM_Home
|
||||
// Github源代码仓库:https://github.com/RRQM
|
||||
// 交流QQ群:234762506
|
||||
// 感谢您的下载和使用
|
||||
//------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#region License
|
||||
|
||||
// Copyright (c) 2007 James Newton-King
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the "Software"), to deal in the Software without
|
||||
// restriction, including without limitation the rights to use,
|
||||
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following
|
||||
// conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
// OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#endregion License
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
#if HAVE_BIG_INTEGER
|
||||
using System.Numerics;
|
||||
#endif
|
||||
|
||||
using RRQMCore.XREF.Newtonsoft.Json.Utilities;
|
||||
using System.Globalization;
|
||||
|
||||
namespace RRQMCore.XREF.Newtonsoft.Json.Bson
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a writer that provides a fast, non-cached, forward-only way of generating BSON data.
|
||||
/// </summary>
|
||||
[Obsolete("BSON reading and writing has been moved to its own package. See https://www.nuget.org/packages/RRQMCore.XREF.Newtonsoft.Json.Bson for more details.")]
|
||||
public class BsonWriter : JsonWriter
|
||||
{
|
||||
private readonly BsonBinaryWriter _writer;
|
||||
|
||||
private BsonToken _root;
|
||||
private BsonToken _parent;
|
||||
private string _propertyName;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the <see cref="DateTimeKind" /> used when writing <see cref="DateTime"/> values to BSON.
|
||||
/// When set to <see cref="DateTimeKind.Unspecified" /> no conversion will occur.
|
||||
/// </summary>
|
||||
/// <value>The <see cref="DateTimeKind" /> used when writing <see cref="DateTime"/> values to BSON.</value>
|
||||
public DateTimeKind DateTimeKindHandling
|
||||
{
|
||||
get => _writer.DateTimeKindHandling;
|
||||
set => _writer.DateTimeKindHandling = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="BsonWriter"/> class.
|
||||
/// </summary>
|
||||
/// <param name="stream">The <see cref="Stream"/> to write to.</param>
|
||||
public BsonWriter(Stream stream)
|
||||
{
|
||||
ValidationUtils.ArgumentNotNull(stream, nameof(stream));
|
||||
_writer = new BsonBinaryWriter(new BinaryWriter(stream));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="BsonWriter"/> class.
|
||||
/// </summary>
|
||||
/// <param name="writer">The <see cref="BinaryWriter"/> to write to.</param>
|
||||
public BsonWriter(BinaryWriter writer)
|
||||
{
|
||||
ValidationUtils.ArgumentNotNull(writer, nameof(writer));
|
||||
_writer = new BsonBinaryWriter(writer);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Flushes whatever is in the buffer to the underlying <see cref="Stream"/> and also flushes the underlying stream.
|
||||
/// </summary>
|
||||
public override void Flush()
|
||||
{
|
||||
_writer.Flush();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes the end.
|
||||
/// </summary>
|
||||
/// <param name="token">The token.</param>
|
||||
protected override void WriteEnd(JsonToken token)
|
||||
{
|
||||
base.WriteEnd(token);
|
||||
RemoveParent();
|
||||
|
||||
if (Top == 0)
|
||||
{
|
||||
_writer.WriteToken(_root);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a comment <c>/*...*/</c> containing the specified text.
|
||||
/// </summary>
|
||||
/// <param name="text">Text to place inside the comment.</param>
|
||||
public override void WriteComment(string text)
|
||||
{
|
||||
throw JsonWriterException.Create(this, "Cannot write JSON comment as BSON.", null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes the start of a constructor with the given name.
|
||||
/// </summary>
|
||||
/// <param name="name">The name of the constructor.</param>
|
||||
public override void WriteStartConstructor(string name)
|
||||
{
|
||||
throw JsonWriterException.Create(this, "Cannot write JSON constructor as BSON.", null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes raw JSON.
|
||||
/// </summary>
|
||||
/// <param name="json">The raw JSON to write.</param>
|
||||
public override void WriteRaw(string json)
|
||||
{
|
||||
throw JsonWriterException.Create(this, "Cannot write raw JSON as BSON.", null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes raw JSON where a value is expected and updates the writer's state.
|
||||
/// </summary>
|
||||
/// <param name="json">The raw JSON to write.</param>
|
||||
public override void WriteRawValue(string json)
|
||||
{
|
||||
throw JsonWriterException.Create(this, "Cannot write raw JSON as BSON.", null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes the beginning of a JSON array.
|
||||
/// </summary>
|
||||
public override void WriteStartArray()
|
||||
{
|
||||
base.WriteStartArray();
|
||||
|
||||
AddParent(new BsonArray());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes the beginning of a JSON object.
|
||||
/// </summary>
|
||||
public override void WriteStartObject()
|
||||
{
|
||||
base.WriteStartObject();
|
||||
|
||||
AddParent(new BsonObject());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes the property name of a name/value pair on a JSON object.
|
||||
/// </summary>
|
||||
/// <param name="name">The name of the property.</param>
|
||||
public override void WritePropertyName(string name)
|
||||
{
|
||||
base.WritePropertyName(name);
|
||||
|
||||
_propertyName = name;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Closes this writer.
|
||||
/// If <see cref="JsonWriter.CloseOutput"/> is set to <c>true</c>, the underlying <see cref="Stream"/> is also closed.
|
||||
/// If <see cref="JsonWriter.AutoCompleteOnClose"/> is set to <c>true</c>, the JSON is auto-completed.
|
||||
/// </summary>
|
||||
public override void Close()
|
||||
{
|
||||
base.Close();
|
||||
|
||||
if (CloseOutput)
|
||||
{
|
||||
_writer?.Close();
|
||||
}
|
||||
}
|
||||
|
||||
private void AddParent(BsonToken container)
|
||||
{
|
||||
AddToken(container);
|
||||
_parent = container;
|
||||
}
|
||||
|
||||
private void RemoveParent()
|
||||
{
|
||||
_parent = _parent.Parent;
|
||||
}
|
||||
|
||||
private void AddValue(object value, BsonType type)
|
||||
{
|
||||
AddToken(new BsonValue(value, type));
|
||||
}
|
||||
|
||||
internal void AddToken(BsonToken token)
|
||||
{
|
||||
if (_parent != null)
|
||||
{
|
||||
BsonObject bo = _parent as BsonObject;
|
||||
if (bo != null)
|
||||
{
|
||||
bo.Add(_propertyName, token);
|
||||
_propertyName = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
((BsonArray)_parent).Add(token);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (token.Type != BsonType.Object && token.Type != BsonType.Array)
|
||||
{
|
||||
throw JsonWriterException.Create(this, "Error writing {0} value. BSON must start with an Object or Array.".FormatWith(CultureInfo.InvariantCulture, token.Type), null);
|
||||
}
|
||||
|
||||
_parent = token;
|
||||
_root = token;
|
||||
}
|
||||
}
|
||||
|
||||
#region WriteValue methods
|
||||
|
||||
/// <summary>
|
||||
/// Writes a <see cref="Object"/> value.
|
||||
/// An error will raised if the value cannot be written as a single JSON token.
|
||||
/// </summary>
|
||||
/// <param name="value">The <see cref="Object"/> value to write.</param>
|
||||
public override void WriteValue(object value)
|
||||
{
|
||||
#if HAVE_BIG_INTEGER
|
||||
if (value is BigInteger)
|
||||
{
|
||||
SetWriteState(JsonToken.Integer, null);
|
||||
AddToken(new BsonBinary(((BigInteger)value).ToByteArray(), BsonBinaryType.Binary));
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
base.WriteValue(value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a null value.
|
||||
/// </summary>
|
||||
public override void WriteNull()
|
||||
{
|
||||
base.WriteNull();
|
||||
AddToken(BsonEmpty.Null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes an undefined value.
|
||||
/// </summary>
|
||||
public override void WriteUndefined()
|
||||
{
|
||||
base.WriteUndefined();
|
||||
AddToken(BsonEmpty.Undefined);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a <see cref="String"/> value.
|
||||
/// </summary>
|
||||
/// <param name="value">The <see cref="String"/> value to write.</param>
|
||||
public override void WriteValue(string value)
|
||||
{
|
||||
base.WriteValue(value);
|
||||
AddToken(value == null ? BsonEmpty.Null : new BsonString(value, true));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a <see cref="Int32"/> value.
|
||||
/// </summary>
|
||||
/// <param name="value">The <see cref="Int32"/> value to write.</param>
|
||||
public override void WriteValue(int value)
|
||||
{
|
||||
base.WriteValue(value);
|
||||
AddValue(value, BsonType.Integer);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a <see cref="UInt32"/> value.
|
||||
/// </summary>
|
||||
/// <param name="value">The <see cref="UInt32"/> value to write.</param>
|
||||
|
||||
public override void WriteValue(uint value)
|
||||
{
|
||||
if (value > int.MaxValue)
|
||||
{
|
||||
throw JsonWriterException.Create(this, "Value is too large to fit in a signed 32 bit integer. BSON does not support unsigned values.", null);
|
||||
}
|
||||
|
||||
base.WriteValue(value);
|
||||
AddValue(value, BsonType.Integer);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a <see cref="Int64"/> value.
|
||||
/// </summary>
|
||||
/// <param name="value">The <see cref="Int64"/> value to write.</param>
|
||||
public override void WriteValue(long value)
|
||||
{
|
||||
base.WriteValue(value);
|
||||
AddValue(value, BsonType.Long);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a <see cref="UInt64"/> value.
|
||||
/// </summary>
|
||||
/// <param name="value">The <see cref="UInt64"/> value to write.</param>
|
||||
|
||||
public override void WriteValue(ulong value)
|
||||
{
|
||||
if (value > long.MaxValue)
|
||||
{
|
||||
throw JsonWriterException.Create(this, "Value is too large to fit in a signed 64 bit integer. BSON does not support unsigned values.", null);
|
||||
}
|
||||
|
||||
base.WriteValue(value);
|
||||
AddValue(value, BsonType.Long);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a <see cref="Single"/> value.
|
||||
/// </summary>
|
||||
/// <param name="value">The <see cref="Single"/> value to write.</param>
|
||||
public override void WriteValue(float value)
|
||||
{
|
||||
base.WriteValue(value);
|
||||
AddValue(value, BsonType.Number);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a <see cref="Double"/> value.
|
||||
/// </summary>
|
||||
/// <param name="value">The <see cref="Double"/> value to write.</param>
|
||||
public override void WriteValue(double value)
|
||||
{
|
||||
base.WriteValue(value);
|
||||
AddValue(value, BsonType.Number);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a <see cref="Boolean"/> value.
|
||||
/// </summary>
|
||||
/// <param name="value">The <see cref="Boolean"/> value to write.</param>
|
||||
public override void WriteValue(bool value)
|
||||
{
|
||||
base.WriteValue(value);
|
||||
AddToken(value ? BsonBoolean.True : BsonBoolean.False);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a <see cref="Int16"/> value.
|
||||
/// </summary>
|
||||
/// <param name="value">The <see cref="Int16"/> value to write.</param>
|
||||
public override void WriteValue(short value)
|
||||
{
|
||||
base.WriteValue(value);
|
||||
AddValue(value, BsonType.Integer);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a <see cref="UInt16"/> value.
|
||||
/// </summary>
|
||||
/// <param name="value">The <see cref="UInt16"/> value to write.</param>
|
||||
|
||||
public override void WriteValue(ushort value)
|
||||
{
|
||||
base.WriteValue(value);
|
||||
AddValue(value, BsonType.Integer);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a <see cref="Char"/> value.
|
||||
/// </summary>
|
||||
/// <param name="value">The <see cref="Char"/> value to write.</param>
|
||||
public override void WriteValue(char value)
|
||||
{
|
||||
base.WriteValue(value);
|
||||
string s = null;
|
||||
#if HAVE_CHAR_TO_STRING_WITH_CULTURE
|
||||
s = value.ToString(CultureInfo.InvariantCulture);
|
||||
#else
|
||||
s = value.ToString();
|
||||
#endif
|
||||
AddToken(new BsonString(s, true));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a <see cref="Byte"/> value.
|
||||
/// </summary>
|
||||
/// <param name="value">The <see cref="Byte"/> value to write.</param>
|
||||
public override void WriteValue(byte value)
|
||||
{
|
||||
base.WriteValue(value);
|
||||
AddValue(value, BsonType.Integer);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a <see cref="SByte"/> value.
|
||||
/// </summary>
|
||||
/// <param name="value">The <see cref="SByte"/> value to write.</param>
|
||||
|
||||
public override void WriteValue(sbyte value)
|
||||
{
|
||||
base.WriteValue(value);
|
||||
AddValue(value, BsonType.Integer);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a <see cref="Decimal"/> value.
|
||||
/// </summary>
|
||||
/// <param name="value">The <see cref="Decimal"/> value to write.</param>
|
||||
public override void WriteValue(decimal value)
|
||||
{
|
||||
base.WriteValue(value);
|
||||
AddValue(value, BsonType.Number);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a <see cref="DateTime"/> value.
|
||||
/// </summary>
|
||||
/// <param name="value">The <see cref="DateTime"/> value to write.</param>
|
||||
public override void WriteValue(DateTime value)
|
||||
{
|
||||
base.WriteValue(value);
|
||||
value = DateTimeUtils.EnsureDateTime(value, DateTimeZoneHandling);
|
||||
AddValue(value, BsonType.Date);
|
||||
}
|
||||
|
||||
#if HAVE_DATE_TIME_OFFSET
|
||||
/// <summary>
|
||||
/// Writes a <see cref="DateTimeOffset"/> value.
|
||||
/// </summary>
|
||||
/// <param name="value">The <see cref="DateTimeOffset"/> value to write.</param>
|
||||
public override void WriteValue(DateTimeOffset value)
|
||||
{
|
||||
base.WriteValue(value);
|
||||
AddValue(value, BsonType.Date);
|
||||
}
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Writes a <see cref="Byte"/>[] value.
|
||||
/// </summary>
|
||||
/// <param name="value">The <see cref="Byte"/>[] value to write.</param>
|
||||
public override void WriteValue(byte[] value)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
WriteNull();
|
||||
return;
|
||||
}
|
||||
|
||||
base.WriteValue(value);
|
||||
AddToken(new BsonBinary(value, BsonBinaryType.Binary));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a <see cref="Guid"/> value.
|
||||
/// </summary>
|
||||
/// <param name="value">The <see cref="Guid"/> value to write.</param>
|
||||
public override void WriteValue(Guid value)
|
||||
{
|
||||
base.WriteValue(value);
|
||||
AddToken(new BsonBinary(value.ToByteArray(), BsonBinaryType.Uuid));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a <see cref="TimeSpan"/> value.
|
||||
/// </summary>
|
||||
/// <param name="value">The <see cref="TimeSpan"/> value to write.</param>
|
||||
public override void WriteValue(TimeSpan value)
|
||||
{
|
||||
base.WriteValue(value);
|
||||
AddToken(new BsonString(value.ToString(), true));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a <see cref="Uri"/> value.
|
||||
/// </summary>
|
||||
/// <param name="value">The <see cref="Uri"/> value to write.</param>
|
||||
public override void WriteValue(Uri value)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
WriteNull();
|
||||
return;
|
||||
}
|
||||
|
||||
base.WriteValue(value);
|
||||
AddToken(new BsonString(value.ToString(), true));
|
||||
}
|
||||
|
||||
#endregion WriteValue methods
|
||||
|
||||
/// <summary>
|
||||
/// Writes a <see cref="Byte"/>[] value that represents a BSON object id.
|
||||
/// </summary>
|
||||
/// <param name="value">The Object ID value to write.</param>
|
||||
public void WriteObjectId(byte[] value)
|
||||
{
|
||||
ValidationUtils.ArgumentNotNull(value, nameof(value));
|
||||
|
||||
if (value.Length != 12)
|
||||
{
|
||||
throw JsonWriterException.Create(this, "An object id must be 12 bytes", null);
|
||||
}
|
||||
|
||||
// hack to update the writer state
|
||||
SetWriteState(JsonToken.Undefined, null);
|
||||
AddValue(value, BsonType.Oid);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a BSON regex.
|
||||
/// </summary>
|
||||
/// <param name="pattern">The regex pattern.</param>
|
||||
/// <param name="options">The regex options.</param>
|
||||
public void WriteRegex(string pattern, string options)
|
||||
{
|
||||
ValidationUtils.ArgumentNotNull(pattern, nameof(pattern));
|
||||
|
||||
// hack to update the writer state
|
||||
SetWriteState(JsonToken.Undefined, null);
|
||||
AddToken(new BsonRegex(pattern, options));
|
||||
}
|
||||
}
|
||||
}
|
||||
57
RRQMCore/XREF/Newtonsoft.Json/ConstructorHandling.cs
Normal file
57
RRQMCore/XREF/Newtonsoft.Json/ConstructorHandling.cs
Normal file
@@ -0,0 +1,57 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权(除特别声明或在RRQMCore.XREF命名空间的代码)归作者本人若汝棋茗所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权
|
||||
// CSDN博客:https://blog.csdn.net/qq_40374647
|
||||
// 哔哩哔哩视频:https://space.bilibili.com/94253567
|
||||
// Gitee源代码仓库:https://gitee.com/RRQM_Home
|
||||
// Github源代码仓库:https://github.com/RRQM
|
||||
// 交流QQ群:234762506
|
||||
// 感谢您的下载和使用
|
||||
//------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#region License
|
||||
|
||||
// Copyright (c) 2007 James Newton-King
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the "Software"), to deal in the Software without
|
||||
// restriction, including without limitation the rights to use,
|
||||
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following
|
||||
// conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
// OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#endregion License
|
||||
|
||||
namespace RRQMCore.XREF.Newtonsoft.Json
|
||||
{
|
||||
/// <summary>
|
||||
/// Specifies how constructors are used when initializing objects during deserialization by the <see cref="JsonSerializer"/>.
|
||||
/// </summary>
|
||||
public enum ConstructorHandling
|
||||
{
|
||||
/// <summary>
|
||||
/// First attempt to use the public default constructor, then fall back to a single parameterized constructor, then to the non-public default constructor.
|
||||
/// </summary>
|
||||
Default = 0,
|
||||
|
||||
/// <summary>
|
||||
/// Json.NET will use a non-public default constructor before falling back to a parameterized constructor.
|
||||
/// </summary>
|
||||
AllowNonPublicDefaultConstructor = 1
|
||||
}
|
||||
}
|
||||
225
RRQMCore/XREF/Newtonsoft.Json/Converters/BinaryConverter.cs
Normal file
225
RRQMCore/XREF/Newtonsoft.Json/Converters/BinaryConverter.cs
Normal file
@@ -0,0 +1,225 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权(除特别声明或在RRQMCore.XREF命名空间的代码)归作者本人若汝棋茗所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权
|
||||
// CSDN博客:https://blog.csdn.net/qq_40374647
|
||||
// 哔哩哔哩视频:https://space.bilibili.com/94253567
|
||||
// Gitee源代码仓库:https://gitee.com/RRQM_Home
|
||||
// Github源代码仓库:https://github.com/RRQM
|
||||
// 交流QQ群:234762506
|
||||
// 感谢您的下载和使用
|
||||
//------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#region License
|
||||
|
||||
// Copyright (c) 2007 James Newton-King
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the "Software"), to deal in the Software without
|
||||
// restriction, including without limitation the rights to use,
|
||||
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following
|
||||
// conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
// OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#endregion License
|
||||
|
||||
#if HAVE_LINQ || HAVE_ADO_NET
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using RRQMCore.XREF.Newtonsoft.Json.Utilities;
|
||||
using System.Collections.Generic;
|
||||
#if HAVE_ADO_NET
|
||||
using System.Data.SqlTypes;
|
||||
#endif
|
||||
|
||||
namespace RRQMCore.XREF.Newtonsoft.Json.Converters
|
||||
{
|
||||
/// <summary>
|
||||
/// Converts a binary value to and from a base 64 string value.
|
||||
/// </summary>
|
||||
public class BinaryConverter : JsonConverter
|
||||
{
|
||||
#if HAVE_LINQ
|
||||
private const string BinaryTypeName = "System.Data.Linq.Binary";
|
||||
private const string BinaryToArrayName = "ToArray";
|
||||
private static ReflectionObject _reflectionObject;
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Writes the JSON representation of the object.
|
||||
/// </summary>
|
||||
/// <param name="writer">The <see cref="JsonWriter"/> to write to.</param>
|
||||
/// <param name="value">The value.</param>
|
||||
/// <param name="serializer">The calling serializer.</param>
|
||||
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
writer.WriteNull();
|
||||
return;
|
||||
}
|
||||
|
||||
byte[] data = GetByteArray(value);
|
||||
|
||||
writer.WriteValue(data);
|
||||
}
|
||||
|
||||
private byte[] GetByteArray(object value)
|
||||
{
|
||||
#if HAVE_LINQ
|
||||
if (value.GetType().FullName == BinaryTypeName)
|
||||
{
|
||||
EnsureReflectionObject(value.GetType());
|
||||
return (byte[])_reflectionObject.GetValue(value, BinaryToArrayName);
|
||||
}
|
||||
#endif
|
||||
#if HAVE_ADO_NET
|
||||
if (value is SqlBinary binary)
|
||||
{
|
||||
return binary.Value;
|
||||
}
|
||||
#endif
|
||||
|
||||
throw new JsonSerializationException("Unexpected value type when writing binary: {0}".FormatWith(CultureInfo.InvariantCulture, value.GetType()));
|
||||
}
|
||||
|
||||
#if HAVE_LINQ
|
||||
private static void EnsureReflectionObject(Type t)
|
||||
{
|
||||
if (_reflectionObject == null)
|
||||
{
|
||||
_reflectionObject = ReflectionObject.Create(t, t.GetConstructor(new[] { typeof(byte[]) }), BinaryToArrayName);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Reads the JSON representation of the object.
|
||||
/// </summary>
|
||||
/// <param name="reader">The <see cref="JsonReader"/> to read from.</param>
|
||||
/// <param name="objectType">Type of the object.</param>
|
||||
/// <param name="existingValue">The existing value of object being read.</param>
|
||||
/// <param name="serializer">The calling serializer.</param>
|
||||
/// <returns>The object value.</returns>
|
||||
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
|
||||
{
|
||||
if (reader.TokenType == JsonToken.Null)
|
||||
{
|
||||
if (!ReflectionUtils.IsNullable(objectType))
|
||||
{
|
||||
throw JsonSerializationException.Create(reader, "Cannot convert null value to {0}.".FormatWith(CultureInfo.InvariantCulture, objectType));
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
byte[] data;
|
||||
|
||||
if (reader.TokenType == JsonToken.StartArray)
|
||||
{
|
||||
data = ReadByteArray(reader);
|
||||
}
|
||||
else if (reader.TokenType == JsonToken.String)
|
||||
{
|
||||
// current token is already at base64 string
|
||||
// unable to call ReadAsBytes so do it the old fashion way
|
||||
string encodedData = reader.Value.ToString();
|
||||
data = Convert.FromBase64String(encodedData);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw JsonSerializationException.Create(reader, "Unexpected token parsing binary. Expected String or StartArray, got {0}.".FormatWith(CultureInfo.InvariantCulture, reader.TokenType));
|
||||
}
|
||||
|
||||
Type t = (ReflectionUtils.IsNullableType(objectType))
|
||||
? Nullable.GetUnderlyingType(objectType)
|
||||
: objectType;
|
||||
|
||||
#if HAVE_LINQ
|
||||
if (t.FullName == BinaryTypeName)
|
||||
{
|
||||
EnsureReflectionObject(t);
|
||||
|
||||
return _reflectionObject.Creator(data);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if HAVE_ADO_NET
|
||||
if (t == typeof(SqlBinary))
|
||||
{
|
||||
return new SqlBinary(data);
|
||||
}
|
||||
#endif
|
||||
|
||||
throw JsonSerializationException.Create(reader, "Unexpected object type when writing binary: {0}".FormatWith(CultureInfo.InvariantCulture, objectType));
|
||||
}
|
||||
|
||||
private byte[] ReadByteArray(JsonReader reader)
|
||||
{
|
||||
List<byte> byteList = new List<byte>();
|
||||
|
||||
while (reader.Read())
|
||||
{
|
||||
switch (reader.TokenType)
|
||||
{
|
||||
case JsonToken.Integer:
|
||||
byteList.Add(Convert.ToByte(reader.Value, CultureInfo.InvariantCulture));
|
||||
break;
|
||||
|
||||
case JsonToken.EndArray:
|
||||
return byteList.ToArray();
|
||||
|
||||
case JsonToken.Comment:
|
||||
// skip
|
||||
break;
|
||||
|
||||
default:
|
||||
throw JsonSerializationException.Create(reader, "Unexpected token when reading bytes: {0}".FormatWith(CultureInfo.InvariantCulture, reader.TokenType));
|
||||
}
|
||||
}
|
||||
|
||||
throw JsonSerializationException.Create(reader, "Unexpected end when reading bytes.");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether this instance can convert the specified object type.
|
||||
/// </summary>
|
||||
/// <param name="objectType">Type of the object.</param>
|
||||
/// <returns>
|
||||
/// <c>true</c> if this instance can convert the specified object type; otherwise, <c>false</c>.
|
||||
/// </returns>
|
||||
public override bool CanConvert(Type objectType)
|
||||
{
|
||||
#if HAVE_LINQ
|
||||
if (objectType.FullName == BinaryTypeName)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
#if HAVE_ADO_NET
|
||||
if (objectType == typeof(SqlBinary) || objectType == typeof(SqlBinary?))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,105 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权(除特别声明或在RRQMCore.XREF命名空间的代码)归作者本人若汝棋茗所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权
|
||||
// CSDN博客:https://blog.csdn.net/qq_40374647
|
||||
// 哔哩哔哩视频:https://space.bilibili.com/94253567
|
||||
// Gitee源代码仓库:https://gitee.com/RRQM_Home
|
||||
// Github源代码仓库:https://github.com/RRQM
|
||||
// 交流QQ群:234762506
|
||||
// 感谢您的下载和使用
|
||||
//------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#region License
|
||||
|
||||
// Copyright (c) 2007 James Newton-King
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the "Software"), to deal in the Software without
|
||||
// restriction, including without limitation the rights to use,
|
||||
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following
|
||||
// conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
// OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#endregion License
|
||||
|
||||
using RRQMCore.XREF.Newtonsoft.Json.Bson;
|
||||
using RRQMCore.XREF.Newtonsoft.Json.Utilities;
|
||||
using System;
|
||||
using System.Globalization;
|
||||
|
||||
namespace RRQMCore.XREF.Newtonsoft.Json.Converters
|
||||
{
|
||||
/// <summary>
|
||||
/// Converts a <see cref="BsonObjectId"/> to and from JSON and BSON.
|
||||
/// </summary>
|
||||
[Obsolete("BSON reading and writing has been moved to its own package. See https://www.nuget.org/packages/RRQMCore.XREF.Newtonsoft.Json.Bson for more details.")]
|
||||
public class BsonObjectIdConverter : JsonConverter
|
||||
{
|
||||
/// <summary>
|
||||
/// Writes the JSON representation of the object.
|
||||
/// </summary>
|
||||
/// <param name="writer">The <see cref="JsonWriter"/> to write to.</param>
|
||||
/// <param name="value">The value.</param>
|
||||
/// <param name="serializer">The calling serializer.</param>
|
||||
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
|
||||
{
|
||||
BsonObjectId objectId = (BsonObjectId)value;
|
||||
|
||||
if (writer is BsonWriter bsonWriter)
|
||||
{
|
||||
bsonWriter.WriteObjectId(objectId.Value);
|
||||
}
|
||||
else
|
||||
{
|
||||
writer.WriteValue(objectId.Value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads the JSON representation of the object.
|
||||
/// </summary>
|
||||
/// <param name="reader">The <see cref="JsonReader"/> to read from.</param>
|
||||
/// <param name="objectType">Type of the object.</param>
|
||||
/// <param name="existingValue">The existing value of object being read.</param>
|
||||
/// <param name="serializer">The calling serializer.</param>
|
||||
/// <returns>The object value.</returns>
|
||||
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
|
||||
{
|
||||
if (reader.TokenType != JsonToken.Bytes)
|
||||
{
|
||||
throw new JsonSerializationException("Expected Bytes but got {0}.".FormatWith(CultureInfo.InvariantCulture, reader.TokenType));
|
||||
}
|
||||
|
||||
byte[] value = (byte[])reader.Value;
|
||||
|
||||
return new BsonObjectId(value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether this instance can convert the specified object type.
|
||||
/// </summary>
|
||||
/// <param name="objectType">Type of the object.</param>
|
||||
/// <returns>
|
||||
/// <c>true</c> if this instance can convert the specified object type; otherwise, <c>false</c>.
|
||||
/// </returns>
|
||||
public override bool CanConvert(Type objectType)
|
||||
{
|
||||
return (objectType == typeof(BsonObjectId));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权(除特别声明或在RRQMCore.XREF命名空间的代码)归作者本人若汝棋茗所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权
|
||||
// CSDN博客:https://blog.csdn.net/qq_40374647
|
||||
// 哔哩哔哩视频:https://space.bilibili.com/94253567
|
||||
// Gitee源代码仓库:https://gitee.com/RRQM_Home
|
||||
// Github源代码仓库:https://github.com/RRQM
|
||||
// 交流QQ群:234762506
|
||||
// 感谢您的下载和使用
|
||||
//------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#region License
|
||||
|
||||
// Copyright (c) 2007 James Newton-King
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the "Software"), to deal in the Software without
|
||||
// restriction, including without limitation the rights to use,
|
||||
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following
|
||||
// conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
// OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#endregion License
|
||||
|
||||
using System;
|
||||
|
||||
namespace RRQMCore.XREF.Newtonsoft.Json.Converters
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a custom object.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The object type to convert.</typeparam>
|
||||
public abstract class CustomCreationConverter<T> : JsonConverter
|
||||
{
|
||||
/// <summary>
|
||||
/// Writes the JSON representation of the object.
|
||||
/// </summary>
|
||||
/// <param name="writer">The <see cref="JsonWriter"/> to write to.</param>
|
||||
/// <param name="value">The value.</param>
|
||||
/// <param name="serializer">The calling serializer.</param>
|
||||
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
|
||||
{
|
||||
throw new NotSupportedException("CustomCreationConverter should only be used while deserializing.");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads the JSON representation of the object.
|
||||
/// </summary>
|
||||
/// <param name="reader">The <see cref="JsonReader"/> to read from.</param>
|
||||
/// <param name="objectType">Type of the object.</param>
|
||||
/// <param name="existingValue">The existing value of object being read.</param>
|
||||
/// <param name="serializer">The calling serializer.</param>
|
||||
/// <returns>The object value.</returns>
|
||||
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
|
||||
{
|
||||
if (reader.TokenType == JsonToken.Null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
T value = Create(objectType);
|
||||
if (value == null)
|
||||
{
|
||||
throw new JsonSerializationException("No object created.");
|
||||
}
|
||||
|
||||
serializer.Populate(reader, value);
|
||||
return value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates an object which will then be populated by the serializer.
|
||||
/// </summary>
|
||||
/// <param name="objectType">Type of the object.</param>
|
||||
/// <returns>The created object.</returns>
|
||||
public abstract T Create(Type objectType);
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether this instance can convert the specified object type.
|
||||
/// </summary>
|
||||
/// <param name="objectType">Type of the object.</param>
|
||||
/// <returns>
|
||||
/// <c>true</c> if this instance can convert the specified object type; otherwise, <c>false</c>.
|
||||
/// </returns>
|
||||
public override bool CanConvert(Type objectType)
|
||||
{
|
||||
return typeof(T).IsAssignableFrom(objectType);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether this <see cref="JsonConverter"/> can write JSON.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// <c>true</c> if this <see cref="JsonConverter"/> can write JSON; otherwise, <c>false</c>.
|
||||
/// </value>
|
||||
public override bool CanWrite => false;
|
||||
}
|
||||
}
|
||||
139
RRQMCore/XREF/Newtonsoft.Json/Converters/DataSetConverter.cs
Normal file
139
RRQMCore/XREF/Newtonsoft.Json/Converters/DataSetConverter.cs
Normal file
@@ -0,0 +1,139 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权(除特别声明或在RRQMCore.XREF命名空间的代码)归作者本人若汝棋茗所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权
|
||||
// CSDN博客:https://blog.csdn.net/qq_40374647
|
||||
// 哔哩哔哩视频:https://space.bilibili.com/94253567
|
||||
// Gitee源代码仓库:https://gitee.com/RRQM_Home
|
||||
// Github源代码仓库:https://github.com/RRQM
|
||||
// 交流QQ群:234762506
|
||||
// 感谢您的下载和使用
|
||||
//------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#region License
|
||||
|
||||
// Copyright (c) 2007 James Newton-King
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the "Software"), to deal in the Software without
|
||||
// restriction, including without limitation the rights to use,
|
||||
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following
|
||||
// conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
// OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#endregion License
|
||||
|
||||
#if HAVE_ADO_NET
|
||||
using System;
|
||||
using System.Data;
|
||||
using RRQMCore.XREF.Newtonsoft.Json.Serialization;
|
||||
|
||||
namespace RRQMCore.XREF.Newtonsoft.Json.Converters
|
||||
{
|
||||
/// <summary>
|
||||
/// Converts a <see cref="DataSet"/> to and from JSON.
|
||||
/// </summary>
|
||||
public class DataSetConverter : JsonConverter
|
||||
{
|
||||
/// <summary>
|
||||
/// Writes the JSON representation of the object.
|
||||
/// </summary>
|
||||
/// <param name="writer">The <see cref="JsonWriter"/> to write to.</param>
|
||||
/// <param name="value">The value.</param>
|
||||
/// <param name="serializer">The calling serializer.</param>
|
||||
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
writer.WriteNull();
|
||||
return;
|
||||
}
|
||||
|
||||
DataSet dataSet = (DataSet)value;
|
||||
DefaultContractResolver resolver = serializer.ContractResolver as DefaultContractResolver;
|
||||
|
||||
DataTableConverter converter = new DataTableConverter();
|
||||
|
||||
writer.WriteStartObject();
|
||||
|
||||
foreach (DataTable table in dataSet.Tables)
|
||||
{
|
||||
writer.WritePropertyName((resolver != null) ? resolver.GetResolvedPropertyName(table.TableName) : table.TableName);
|
||||
|
||||
converter.WriteJson(writer, table, serializer);
|
||||
}
|
||||
|
||||
writer.WriteEndObject();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads the JSON representation of the object.
|
||||
/// </summary>
|
||||
/// <param name="reader">The <see cref="JsonReader"/> to read from.</param>
|
||||
/// <param name="objectType">Type of the object.</param>
|
||||
/// <param name="existingValue">The existing value of object being read.</param>
|
||||
/// <param name="serializer">The calling serializer.</param>
|
||||
/// <returns>The object value.</returns>
|
||||
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
|
||||
{
|
||||
if (reader.TokenType == JsonToken.Null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
// handle typed datasets
|
||||
DataSet ds = (objectType == typeof(DataSet))
|
||||
? new DataSet()
|
||||
: (DataSet)Activator.CreateInstance(objectType);
|
||||
|
||||
DataTableConverter converter = new DataTableConverter();
|
||||
|
||||
reader.ReadAndAssert();
|
||||
|
||||
while (reader.TokenType == JsonToken.PropertyName)
|
||||
{
|
||||
DataTable dt = ds.Tables[(string)reader.Value];
|
||||
bool exists = (dt != null);
|
||||
|
||||
dt = (DataTable)converter.ReadJson(reader, typeof(DataTable), dt, serializer);
|
||||
|
||||
if (!exists)
|
||||
{
|
||||
ds.Tables.Add(dt);
|
||||
}
|
||||
|
||||
reader.ReadAndAssert();
|
||||
}
|
||||
|
||||
return ds;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether this instance can convert the specified value type.
|
||||
/// </summary>
|
||||
/// <param name="valueType">Type of the value.</param>
|
||||
/// <returns>
|
||||
/// <c>true</c> if this instance can convert the specified value type; otherwise, <c>false</c>.
|
||||
/// </returns>
|
||||
public override bool CanConvert(Type valueType)
|
||||
{
|
||||
return typeof(DataSet).IsAssignableFrom(valueType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
270
RRQMCore/XREF/Newtonsoft.Json/Converters/DataTableConverter.cs
Normal file
270
RRQMCore/XREF/Newtonsoft.Json/Converters/DataTableConverter.cs
Normal file
@@ -0,0 +1,270 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权(除特别声明或在RRQMCore.XREF命名空间的代码)归作者本人若汝棋茗所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权
|
||||
// CSDN博客:https://blog.csdn.net/qq_40374647
|
||||
// 哔哩哔哩视频:https://space.bilibili.com/94253567
|
||||
// Gitee源代码仓库:https://gitee.com/RRQM_Home
|
||||
// Github源代码仓库:https://github.com/RRQM
|
||||
// 交流QQ群:234762506
|
||||
// 感谢您的下载和使用
|
||||
//------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#region License
|
||||
|
||||
// Copyright (c) 2007 James Newton-King
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the "Software"), to deal in the Software without
|
||||
// restriction, including without limitation the rights to use,
|
||||
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following
|
||||
// conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
// OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#endregion License
|
||||
|
||||
#if HAVE_ADO_NET
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using RRQMCore.XREF.Newtonsoft.Json.Utilities;
|
||||
using System;
|
||||
using System.Data;
|
||||
using RRQMCore.XREF.Newtonsoft.Json.Serialization;
|
||||
|
||||
namespace RRQMCore.XREF.Newtonsoft.Json.Converters
|
||||
{
|
||||
/// <summary>
|
||||
/// Converts a <see cref="DataTable"/> to and from JSON.
|
||||
/// </summary>
|
||||
public class DataTableConverter : JsonConverter
|
||||
{
|
||||
/// <summary>
|
||||
/// Writes the JSON representation of the object.
|
||||
/// </summary>
|
||||
/// <param name="writer">The <see cref="JsonWriter"/> to write to.</param>
|
||||
/// <param name="value">The value.</param>
|
||||
/// <param name="serializer">The calling serializer.</param>
|
||||
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
writer.WriteNull();
|
||||
return;
|
||||
}
|
||||
|
||||
DataTable table = (DataTable)value;
|
||||
DefaultContractResolver resolver = serializer.ContractResolver as DefaultContractResolver;
|
||||
|
||||
writer.WriteStartArray();
|
||||
|
||||
foreach (DataRow row in table.Rows)
|
||||
{
|
||||
writer.WriteStartObject();
|
||||
foreach (DataColumn column in row.Table.Columns)
|
||||
{
|
||||
object columnValue = row[column];
|
||||
|
||||
if (serializer.NullValueHandling == NullValueHandling.Ignore && (columnValue == null || columnValue == DBNull.Value))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
writer.WritePropertyName((resolver != null) ? resolver.GetResolvedPropertyName(column.ColumnName) : column.ColumnName);
|
||||
serializer.Serialize(writer, columnValue);
|
||||
}
|
||||
writer.WriteEndObject();
|
||||
}
|
||||
|
||||
writer.WriteEndArray();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads the JSON representation of the object.
|
||||
/// </summary>
|
||||
/// <param name="reader">The <see cref="JsonReader"/> to read from.</param>
|
||||
/// <param name="objectType">Type of the object.</param>
|
||||
/// <param name="existingValue">The existing value of object being read.</param>
|
||||
/// <param name="serializer">The calling serializer.</param>
|
||||
/// <returns>The object value.</returns>
|
||||
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
|
||||
{
|
||||
if (reader.TokenType == JsonToken.Null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!(existingValue is DataTable dt))
|
||||
{
|
||||
// handle typed datasets
|
||||
dt = (objectType == typeof(DataTable))
|
||||
? new DataTable()
|
||||
: (DataTable)Activator.CreateInstance(objectType);
|
||||
}
|
||||
|
||||
// DataTable is inside a DataSet
|
||||
// populate the name from the property name
|
||||
if (reader.TokenType == JsonToken.PropertyName)
|
||||
{
|
||||
dt.TableName = (string)reader.Value;
|
||||
|
||||
reader.ReadAndAssert();
|
||||
|
||||
if (reader.TokenType == JsonToken.Null)
|
||||
{
|
||||
return dt;
|
||||
}
|
||||
}
|
||||
|
||||
if (reader.TokenType != JsonToken.StartArray)
|
||||
{
|
||||
throw JsonSerializationException.Create(reader, "Unexpected JSON token when reading DataTable. Expected StartArray, got {0}.".FormatWith(CultureInfo.InvariantCulture, reader.TokenType));
|
||||
}
|
||||
|
||||
reader.ReadAndAssert();
|
||||
|
||||
while (reader.TokenType != JsonToken.EndArray)
|
||||
{
|
||||
CreateRow(reader, dt, serializer);
|
||||
|
||||
reader.ReadAndAssert();
|
||||
}
|
||||
|
||||
return dt;
|
||||
}
|
||||
|
||||
private static void CreateRow(JsonReader reader, DataTable dt, JsonSerializer serializer)
|
||||
{
|
||||
DataRow dr = dt.NewRow();
|
||||
reader.ReadAndAssert();
|
||||
|
||||
while (reader.TokenType == JsonToken.PropertyName)
|
||||
{
|
||||
string columnName = (string)reader.Value;
|
||||
|
||||
reader.ReadAndAssert();
|
||||
|
||||
DataColumn column = dt.Columns[columnName];
|
||||
if (column == null)
|
||||
{
|
||||
Type columnType = GetColumnDataType(reader);
|
||||
column = new DataColumn(columnName, columnType);
|
||||
dt.Columns.Add(column);
|
||||
}
|
||||
|
||||
if (column.DataType == typeof(DataTable))
|
||||
{
|
||||
if (reader.TokenType == JsonToken.StartArray)
|
||||
{
|
||||
reader.ReadAndAssert();
|
||||
}
|
||||
|
||||
DataTable nestedDt = new DataTable();
|
||||
|
||||
while (reader.TokenType != JsonToken.EndArray)
|
||||
{
|
||||
CreateRow(reader, nestedDt, serializer);
|
||||
|
||||
reader.ReadAndAssert();
|
||||
}
|
||||
|
||||
dr[columnName] = nestedDt;
|
||||
}
|
||||
else if (column.DataType.IsArray && column.DataType != typeof(byte[]))
|
||||
{
|
||||
if (reader.TokenType == JsonToken.StartArray)
|
||||
{
|
||||
reader.ReadAndAssert();
|
||||
}
|
||||
|
||||
List<object> o = new List<object>();
|
||||
|
||||
while (reader.TokenType != JsonToken.EndArray)
|
||||
{
|
||||
o.Add(reader.Value);
|
||||
reader.ReadAndAssert();
|
||||
}
|
||||
|
||||
Array destinationArray = Array.CreateInstance(column.DataType.GetElementType(), o.Count);
|
||||
((IList)o).CopyTo(destinationArray, 0);
|
||||
|
||||
dr[columnName] = destinationArray;
|
||||
}
|
||||
else
|
||||
{
|
||||
object columnValue = (reader.Value != null)
|
||||
? serializer.Deserialize(reader, column.DataType) ?? DBNull.Value
|
||||
: DBNull.Value;
|
||||
|
||||
dr[columnName] = columnValue;
|
||||
}
|
||||
|
||||
reader.ReadAndAssert();
|
||||
}
|
||||
|
||||
dr.EndEdit();
|
||||
dt.Rows.Add(dr);
|
||||
}
|
||||
|
||||
private static Type GetColumnDataType(JsonReader reader)
|
||||
{
|
||||
JsonToken tokenType = reader.TokenType;
|
||||
|
||||
switch (tokenType)
|
||||
{
|
||||
case JsonToken.Integer:
|
||||
case JsonToken.Boolean:
|
||||
case JsonToken.Float:
|
||||
case JsonToken.String:
|
||||
case JsonToken.Date:
|
||||
case JsonToken.Bytes:
|
||||
return reader.ValueType;
|
||||
|
||||
case JsonToken.Null:
|
||||
case JsonToken.Undefined:
|
||||
return typeof(string);
|
||||
|
||||
case JsonToken.StartArray:
|
||||
reader.ReadAndAssert();
|
||||
if (reader.TokenType == JsonToken.StartObject)
|
||||
{
|
||||
return typeof(DataTable); // nested datatable
|
||||
}
|
||||
|
||||
Type arrayType = GetColumnDataType(reader);
|
||||
return arrayType.MakeArrayType();
|
||||
|
||||
default:
|
||||
throw JsonSerializationException.Create(reader, "Unexpected JSON token when reading DataTable: {0}".FormatWith(CultureInfo.InvariantCulture, tokenType));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether this instance can convert the specified value type.
|
||||
/// </summary>
|
||||
/// <param name="valueType">Type of the value.</param>
|
||||
/// <returns>
|
||||
/// <c>true</c> if this instance can convert the specified value type; otherwise, <c>false</c>.
|
||||
/// </returns>
|
||||
public override bool CanConvert(Type valueType)
|
||||
{
|
||||
return typeof(DataTable).IsAssignableFrom(valueType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,72 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权(除特别声明或在RRQMCore.XREF命名空间的代码)归作者本人若汝棋茗所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权
|
||||
// CSDN博客:https://blog.csdn.net/qq_40374647
|
||||
// 哔哩哔哩视频:https://space.bilibili.com/94253567
|
||||
// Gitee源代码仓库:https://gitee.com/RRQM_Home
|
||||
// Github源代码仓库:https://github.com/RRQM
|
||||
// 交流QQ群:234762506
|
||||
// 感谢您的下载和使用
|
||||
//------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#region License
|
||||
|
||||
// Copyright (c) 2007 James Newton-King
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the "Software"), to deal in the Software without
|
||||
// restriction, including without limitation the rights to use,
|
||||
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following
|
||||
// conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
// OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#endregion License
|
||||
|
||||
using System;
|
||||
|
||||
namespace RRQMCore.XREF.Newtonsoft.Json.Converters
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides a base class for converting a <see cref="DateTime"/> to and from JSON.
|
||||
/// </summary>
|
||||
public abstract class DateTimeConverterBase : JsonConverter
|
||||
{
|
||||
/// <summary>
|
||||
/// Determines whether this instance can convert the specified object type.
|
||||
/// </summary>
|
||||
/// <param name="objectType">Type of the object.</param>
|
||||
/// <returns>
|
||||
/// <c>true</c> if this instance can convert the specified object type; otherwise, <c>false</c>.
|
||||
/// </returns>
|
||||
public override bool CanConvert(Type objectType)
|
||||
{
|
||||
if (objectType == typeof(DateTime) || objectType == typeof(DateTime?))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
#if HAVE_DATE_TIME_OFFSET
|
||||
if (objectType == typeof(DateTimeOffset) || objectType == typeof(DateTimeOffset?))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,296 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权(除特别声明或在RRQMCore.XREF命名空间的代码)归作者本人若汝棋茗所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权
|
||||
// CSDN博客:https://blog.csdn.net/qq_40374647
|
||||
// 哔哩哔哩视频:https://space.bilibili.com/94253567
|
||||
// Gitee源代码仓库:https://gitee.com/RRQM_Home
|
||||
// Github源代码仓库:https://github.com/RRQM
|
||||
// 交流QQ群:234762506
|
||||
// 感谢您的下载和使用
|
||||
//------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#region License
|
||||
|
||||
// Copyright (c) 2007 James Newton-King
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the "Software"), to deal in the Software without
|
||||
// restriction, including without limitation the rights to use,
|
||||
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following
|
||||
// conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
// OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#endregion License
|
||||
|
||||
#if HAVE_FSHARP_TYPES
|
||||
using RRQMCore.XREF.Newtonsoft.Json.Linq;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
#if !HAVE_LINQ
|
||||
using RRQMCore.XREF.Newtonsoft.Json.Utilities.LinqBridge;
|
||||
#else
|
||||
using System.Linq;
|
||||
#endif
|
||||
using System.Reflection;
|
||||
using RRQMCore.XREF.Newtonsoft.Json.Serialization;
|
||||
using System.Globalization;
|
||||
using RRQMCore.XREF.Newtonsoft.Json.Utilities;
|
||||
|
||||
namespace RRQMCore.XREF.Newtonsoft.Json.Converters
|
||||
{
|
||||
/// <summary>
|
||||
/// Converts a F# discriminated union type to and from JSON.
|
||||
/// </summary>
|
||||
public class DiscriminatedUnionConverter : JsonConverter
|
||||
{
|
||||
#region UnionDefinition
|
||||
|
||||
internal class Union
|
||||
{
|
||||
public List<UnionCase> Cases;
|
||||
public FSharpFunction TagReader { get; set; }
|
||||
}
|
||||
|
||||
internal class UnionCase
|
||||
{
|
||||
public int Tag;
|
||||
public string Name;
|
||||
public PropertyInfo[] Fields;
|
||||
public FSharpFunction FieldReader;
|
||||
public FSharpFunction Constructor;
|
||||
}
|
||||
|
||||
#endregion UnionDefinition
|
||||
|
||||
private const string CasePropertyName = "Case";
|
||||
private const string FieldsPropertyName = "Fields";
|
||||
|
||||
private static readonly ThreadSafeStore<Type, Union> UnionCache = new ThreadSafeStore<Type, Union>(CreateUnion);
|
||||
private static readonly ThreadSafeStore<Type, Type> UnionTypeLookupCache = new ThreadSafeStore<Type, Type>(CreateUnionTypeLookup);
|
||||
|
||||
private static Type CreateUnionTypeLookup(Type t)
|
||||
{
|
||||
// this lookup is because cases with fields are derived from union type
|
||||
// need to get declaring type to avoid duplicate Unions in cache
|
||||
|
||||
// hacky but I can't find an API to get the declaring type without GetUnionCases
|
||||
object[] cases = (object[])FSharpUtils.GetUnionCases(null, t, null);
|
||||
|
||||
object caseInfo = cases.First();
|
||||
|
||||
Type unionType = (Type)FSharpUtils.GetUnionCaseInfoDeclaringType(caseInfo);
|
||||
return unionType;
|
||||
}
|
||||
|
||||
private static Union CreateUnion(Type t)
|
||||
{
|
||||
Union u = new Union();
|
||||
|
||||
u.TagReader = (FSharpFunction)FSharpUtils.PreComputeUnionTagReader(null, t, null);
|
||||
u.Cases = new List<UnionCase>();
|
||||
|
||||
object[] cases = (object[])FSharpUtils.GetUnionCases(null, t, null);
|
||||
|
||||
foreach (object unionCaseInfo in cases)
|
||||
{
|
||||
UnionCase unionCase = new UnionCase();
|
||||
unionCase.Tag = (int)FSharpUtils.GetUnionCaseInfoTag(unionCaseInfo);
|
||||
unionCase.Name = (string)FSharpUtils.GetUnionCaseInfoName(unionCaseInfo);
|
||||
unionCase.Fields = (PropertyInfo[])FSharpUtils.GetUnionCaseInfoFields(unionCaseInfo);
|
||||
unionCase.FieldReader = (FSharpFunction)FSharpUtils.PreComputeUnionReader(null, unionCaseInfo, null);
|
||||
unionCase.Constructor = (FSharpFunction)FSharpUtils.PreComputeUnionConstructor(null, unionCaseInfo, null);
|
||||
|
||||
u.Cases.Add(unionCase);
|
||||
}
|
||||
|
||||
return u;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes the JSON representation of the object.
|
||||
/// </summary>
|
||||
/// <param name="writer">The <see cref="JsonWriter"/> to write to.</param>
|
||||
/// <param name="value">The value.</param>
|
||||
/// <param name="serializer">The calling serializer.</param>
|
||||
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
|
||||
{
|
||||
DefaultContractResolver resolver = serializer.ContractResolver as DefaultContractResolver;
|
||||
|
||||
Type unionType = UnionTypeLookupCache.Get(value.GetType());
|
||||
Union union = UnionCache.Get(unionType);
|
||||
|
||||
int tag = (int)union.TagReader.Invoke(value);
|
||||
UnionCase caseInfo = union.Cases.Single(c => c.Tag == tag);
|
||||
|
||||
writer.WriteStartObject();
|
||||
writer.WritePropertyName((resolver != null) ? resolver.GetResolvedPropertyName(CasePropertyName) : CasePropertyName);
|
||||
writer.WriteValue(caseInfo.Name);
|
||||
if (caseInfo.Fields != null && caseInfo.Fields.Length > 0)
|
||||
{
|
||||
object[] fields = (object[])caseInfo.FieldReader.Invoke(value);
|
||||
|
||||
writer.WritePropertyName((resolver != null) ? resolver.GetResolvedPropertyName(FieldsPropertyName) : FieldsPropertyName);
|
||||
writer.WriteStartArray();
|
||||
foreach (object field in fields)
|
||||
{
|
||||
serializer.Serialize(writer, field);
|
||||
}
|
||||
writer.WriteEndArray();
|
||||
}
|
||||
writer.WriteEndObject();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads the JSON representation of the object.
|
||||
/// </summary>
|
||||
/// <param name="reader">The <see cref="JsonReader"/> to read from.</param>
|
||||
/// <param name="objectType">Type of the object.</param>
|
||||
/// <param name="existingValue">The existing value of object being read.</param>
|
||||
/// <param name="serializer">The calling serializer.</param>
|
||||
/// <returns>The object value.</returns>
|
||||
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
|
||||
{
|
||||
if (reader.TokenType == JsonToken.Null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
UnionCase caseInfo = null;
|
||||
string caseName = null;
|
||||
JArray fields = null;
|
||||
|
||||
// start object
|
||||
reader.ReadAndAssert();
|
||||
|
||||
while (reader.TokenType == JsonToken.PropertyName)
|
||||
{
|
||||
string propertyName = reader.Value.ToString();
|
||||
if (string.Equals(propertyName, CasePropertyName, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
reader.ReadAndAssert();
|
||||
|
||||
Union union = UnionCache.Get(objectType);
|
||||
|
||||
caseName = reader.Value.ToString();
|
||||
|
||||
caseInfo = union.Cases.SingleOrDefault(c => c.Name == caseName);
|
||||
|
||||
if (caseInfo == null)
|
||||
{
|
||||
throw JsonSerializationException.Create(reader, "No union type found with the name '{0}'.".FormatWith(CultureInfo.InvariantCulture, caseName));
|
||||
}
|
||||
}
|
||||
else if (string.Equals(propertyName, FieldsPropertyName, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
reader.ReadAndAssert();
|
||||
if (reader.TokenType != JsonToken.StartArray)
|
||||
{
|
||||
throw JsonSerializationException.Create(reader, "Union fields must been an array.");
|
||||
}
|
||||
|
||||
fields = (JArray)JToken.ReadFrom(reader);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw JsonSerializationException.Create(reader, "Unexpected property '{0}' found when reading union.".FormatWith(CultureInfo.InvariantCulture, propertyName));
|
||||
}
|
||||
|
||||
reader.ReadAndAssert();
|
||||
}
|
||||
|
||||
if (caseInfo == null)
|
||||
{
|
||||
throw JsonSerializationException.Create(reader, "No '{0}' property with union name found.".FormatWith(CultureInfo.InvariantCulture, CasePropertyName));
|
||||
}
|
||||
|
||||
object[] typedFieldValues = new object[caseInfo.Fields.Length];
|
||||
|
||||
if (caseInfo.Fields.Length > 0 && fields == null)
|
||||
{
|
||||
throw JsonSerializationException.Create(reader, "No '{0}' property with union fields found.".FormatWith(CultureInfo.InvariantCulture, FieldsPropertyName));
|
||||
}
|
||||
|
||||
if (fields != null)
|
||||
{
|
||||
if (caseInfo.Fields.Length != fields.Count)
|
||||
{
|
||||
throw JsonSerializationException.Create(reader, "The number of field values does not match the number of properties defined by union '{0}'.".FormatWith(CultureInfo.InvariantCulture, caseName));
|
||||
}
|
||||
|
||||
for (int i = 0; i < fields.Count; i++)
|
||||
{
|
||||
JToken t = fields[i];
|
||||
PropertyInfo fieldProperty = caseInfo.Fields[i];
|
||||
|
||||
typedFieldValues[i] = t.ToObject(fieldProperty.PropertyType, serializer);
|
||||
}
|
||||
}
|
||||
|
||||
object[] args = { typedFieldValues };
|
||||
|
||||
return caseInfo.Constructor.Invoke(args);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether this instance can convert the specified object type.
|
||||
/// </summary>
|
||||
/// <param name="objectType">Type of the object.</param>
|
||||
/// <returns>
|
||||
/// <c>true</c> if this instance can convert the specified object type; otherwise, <c>false</c>.
|
||||
/// </returns>
|
||||
public override bool CanConvert(Type objectType)
|
||||
{
|
||||
if (typeof(IEnumerable).IsAssignableFrom(objectType))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// all fsharp objects have CompilationMappingAttribute
|
||||
// get the fsharp assembly from the attribute and initialize latebound methods
|
||||
object[] attributes;
|
||||
#if HAVE_FULL_REFLECTION
|
||||
attributes = objectType.GetCustomAttributes(true);
|
||||
#else
|
||||
attributes = objectType.GetTypeInfo().GetCustomAttributes(true).ToArray();
|
||||
#endif
|
||||
|
||||
bool isFSharpType = false;
|
||||
foreach (object attribute in attributes)
|
||||
{
|
||||
Type attributeType = attribute.GetType();
|
||||
if (attributeType.FullName == "Microsoft.FSharp.Core.CompilationMappingAttribute")
|
||||
{
|
||||
FSharpUtils.EnsureInitialized(attributeType.Assembly());
|
||||
|
||||
isFSharpType = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!isFSharpType)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return (bool)FSharpUtils.IsUnion(null, objectType, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,170 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权(除特别声明或在RRQMCore.XREF命名空间的代码)归作者本人若汝棋茗所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权
|
||||
// CSDN博客:https://blog.csdn.net/qq_40374647
|
||||
// 哔哩哔哩视频:https://space.bilibili.com/94253567
|
||||
// Gitee源代码仓库:https://gitee.com/RRQM_Home
|
||||
// Github源代码仓库:https://github.com/RRQM
|
||||
// 交流QQ群:234762506
|
||||
// 感谢您的下载和使用
|
||||
//------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#region License
|
||||
|
||||
// Copyright (c) 2007 James Newton-King
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the "Software"), to deal in the Software without
|
||||
// restriction, including without limitation the rights to use,
|
||||
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following
|
||||
// conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
// OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#endregion License
|
||||
|
||||
#if HAVE_ENTITY_FRAMEWORK
|
||||
using System;
|
||||
using RRQMCore.XREF.Newtonsoft.Json.Serialization;
|
||||
using System.Globalization;
|
||||
using RRQMCore.XREF.Newtonsoft.Json.Utilities;
|
||||
|
||||
namespace RRQMCore.XREF.Newtonsoft.Json.Converters
|
||||
{
|
||||
/// <summary>
|
||||
/// Converts an Entity Framework <see cref="T:System.Data.EntityKeyMember"/> to and from JSON.
|
||||
/// </summary>
|
||||
public class EntityKeyMemberConverter : JsonConverter
|
||||
{
|
||||
private const string EntityKeyMemberFullTypeName = "System.Data.EntityKeyMember";
|
||||
|
||||
private const string KeyPropertyName = "Key";
|
||||
private const string TypePropertyName = "Type";
|
||||
private const string ValuePropertyName = "Value";
|
||||
|
||||
private static ReflectionObject _reflectionObject;
|
||||
|
||||
/// <summary>
|
||||
/// Writes the JSON representation of the object.
|
||||
/// </summary>
|
||||
/// <param name="writer">The <see cref="JsonWriter"/> to write to.</param>
|
||||
/// <param name="value">The value.</param>
|
||||
/// <param name="serializer">The calling serializer.</param>
|
||||
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
|
||||
{
|
||||
EnsureReflectionObject(value.GetType());
|
||||
|
||||
DefaultContractResolver resolver = serializer.ContractResolver as DefaultContractResolver;
|
||||
|
||||
string keyName = (string)_reflectionObject.GetValue(value, KeyPropertyName);
|
||||
object keyValue = _reflectionObject.GetValue(value, ValuePropertyName);
|
||||
|
||||
Type keyValueType = keyValue?.GetType();
|
||||
|
||||
writer.WriteStartObject();
|
||||
writer.WritePropertyName((resolver != null) ? resolver.GetResolvedPropertyName(KeyPropertyName) : KeyPropertyName);
|
||||
writer.WriteValue(keyName);
|
||||
writer.WritePropertyName((resolver != null) ? resolver.GetResolvedPropertyName(TypePropertyName) : TypePropertyName);
|
||||
writer.WriteValue(keyValueType?.FullName);
|
||||
|
||||
writer.WritePropertyName((resolver != null) ? resolver.GetResolvedPropertyName(ValuePropertyName) : ValuePropertyName);
|
||||
|
||||
if (keyValueType != null)
|
||||
{
|
||||
if (JsonSerializerInternalWriter.TryConvertToString(keyValue, keyValueType, out string valueJson))
|
||||
{
|
||||
writer.WriteValue(valueJson);
|
||||
}
|
||||
else
|
||||
{
|
||||
writer.WriteValue(keyValue);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
writer.WriteNull();
|
||||
}
|
||||
|
||||
writer.WriteEndObject();
|
||||
}
|
||||
|
||||
private static void ReadAndAssertProperty(JsonReader reader, string propertyName)
|
||||
{
|
||||
reader.ReadAndAssert();
|
||||
|
||||
if (reader.TokenType != JsonToken.PropertyName || !string.Equals(reader.Value.ToString(), propertyName, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
throw new JsonSerializationException("Expected JSON property '{0}'.".FormatWith(CultureInfo.InvariantCulture, propertyName));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads the JSON representation of the object.
|
||||
/// </summary>
|
||||
/// <param name="reader">The <see cref="JsonReader"/> to read from.</param>
|
||||
/// <param name="objectType">Type of the object.</param>
|
||||
/// <param name="existingValue">The existing value of object being read.</param>
|
||||
/// <param name="serializer">The calling serializer.</param>
|
||||
/// <returns>The object value.</returns>
|
||||
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
|
||||
{
|
||||
EnsureReflectionObject(objectType);
|
||||
|
||||
object entityKeyMember = _reflectionObject.Creator();
|
||||
|
||||
ReadAndAssertProperty(reader, KeyPropertyName);
|
||||
reader.ReadAndAssert();
|
||||
_reflectionObject.SetValue(entityKeyMember, KeyPropertyName, reader.Value.ToString());
|
||||
|
||||
ReadAndAssertProperty(reader, TypePropertyName);
|
||||
reader.ReadAndAssert();
|
||||
string type = reader.Value.ToString();
|
||||
|
||||
Type t = Type.GetType(type);
|
||||
|
||||
ReadAndAssertProperty(reader, ValuePropertyName);
|
||||
reader.ReadAndAssert();
|
||||
_reflectionObject.SetValue(entityKeyMember, ValuePropertyName, serializer.Deserialize(reader, t));
|
||||
|
||||
reader.ReadAndAssert();
|
||||
|
||||
return entityKeyMember;
|
||||
}
|
||||
|
||||
private static void EnsureReflectionObject(Type objectType)
|
||||
{
|
||||
if (_reflectionObject == null)
|
||||
{
|
||||
_reflectionObject = ReflectionObject.Create(objectType, KeyPropertyName, ValuePropertyName);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether this instance can convert the specified object type.
|
||||
/// </summary>
|
||||
/// <param name="objectType">Type of the object.</param>
|
||||
/// <returns>
|
||||
/// <c>true</c> if this instance can convert the specified object type; otherwise, <c>false</c>.
|
||||
/// </returns>
|
||||
public override bool CanConvert(Type objectType)
|
||||
{
|
||||
return objectType.AssignableToTypeName(EntityKeyMemberFullTypeName, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,188 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权(除特别声明或在RRQMCore.XREF命名空间的代码)归作者本人若汝棋茗所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权
|
||||
// CSDN博客:https://blog.csdn.net/qq_40374647
|
||||
// 哔哩哔哩视频:https://space.bilibili.com/94253567
|
||||
// Gitee源代码仓库:https://gitee.com/RRQM_Home
|
||||
// Github源代码仓库:https://github.com/RRQM
|
||||
// 交流QQ群:234762506
|
||||
// 感谢您的下载和使用
|
||||
//------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#region License
|
||||
|
||||
// Copyright (c) 2007 James Newton-King
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the "Software"), to deal in the Software without
|
||||
// restriction, including without limitation the rights to use,
|
||||
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following
|
||||
// conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
// OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#endregion License
|
||||
|
||||
#if HAVE_DYNAMIC
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Dynamic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using RRQMCore.XREF.Newtonsoft.Json.Utilities;
|
||||
|
||||
namespace RRQMCore.XREF.Newtonsoft.Json.Converters
|
||||
{
|
||||
/// <summary>
|
||||
/// Converts an <see cref="ExpandoObject"/> to and from JSON.
|
||||
/// </summary>
|
||||
public class ExpandoObjectConverter : JsonConverter
|
||||
{
|
||||
/// <summary>
|
||||
/// Writes the JSON representation of the object.
|
||||
/// </summary>
|
||||
/// <param name="writer">The <see cref="JsonWriter"/> to write to.</param>
|
||||
/// <param name="value">The value.</param>
|
||||
/// <param name="serializer">The calling serializer.</param>
|
||||
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
|
||||
{
|
||||
// can write is set to false
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads the JSON representation of the object.
|
||||
/// </summary>
|
||||
/// <param name="reader">The <see cref="JsonReader"/> to read from.</param>
|
||||
/// <param name="objectType">Type of the object.</param>
|
||||
/// <param name="existingValue">The existing value of object being read.</param>
|
||||
/// <param name="serializer">The calling serializer.</param>
|
||||
/// <returns>The object value.</returns>
|
||||
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
|
||||
{
|
||||
return ReadValue(reader);
|
||||
}
|
||||
|
||||
private object ReadValue(JsonReader reader)
|
||||
{
|
||||
if (!reader.MoveToContent())
|
||||
{
|
||||
throw JsonSerializationException.Create(reader, "Unexpected end when reading ExpandoObject.");
|
||||
}
|
||||
|
||||
switch (reader.TokenType)
|
||||
{
|
||||
case JsonToken.StartObject:
|
||||
return ReadObject(reader);
|
||||
|
||||
case JsonToken.StartArray:
|
||||
return ReadList(reader);
|
||||
|
||||
default:
|
||||
if (JsonTokenUtils.IsPrimitiveToken(reader.TokenType))
|
||||
{
|
||||
return reader.Value;
|
||||
}
|
||||
|
||||
throw JsonSerializationException.Create(reader, "Unexpected token when converting ExpandoObject: {0}".FormatWith(CultureInfo.InvariantCulture, reader.TokenType));
|
||||
}
|
||||
}
|
||||
|
||||
private object ReadList(JsonReader reader)
|
||||
{
|
||||
IList<object> list = new List<object>();
|
||||
|
||||
while (reader.Read())
|
||||
{
|
||||
switch (reader.TokenType)
|
||||
{
|
||||
case JsonToken.Comment:
|
||||
break;
|
||||
|
||||
default:
|
||||
object v = ReadValue(reader);
|
||||
|
||||
list.Add(v);
|
||||
break;
|
||||
|
||||
case JsonToken.EndArray:
|
||||
return list;
|
||||
}
|
||||
}
|
||||
|
||||
throw JsonSerializationException.Create(reader, "Unexpected end when reading ExpandoObject.");
|
||||
}
|
||||
|
||||
private object ReadObject(JsonReader reader)
|
||||
{
|
||||
IDictionary<string, object> expandoObject = new ExpandoObject();
|
||||
|
||||
while (reader.Read())
|
||||
{
|
||||
switch (reader.TokenType)
|
||||
{
|
||||
case JsonToken.PropertyName:
|
||||
string propertyName = reader.Value.ToString();
|
||||
|
||||
if (!reader.Read())
|
||||
{
|
||||
throw JsonSerializationException.Create(reader, "Unexpected end when reading ExpandoObject.");
|
||||
}
|
||||
|
||||
object v = ReadValue(reader);
|
||||
|
||||
expandoObject[propertyName] = v;
|
||||
break;
|
||||
|
||||
case JsonToken.Comment:
|
||||
break;
|
||||
|
||||
case JsonToken.EndObject:
|
||||
return expandoObject;
|
||||
}
|
||||
}
|
||||
|
||||
throw JsonSerializationException.Create(reader, "Unexpected end when reading ExpandoObject.");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether this instance can convert the specified object type.
|
||||
/// </summary>
|
||||
/// <param name="objectType">Type of the object.</param>
|
||||
/// <returns>
|
||||
/// <c>true</c> if this instance can convert the specified object type; otherwise, <c>false</c>.
|
||||
/// </returns>
|
||||
public override bool CanConvert(Type objectType)
|
||||
{
|
||||
return (objectType == typeof(ExpandoObject));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether this <see cref="JsonConverter"/> can write JSON.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// <c>true</c> if this <see cref="JsonConverter"/> can write JSON; otherwise, <c>false</c>.
|
||||
/// </value>
|
||||
public override bool CanWrite
|
||||
{
|
||||
get { return false; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
208
RRQMCore/XREF/Newtonsoft.Json/Converters/IsoDateTimeConverter.cs
Normal file
208
RRQMCore/XREF/Newtonsoft.Json/Converters/IsoDateTimeConverter.cs
Normal file
@@ -0,0 +1,208 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权(除特别声明或在RRQMCore.XREF命名空间的代码)归作者本人若汝棋茗所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权
|
||||
// CSDN博客:https://blog.csdn.net/qq_40374647
|
||||
// 哔哩哔哩视频:https://space.bilibili.com/94253567
|
||||
// Gitee源代码仓库:https://gitee.com/RRQM_Home
|
||||
// Github源代码仓库:https://github.com/RRQM
|
||||
// 交流QQ群:234762506
|
||||
// 感谢您的下载和使用
|
||||
//------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#region License
|
||||
|
||||
// Copyright (c) 2007 James Newton-King
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the "Software"), to deal in the Software without
|
||||
// restriction, including without limitation the rights to use,
|
||||
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following
|
||||
// conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
// OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#endregion License
|
||||
|
||||
using RRQMCore.XREF.Newtonsoft.Json.Utilities;
|
||||
using System;
|
||||
using System.Globalization;
|
||||
|
||||
namespace RRQMCore.XREF.Newtonsoft.Json.Converters
|
||||
{
|
||||
/// <summary>
|
||||
/// Converts a <see cref="DateTime"/> to and from the ISO 8601 date format (e.g. <c>"2008-04-12T12:53Z"</c>).
|
||||
/// </summary>
|
||||
public class IsoDateTimeConverter : DateTimeConverterBase
|
||||
{
|
||||
private const string DefaultDateTimeFormat = "yyyy'-'MM'-'dd'T'HH':'mm':'ss.FFFFFFFK";
|
||||
|
||||
private DateTimeStyles _dateTimeStyles = DateTimeStyles.RoundtripKind;
|
||||
private string _dateTimeFormat;
|
||||
private CultureInfo _culture;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the date time styles used when converting a date to and from JSON.
|
||||
/// </summary>
|
||||
/// <value>The date time styles used when converting a date to and from JSON.</value>
|
||||
public DateTimeStyles DateTimeStyles
|
||||
{
|
||||
get => _dateTimeStyles;
|
||||
set => _dateTimeStyles = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the date time format used when converting a date to and from JSON.
|
||||
/// </summary>
|
||||
/// <value>The date time format used when converting a date to and from JSON.</value>
|
||||
public string DateTimeFormat
|
||||
{
|
||||
get => _dateTimeFormat ?? string.Empty;
|
||||
set => _dateTimeFormat = (string.IsNullOrEmpty(value)) ? null : value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the culture used when converting a date to and from JSON.
|
||||
/// </summary>
|
||||
/// <value>The culture used when converting a date to and from JSON.</value>
|
||||
public CultureInfo Culture
|
||||
{
|
||||
get => _culture ?? CultureInfo.CurrentCulture;
|
||||
set => _culture = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes the JSON representation of the object.
|
||||
/// </summary>
|
||||
/// <param name="writer">The <see cref="JsonWriter"/> to write to.</param>
|
||||
/// <param name="value">The value.</param>
|
||||
/// <param name="serializer">The calling serializer.</param>
|
||||
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
|
||||
{
|
||||
string text;
|
||||
|
||||
if (value is DateTime dateTime)
|
||||
{
|
||||
if ((_dateTimeStyles & DateTimeStyles.AdjustToUniversal) == DateTimeStyles.AdjustToUniversal
|
||||
|| (_dateTimeStyles & DateTimeStyles.AssumeUniversal) == DateTimeStyles.AssumeUniversal)
|
||||
{
|
||||
dateTime = dateTime.ToUniversalTime();
|
||||
}
|
||||
|
||||
text = dateTime.ToString(_dateTimeFormat ?? DefaultDateTimeFormat, Culture);
|
||||
}
|
||||
#if HAVE_DATE_TIME_OFFSET
|
||||
else if (value is DateTimeOffset dateTimeOffset)
|
||||
{
|
||||
if ((_dateTimeStyles & DateTimeStyles.AdjustToUniversal) == DateTimeStyles.AdjustToUniversal
|
||||
|| (_dateTimeStyles & DateTimeStyles.AssumeUniversal) == DateTimeStyles.AssumeUniversal)
|
||||
{
|
||||
dateTimeOffset = dateTimeOffset.ToUniversalTime();
|
||||
}
|
||||
|
||||
text = dateTimeOffset.ToString(_dateTimeFormat ?? DefaultDateTimeFormat, Culture);
|
||||
}
|
||||
#endif
|
||||
else
|
||||
{
|
||||
throw new JsonSerializationException("Unexpected value when converting date. Expected DateTime or DateTimeOffset, got {0}.".FormatWith(CultureInfo.InvariantCulture, ReflectionUtils.GetObjectType(value)));
|
||||
}
|
||||
|
||||
writer.WriteValue(text);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads the JSON representation of the object.
|
||||
/// </summary>
|
||||
/// <param name="reader">The <see cref="JsonReader"/> to read from.</param>
|
||||
/// <param name="objectType">Type of the object.</param>
|
||||
/// <param name="existingValue">The existing value of object being read.</param>
|
||||
/// <param name="serializer">The calling serializer.</param>
|
||||
/// <returns>The object value.</returns>
|
||||
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
|
||||
{
|
||||
bool nullable = ReflectionUtils.IsNullableType(objectType);
|
||||
if (reader.TokenType == JsonToken.Null)
|
||||
{
|
||||
if (!nullable)
|
||||
{
|
||||
throw JsonSerializationException.Create(reader, "Cannot convert null value to {0}.".FormatWith(CultureInfo.InvariantCulture, objectType));
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
#if HAVE_DATE_TIME_OFFSET
|
||||
Type t = (nullable)
|
||||
? Nullable.GetUnderlyingType(objectType)
|
||||
: objectType;
|
||||
#endif
|
||||
|
||||
if (reader.TokenType == JsonToken.Date)
|
||||
{
|
||||
#if HAVE_DATE_TIME_OFFSET
|
||||
if (t == typeof(DateTimeOffset))
|
||||
{
|
||||
return (reader.Value is DateTimeOffset) ? reader.Value : new DateTimeOffset((DateTime)reader.Value);
|
||||
}
|
||||
|
||||
// converter is expected to return a DateTime
|
||||
if (reader.Value is DateTimeOffset offset)
|
||||
{
|
||||
return offset.DateTime;
|
||||
}
|
||||
#endif
|
||||
|
||||
return reader.Value;
|
||||
}
|
||||
|
||||
if (reader.TokenType != JsonToken.String)
|
||||
{
|
||||
throw JsonSerializationException.Create(reader, "Unexpected token parsing date. Expected String, got {0}.".FormatWith(CultureInfo.InvariantCulture, reader.TokenType));
|
||||
}
|
||||
|
||||
string dateText = reader.Value.ToString();
|
||||
|
||||
if (string.IsNullOrEmpty(dateText) && nullable)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
#if HAVE_DATE_TIME_OFFSET
|
||||
if (t == typeof(DateTimeOffset))
|
||||
{
|
||||
if (!string.IsNullOrEmpty(_dateTimeFormat))
|
||||
{
|
||||
return DateTimeOffset.ParseExact(dateText, _dateTimeFormat, Culture, _dateTimeStyles);
|
||||
}
|
||||
else
|
||||
{
|
||||
return DateTimeOffset.Parse(dateText, Culture, _dateTimeStyles);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!string.IsNullOrEmpty(_dateTimeFormat))
|
||||
{
|
||||
return DateTime.ParseExact(dateText, _dateTimeFormat, Culture, _dateTimeStyles);
|
||||
}
|
||||
else
|
||||
{
|
||||
return DateTime.Parse(dateText, Culture, _dateTimeStyles);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,138 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权(除特别声明或在RRQMCore.XREF命名空间的代码)归作者本人若汝棋茗所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权
|
||||
// CSDN博客:https://blog.csdn.net/qq_40374647
|
||||
// 哔哩哔哩视频:https://space.bilibili.com/94253567
|
||||
// Gitee源代码仓库:https://gitee.com/RRQM_Home
|
||||
// Github源代码仓库:https://github.com/RRQM
|
||||
// 交流QQ群:234762506
|
||||
// 感谢您的下载和使用
|
||||
//------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#region License
|
||||
|
||||
// Copyright (c) 2007 James Newton-King
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the "Software"), to deal in the Software without
|
||||
// restriction, including without limitation the rights to use,
|
||||
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following
|
||||
// conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
// OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#endregion License
|
||||
|
||||
using RRQMCore.XREF.Newtonsoft.Json.Utilities;
|
||||
using System;
|
||||
using System.Globalization;
|
||||
|
||||
namespace RRQMCore.XREF.Newtonsoft.Json.Converters
|
||||
{
|
||||
/// <summary>
|
||||
/// Converts a <see cref="DateTime"/> to and from a JavaScript <c>Date</c> constructor (e.g. <c>new Date(52231943)</c>).
|
||||
/// </summary>
|
||||
public class JavaScriptDateTimeConverter : DateTimeConverterBase
|
||||
{
|
||||
/// <summary>
|
||||
/// Writes the JSON representation of the object.
|
||||
/// </summary>
|
||||
/// <param name="writer">The <see cref="JsonWriter"/> to write to.</param>
|
||||
/// <param name="value">The value.</param>
|
||||
/// <param name="serializer">The calling serializer.</param>
|
||||
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
|
||||
{
|
||||
long ticks;
|
||||
|
||||
if (value is DateTime dateTime)
|
||||
{
|
||||
DateTime utcDateTime = dateTime.ToUniversalTime();
|
||||
ticks = DateTimeUtils.ConvertDateTimeToJavaScriptTicks(utcDateTime);
|
||||
}
|
||||
#if HAVE_DATE_TIME_OFFSET
|
||||
else if (value is DateTimeOffset dateTimeOffset)
|
||||
{
|
||||
DateTimeOffset utcDateTimeOffset = dateTimeOffset.ToUniversalTime();
|
||||
ticks = DateTimeUtils.ConvertDateTimeToJavaScriptTicks(utcDateTimeOffset.UtcDateTime);
|
||||
}
|
||||
#endif
|
||||
else
|
||||
{
|
||||
throw new JsonSerializationException("Expected date object value.");
|
||||
}
|
||||
|
||||
writer.WriteStartConstructor("Date");
|
||||
writer.WriteValue(ticks);
|
||||
writer.WriteEndConstructor();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads the JSON representation of the object.
|
||||
/// </summary>
|
||||
/// <param name="reader">The <see cref="JsonReader"/> to read from.</param>
|
||||
/// <param name="objectType">Type of the object.</param>
|
||||
/// <param name="existingValue">The existing property value of the JSON that is being converted.</param>
|
||||
/// <param name="serializer">The calling serializer.</param>
|
||||
/// <returns>The object value.</returns>
|
||||
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
|
||||
{
|
||||
if (reader.TokenType == JsonToken.Null)
|
||||
{
|
||||
if (!ReflectionUtils.IsNullable(objectType))
|
||||
{
|
||||
throw JsonSerializationException.Create(reader, "Cannot convert null value to {0}.".FormatWith(CultureInfo.InvariantCulture, objectType));
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
if (reader.TokenType != JsonToken.StartConstructor || !string.Equals(reader.Value.ToString(), "Date", StringComparison.Ordinal))
|
||||
{
|
||||
throw JsonSerializationException.Create(reader, "Unexpected token or value when parsing date. Token: {0}, Value: {1}".FormatWith(CultureInfo.InvariantCulture, reader.TokenType, reader.Value));
|
||||
}
|
||||
|
||||
reader.Read();
|
||||
|
||||
if (reader.TokenType != JsonToken.Integer)
|
||||
{
|
||||
throw JsonSerializationException.Create(reader, "Unexpected token parsing date. Expected Integer, got {0}.".FormatWith(CultureInfo.InvariantCulture, reader.TokenType));
|
||||
}
|
||||
|
||||
long ticks = (long)reader.Value;
|
||||
|
||||
DateTime d = DateTimeUtils.ConvertJavaScriptTicksToDateTime(ticks);
|
||||
|
||||
reader.Read();
|
||||
|
||||
if (reader.TokenType != JsonToken.EndConstructor)
|
||||
{
|
||||
throw JsonSerializationException.Create(reader, "Unexpected token parsing date. Expected EndConstructor, got {0}.".FormatWith(CultureInfo.InvariantCulture, reader.TokenType));
|
||||
}
|
||||
|
||||
#if HAVE_DATE_TIME_OFFSET
|
||||
Type t = (ReflectionUtils.IsNullableType(objectType))
|
||||
? Nullable.GetUnderlyingType(objectType)
|
||||
: objectType;
|
||||
if (t == typeof(DateTimeOffset))
|
||||
{
|
||||
return new DateTimeOffset(d);
|
||||
}
|
||||
#endif
|
||||
return d;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,166 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权(除特别声明或在RRQMCore.XREF命名空间的代码)归作者本人若汝棋茗所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权
|
||||
// CSDN博客:https://blog.csdn.net/qq_40374647
|
||||
// 哔哩哔哩视频:https://space.bilibili.com/94253567
|
||||
// Gitee源代码仓库:https://gitee.com/RRQM_Home
|
||||
// Github源代码仓库:https://github.com/RRQM
|
||||
// 交流QQ群:234762506
|
||||
// 感谢您的下载和使用
|
||||
//------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#region License
|
||||
|
||||
// Copyright (c) 2007 James Newton-King
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the "Software"), to deal in the Software without
|
||||
// restriction, including without limitation the rights to use,
|
||||
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following
|
||||
// conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
// OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#endregion License
|
||||
|
||||
using RRQMCore.XREF.Newtonsoft.Json.Serialization;
|
||||
using RRQMCore.XREF.Newtonsoft.Json.Utilities;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace RRQMCore.XREF.Newtonsoft.Json.Converters
|
||||
{
|
||||
/// <summary>
|
||||
/// Converts a <see cref="KeyValuePair{TKey,TValue}"/> to and from JSON.
|
||||
/// </summary>
|
||||
public class KeyValuePairConverter : JsonConverter
|
||||
{
|
||||
private const string KeyName = "Key";
|
||||
private const string ValueName = "Value";
|
||||
|
||||
private static readonly ThreadSafeStore<Type, ReflectionObject> ReflectionObjectPerType = new ThreadSafeStore<Type, ReflectionObject>(InitializeReflectionObject);
|
||||
|
||||
private static ReflectionObject InitializeReflectionObject(Type t)
|
||||
{
|
||||
IList<Type> genericArguments = t.GetGenericArguments();
|
||||
Type keyType = genericArguments[0];
|
||||
Type valueType = genericArguments[1];
|
||||
|
||||
return ReflectionObject.Create(t, t.GetConstructor(new[] { keyType, valueType }), KeyName, ValueName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes the JSON representation of the object.
|
||||
/// </summary>
|
||||
/// <param name="writer">The <see cref="JsonWriter"/> to write to.</param>
|
||||
/// <param name="value">The value.</param>
|
||||
/// <param name="serializer">The calling serializer.</param>
|
||||
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
|
||||
{
|
||||
ReflectionObject reflectionObject = ReflectionObjectPerType.Get(value.GetType());
|
||||
|
||||
DefaultContractResolver resolver = serializer.ContractResolver as DefaultContractResolver;
|
||||
|
||||
writer.WriteStartObject();
|
||||
writer.WritePropertyName((resolver != null) ? resolver.GetResolvedPropertyName(KeyName) : KeyName);
|
||||
serializer.Serialize(writer, reflectionObject.GetValue(value, KeyName), reflectionObject.GetType(KeyName));
|
||||
writer.WritePropertyName((resolver != null) ? resolver.GetResolvedPropertyName(ValueName) : ValueName);
|
||||
serializer.Serialize(writer, reflectionObject.GetValue(value, ValueName), reflectionObject.GetType(ValueName));
|
||||
writer.WriteEndObject();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads the JSON representation of the object.
|
||||
/// </summary>
|
||||
/// <param name="reader">The <see cref="JsonReader"/> to read from.</param>
|
||||
/// <param name="objectType">Type of the object.</param>
|
||||
/// <param name="existingValue">The existing value of object being read.</param>
|
||||
/// <param name="serializer">The calling serializer.</param>
|
||||
/// <returns>The object value.</returns>
|
||||
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
|
||||
{
|
||||
if (reader.TokenType == JsonToken.Null)
|
||||
{
|
||||
if (!ReflectionUtils.IsNullableType(objectType))
|
||||
{
|
||||
throw JsonSerializationException.Create(reader, "Cannot convert null value to KeyValuePair.");
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
object key = null;
|
||||
object value = null;
|
||||
|
||||
reader.ReadAndAssert();
|
||||
|
||||
Type t = ReflectionUtils.IsNullableType(objectType)
|
||||
? Nullable.GetUnderlyingType(objectType)
|
||||
: objectType;
|
||||
|
||||
ReflectionObject reflectionObject = ReflectionObjectPerType.Get(t);
|
||||
JsonContract keyContract = serializer.ContractResolver.ResolveContract(reflectionObject.GetType(KeyName));
|
||||
JsonContract valueContract = serializer.ContractResolver.ResolveContract(reflectionObject.GetType(ValueName));
|
||||
|
||||
while (reader.TokenType == JsonToken.PropertyName)
|
||||
{
|
||||
string propertyName = reader.Value.ToString();
|
||||
if (string.Equals(propertyName, KeyName, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
reader.ReadForTypeAndAssert(keyContract, false);
|
||||
|
||||
key = serializer.Deserialize(reader, keyContract.UnderlyingType);
|
||||
}
|
||||
else if (string.Equals(propertyName, ValueName, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
reader.ReadForTypeAndAssert(valueContract, false);
|
||||
|
||||
value = serializer.Deserialize(reader, valueContract.UnderlyingType);
|
||||
}
|
||||
else
|
||||
{
|
||||
reader.Skip();
|
||||
}
|
||||
|
||||
reader.ReadAndAssert();
|
||||
}
|
||||
|
||||
return reflectionObject.Creator(key, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether this instance can convert the specified object type.
|
||||
/// </summary>
|
||||
/// <param name="objectType">Type of the object.</param>
|
||||
/// <returns>
|
||||
/// <c>true</c> if this instance can convert the specified object type; otherwise, <c>false</c>.
|
||||
/// </returns>
|
||||
public override bool CanConvert(Type objectType)
|
||||
{
|
||||
Type t = (ReflectionUtils.IsNullableType(objectType))
|
||||
? Nullable.GetUnderlyingType(objectType)
|
||||
: objectType;
|
||||
|
||||
if (t.IsValueType() && t.IsGenericType())
|
||||
{
|
||||
return (t.GetGenericTypeDefinition() == typeof(KeyValuePair<,>));
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
254
RRQMCore/XREF/Newtonsoft.Json/Converters/RegexConverter.cs
Normal file
254
RRQMCore/XREF/Newtonsoft.Json/Converters/RegexConverter.cs
Normal file
@@ -0,0 +1,254 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权(除特别声明或在RRQMCore.XREF命名空间的代码)归作者本人若汝棋茗所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权
|
||||
// CSDN博客:https://blog.csdn.net/qq_40374647
|
||||
// 哔哩哔哩视频:https://space.bilibili.com/94253567
|
||||
// Gitee源代码仓库:https://gitee.com/RRQM_Home
|
||||
// Github源代码仓库:https://github.com/RRQM
|
||||
// 交流QQ群:234762506
|
||||
// 感谢您的下载和使用
|
||||
//------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#region License
|
||||
|
||||
// Copyright (c) 2007 James Newton-King
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the "Software"), to deal in the Software without
|
||||
// restriction, including without limitation the rights to use,
|
||||
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following
|
||||
// conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
// OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#endregion License
|
||||
|
||||
using RRQMCore.XREF.Newtonsoft.Json.Bson;
|
||||
using RRQMCore.XREF.Newtonsoft.Json.Serialization;
|
||||
using RRQMCore.XREF.Newtonsoft.Json.Utilities;
|
||||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace RRQMCore.XREF.Newtonsoft.Json.Converters
|
||||
{
|
||||
/// <summary>
|
||||
/// Converts a <see cref="Regex"/> to and from JSON and BSON.
|
||||
/// </summary>
|
||||
public class RegexConverter : JsonConverter
|
||||
{
|
||||
private const string PatternName = "Pattern";
|
||||
private const string OptionsName = "Options";
|
||||
|
||||
/// <summary>
|
||||
/// Writes the JSON representation of the object.
|
||||
/// </summary>
|
||||
/// <param name="writer">The <see cref="JsonWriter"/> to write to.</param>
|
||||
/// <param name="value">The value.</param>
|
||||
/// <param name="serializer">The calling serializer.</param>
|
||||
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
writer.WriteNull();
|
||||
return;
|
||||
}
|
||||
|
||||
Regex regex = (Regex)value;
|
||||
|
||||
#pragma warning disable 618
|
||||
if (writer is BsonWriter bsonWriter)
|
||||
{
|
||||
WriteBson(bsonWriter, regex);
|
||||
}
|
||||
#pragma warning restore 618
|
||||
else
|
||||
{
|
||||
WriteJson(writer, regex, serializer);
|
||||
}
|
||||
}
|
||||
|
||||
private bool HasFlag(RegexOptions options, RegexOptions flag)
|
||||
{
|
||||
return ((options & flag) == flag);
|
||||
}
|
||||
|
||||
#pragma warning disable 618
|
||||
|
||||
private void WriteBson(BsonWriter writer, Regex regex)
|
||||
{
|
||||
// Regular expression - The first cstring is the regex pattern, the second
|
||||
// is the regex options string. Options are identified by characters, which
|
||||
// must be stored in alphabetical order. Valid options are 'i' for case
|
||||
// insensitive matching, 'm' for multiline matching, 'x' for verbose mode,
|
||||
// 'l' to make \w, \W, etc. locale dependent, 's' for dotall mode
|
||||
// ('.' matches everything), and 'u' to make \w, \W, etc. match unicode.
|
||||
|
||||
string options = null;
|
||||
|
||||
if (HasFlag(regex.Options, RegexOptions.IgnoreCase))
|
||||
{
|
||||
options += "i";
|
||||
}
|
||||
|
||||
if (HasFlag(regex.Options, RegexOptions.Multiline))
|
||||
{
|
||||
options += "m";
|
||||
}
|
||||
|
||||
if (HasFlag(regex.Options, RegexOptions.Singleline))
|
||||
{
|
||||
options += "s";
|
||||
}
|
||||
|
||||
options += "u";
|
||||
|
||||
if (HasFlag(regex.Options, RegexOptions.ExplicitCapture))
|
||||
{
|
||||
options += "x";
|
||||
}
|
||||
|
||||
writer.WriteRegex(regex.ToString(), options);
|
||||
}
|
||||
|
||||
#pragma warning restore 618
|
||||
|
||||
private void WriteJson(JsonWriter writer, Regex regex, JsonSerializer serializer)
|
||||
{
|
||||
DefaultContractResolver resolver = serializer.ContractResolver as DefaultContractResolver;
|
||||
|
||||
writer.WriteStartObject();
|
||||
writer.WritePropertyName((resolver != null) ? resolver.GetResolvedPropertyName(PatternName) : PatternName);
|
||||
writer.WriteValue(regex.ToString());
|
||||
writer.WritePropertyName((resolver != null) ? resolver.GetResolvedPropertyName(OptionsName) : OptionsName);
|
||||
serializer.Serialize(writer, regex.Options);
|
||||
writer.WriteEndObject();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads the JSON representation of the object.
|
||||
/// </summary>
|
||||
/// <param name="reader">The <see cref="JsonReader"/> to read from.</param>
|
||||
/// <param name="objectType">Type of the object.</param>
|
||||
/// <param name="existingValue">The existing value of object being read.</param>
|
||||
/// <param name="serializer">The calling serializer.</param>
|
||||
/// <returns>The object value.</returns>
|
||||
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
|
||||
{
|
||||
switch (reader.TokenType)
|
||||
{
|
||||
case JsonToken.StartObject:
|
||||
return ReadRegexObject(reader, serializer);
|
||||
|
||||
case JsonToken.String:
|
||||
return ReadRegexString(reader);
|
||||
|
||||
case JsonToken.Null:
|
||||
return null;
|
||||
}
|
||||
|
||||
throw JsonSerializationException.Create(reader, "Unexpected token when reading Regex.");
|
||||
}
|
||||
|
||||
private object ReadRegexString(JsonReader reader)
|
||||
{
|
||||
string regexText = (string)reader.Value;
|
||||
|
||||
if (regexText.Length > 0 && regexText[0] == '/')
|
||||
{
|
||||
int patternOptionDelimiterIndex = regexText.LastIndexOf('/');
|
||||
|
||||
if (patternOptionDelimiterIndex > 0)
|
||||
{
|
||||
string patternText = regexText.Substring(1, patternOptionDelimiterIndex - 1);
|
||||
string optionsText = regexText.Substring(patternOptionDelimiterIndex + 1);
|
||||
|
||||
RegexOptions options = MiscellaneousUtils.GetRegexOptions(optionsText);
|
||||
|
||||
return new Regex(patternText, options);
|
||||
}
|
||||
}
|
||||
|
||||
throw JsonSerializationException.Create(reader, "Regex pattern must be enclosed by slashes.");
|
||||
}
|
||||
|
||||
private Regex ReadRegexObject(JsonReader reader, JsonSerializer serializer)
|
||||
{
|
||||
string pattern = null;
|
||||
RegexOptions? options = null;
|
||||
|
||||
while (reader.Read())
|
||||
{
|
||||
switch (reader.TokenType)
|
||||
{
|
||||
case JsonToken.PropertyName:
|
||||
string propertyName = reader.Value.ToString();
|
||||
|
||||
if (!reader.Read())
|
||||
{
|
||||
throw JsonSerializationException.Create(reader, "Unexpected end when reading Regex.");
|
||||
}
|
||||
|
||||
if (string.Equals(propertyName, PatternName, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
pattern = (string)reader.Value;
|
||||
}
|
||||
else if (string.Equals(propertyName, OptionsName, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
options = serializer.Deserialize<RegexOptions>(reader);
|
||||
}
|
||||
else
|
||||
{
|
||||
reader.Skip();
|
||||
}
|
||||
break;
|
||||
|
||||
case JsonToken.Comment:
|
||||
break;
|
||||
|
||||
case JsonToken.EndObject:
|
||||
if (pattern == null)
|
||||
{
|
||||
throw JsonSerializationException.Create(reader, "Error deserializing Regex. No pattern found.");
|
||||
}
|
||||
|
||||
return new Regex(pattern, options ?? RegexOptions.None);
|
||||
}
|
||||
}
|
||||
|
||||
throw JsonSerializationException.Create(reader, "Unexpected end when reading Regex.");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether this instance can convert the specified object type.
|
||||
/// </summary>
|
||||
/// <param name="objectType">Type of the object.</param>
|
||||
/// <returns>
|
||||
/// <c>true</c> if this instance can convert the specified object type; otherwise, <c>false</c>.
|
||||
/// </returns>
|
||||
public override bool CanConvert(Type objectType)
|
||||
{
|
||||
return objectType.Name == nameof(Regex) && IsRegex(objectType);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||
private bool IsRegex(Type objectType)
|
||||
{
|
||||
return (objectType == typeof(Regex));
|
||||
}
|
||||
}
|
||||
}
|
||||
193
RRQMCore/XREF/Newtonsoft.Json/Converters/StringEnumConverter.cs
Normal file
193
RRQMCore/XREF/Newtonsoft.Json/Converters/StringEnumConverter.cs
Normal file
@@ -0,0 +1,193 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权(除特别声明或在RRQMCore.XREF命名空间的代码)归作者本人若汝棋茗所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权
|
||||
// CSDN博客:https://blog.csdn.net/qq_40374647
|
||||
// 哔哩哔哩视频:https://space.bilibili.com/94253567
|
||||
// Gitee源代码仓库:https://gitee.com/RRQM_Home
|
||||
// Github源代码仓库:https://github.com/RRQM
|
||||
// 交流QQ群:234762506
|
||||
// 感谢您的下载和使用
|
||||
//------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#region License
|
||||
|
||||
// Copyright (c) 2007 James Newton-King
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the "Software"), to deal in the Software without
|
||||
// restriction, including without limitation the rights to use,
|
||||
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following
|
||||
// conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
// OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#endregion License
|
||||
|
||||
using RRQMCore.XREF.Newtonsoft.Json.Utilities;
|
||||
using System;
|
||||
using System.Globalization;
|
||||
|
||||
#if !HAVE_LINQ
|
||||
#else
|
||||
using System.Linq;
|
||||
|
||||
#endif
|
||||
|
||||
namespace RRQMCore.XREF.Newtonsoft.Json.Converters
|
||||
{
|
||||
/// <summary>
|
||||
/// Converts an <see cref="Enum"/> to and from its name string value.
|
||||
/// </summary>
|
||||
public class StringEnumConverter : JsonConverter
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether the written enum text should be camel case.
|
||||
/// The default value is <c>false</c>.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if the written enum text will be camel case; otherwise, <c>false</c>.</value>
|
||||
public bool CamelCaseText { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether integer values are allowed when deserializing.
|
||||
/// The default value is <c>true</c>.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if integers are allowed when deserializing; otherwise, <c>false</c>.</value>
|
||||
public bool AllowIntegerValues { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="StringEnumConverter"/> class.
|
||||
/// </summary>
|
||||
public StringEnumConverter()
|
||||
{
|
||||
AllowIntegerValues = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="StringEnumConverter"/> class.
|
||||
/// </summary>
|
||||
/// <param name="camelCaseText"><c>true</c> if the written enum text will be camel case; otherwise, <c>false</c>.</param>
|
||||
public StringEnumConverter(bool camelCaseText)
|
||||
: this()
|
||||
{
|
||||
CamelCaseText = camelCaseText;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes the JSON representation of the object.
|
||||
/// </summary>
|
||||
/// <param name="writer">The <see cref="JsonWriter"/> to write to.</param>
|
||||
/// <param name="value">The value.</param>
|
||||
/// <param name="serializer">The calling serializer.</param>
|
||||
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
writer.WriteNull();
|
||||
return;
|
||||
}
|
||||
|
||||
Enum e = (Enum)value;
|
||||
|
||||
if (!EnumUtils.TryToString(e.GetType(), value, CamelCaseText, out string enumName))
|
||||
{
|
||||
if (!AllowIntegerValues)
|
||||
{
|
||||
throw JsonSerializationException.Create(null, writer.ContainerPath, "Integer value {0} is not allowed.".FormatWith(CultureInfo.InvariantCulture, e.ToString("D")), null);
|
||||
}
|
||||
|
||||
// enum value has no name so write number
|
||||
writer.WriteValue(value);
|
||||
}
|
||||
else
|
||||
{
|
||||
writer.WriteValue(enumName);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads the JSON representation of the object.
|
||||
/// </summary>
|
||||
/// <param name="reader">The <see cref="JsonReader"/> to read from.</param>
|
||||
/// <param name="objectType">Type of the object.</param>
|
||||
/// <param name="existingValue">The existing value of object being read.</param>
|
||||
/// <param name="serializer">The calling serializer.</param>
|
||||
/// <returns>The object value.</returns>
|
||||
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
|
||||
{
|
||||
if (reader.TokenType == JsonToken.Null)
|
||||
{
|
||||
if (!ReflectionUtils.IsNullableType(objectType))
|
||||
{
|
||||
throw JsonSerializationException.Create(reader, "Cannot convert null value to {0}.".FormatWith(CultureInfo.InvariantCulture, objectType));
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
bool isNullable = ReflectionUtils.IsNullableType(objectType);
|
||||
Type t = isNullable ? Nullable.GetUnderlyingType(objectType) : objectType;
|
||||
|
||||
try
|
||||
{
|
||||
if (reader.TokenType == JsonToken.String)
|
||||
{
|
||||
string enumText = reader.Value.ToString();
|
||||
|
||||
if (enumText == string.Empty && isNullable)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return EnumUtils.ParseEnum(t, enumText, !AllowIntegerValues);
|
||||
}
|
||||
|
||||
if (reader.TokenType == JsonToken.Integer)
|
||||
{
|
||||
if (!AllowIntegerValues)
|
||||
{
|
||||
throw JsonSerializationException.Create(reader, "Integer value {0} is not allowed.".FormatWith(CultureInfo.InvariantCulture, reader.Value));
|
||||
}
|
||||
|
||||
return ConvertUtils.ConvertOrCast(reader.Value, CultureInfo.InvariantCulture, t);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw JsonSerializationException.Create(reader, "Error converting value {0} to type '{1}'.".FormatWith(CultureInfo.InvariantCulture, MiscellaneousUtils.FormatValueForPrint(reader.Value), objectType), ex);
|
||||
}
|
||||
|
||||
// we don't actually expect to get here.
|
||||
throw JsonSerializationException.Create(reader, "Unexpected token {0} when parsing enum.".FormatWith(CultureInfo.InvariantCulture, reader.TokenType));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether this instance can convert the specified object type.
|
||||
/// </summary>
|
||||
/// <param name="objectType">Type of the object.</param>
|
||||
/// <returns>
|
||||
/// <c>true</c> if this instance can convert the specified object type; otherwise, <c>false</c>.
|
||||
/// </returns>
|
||||
public override bool CanConvert(Type objectType)
|
||||
{
|
||||
Type t = (ReflectionUtils.IsNullableType(objectType))
|
||||
? Nullable.GetUnderlyingType(objectType)
|
||||
: objectType;
|
||||
|
||||
return t.IsEnum();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,146 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权(除特别声明或在RRQMCore.XREF命名空间的代码)归作者本人若汝棋茗所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权
|
||||
// CSDN博客:https://blog.csdn.net/qq_40374647
|
||||
// 哔哩哔哩视频:https://space.bilibili.com/94253567
|
||||
// Gitee源代码仓库:https://gitee.com/RRQM_Home
|
||||
// Github源代码仓库:https://github.com/RRQM
|
||||
// 交流QQ群:234762506
|
||||
// 感谢您的下载和使用
|
||||
//------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#region License
|
||||
|
||||
// Copyright (c) 2007 James Newton-King
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the "Software"), to deal in the Software without
|
||||
// restriction, including without limitation the rights to use,
|
||||
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following
|
||||
// conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
// OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#endregion License
|
||||
|
||||
using RRQMCore.XREF.Newtonsoft.Json.Utilities;
|
||||
using System;
|
||||
using System.Globalization;
|
||||
|
||||
namespace RRQMCore.XREF.Newtonsoft.Json.Converters
|
||||
{
|
||||
/// <summary>
|
||||
/// Converts a <see cref="DateTime"/> to and from Unix epoch time
|
||||
/// </summary>
|
||||
public class UnixDateTimeConverter : DateTimeConverterBase
|
||||
{
|
||||
internal static readonly DateTime UnixEpoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
|
||||
|
||||
/// <summary>
|
||||
/// Writes the JSON representation of the object.
|
||||
/// </summary>
|
||||
/// <param name="writer">The <see cref="JsonWriter"/> to write to.</param>
|
||||
/// <param name="value">The value.</param>
|
||||
/// <param name="serializer">The calling serializer.</param>
|
||||
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
|
||||
{
|
||||
long ticks;
|
||||
|
||||
if (value is DateTime dateTime)
|
||||
{
|
||||
ticks = (long)(dateTime.ToUniversalTime() - UnixEpoch).TotalSeconds;
|
||||
}
|
||||
#if HAVE_DATE_TIME_OFFSET
|
||||
else if (value is DateTimeOffset dateTimeOffset)
|
||||
{
|
||||
ticks = (long)(dateTimeOffset.ToUniversalTime() - UnixEpoch).TotalSeconds;
|
||||
}
|
||||
#endif
|
||||
else
|
||||
{
|
||||
throw new JsonSerializationException("Expected date object value.");
|
||||
}
|
||||
|
||||
if (ticks < 0)
|
||||
{
|
||||
throw new JsonSerializationException("Cannot convert date value that is before Unix epoch of 00:00:00 UTC on 1 January 1970.");
|
||||
}
|
||||
|
||||
writer.WriteValue(ticks);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads the JSON representation of the object.
|
||||
/// </summary>
|
||||
/// <param name="reader">The <see cref="JsonReader"/> to read from.</param>
|
||||
/// <param name="objectType">Type of the object.</param>
|
||||
/// <param name="existingValue">The existing property value of the JSON that is being converted.</param>
|
||||
/// <param name="serializer">The calling serializer.</param>
|
||||
/// <returns>The object value.</returns>
|
||||
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
|
||||
{
|
||||
bool nullable = ReflectionUtils.IsNullable(objectType);
|
||||
if (reader.TokenType == JsonToken.Null)
|
||||
{
|
||||
if (!nullable)
|
||||
{
|
||||
throw JsonSerializationException.Create(reader, "Cannot convert null value to {0}.".FormatWith(CultureInfo.InvariantCulture, objectType));
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
long ticks;
|
||||
|
||||
if (reader.TokenType == JsonToken.Integer)
|
||||
{
|
||||
ticks = (long)reader.Value;
|
||||
}
|
||||
else if (reader.TokenType == JsonToken.String)
|
||||
{
|
||||
if (!long.TryParse((string)reader.Value, out ticks))
|
||||
{
|
||||
throw JsonSerializationException.Create(reader, "Cannot convert invalid value to {0}.".FormatWith(CultureInfo.InvariantCulture, objectType));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw JsonSerializationException.Create(reader, "Unexpected token parsing date. Expected Integer or String, got {0}.".FormatWith(CultureInfo.InvariantCulture, reader.TokenType));
|
||||
}
|
||||
|
||||
if (ticks >= 0)
|
||||
{
|
||||
DateTime d = UnixEpoch.AddSeconds(ticks);
|
||||
|
||||
#if HAVE_DATE_TIME_OFFSET
|
||||
Type t = (nullable)
|
||||
? Nullable.GetUnderlyingType(objectType)
|
||||
: objectType;
|
||||
if (t == typeof(DateTimeOffset))
|
||||
{
|
||||
return new DateTimeOffset(d, TimeSpan.Zero);
|
||||
}
|
||||
#endif
|
||||
return d;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw JsonSerializationException.Create(reader, "Cannot convert value that is before Unix epoch of 00:00:00 UTC on 1 January 1970 to {0}.".FormatWith(CultureInfo.InvariantCulture, objectType));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
120
RRQMCore/XREF/Newtonsoft.Json/Converters/VersionConverter.cs
Normal file
120
RRQMCore/XREF/Newtonsoft.Json/Converters/VersionConverter.cs
Normal file
@@ -0,0 +1,120 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权(除特别声明或在RRQMCore.XREF命名空间的代码)归作者本人若汝棋茗所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权
|
||||
// CSDN博客:https://blog.csdn.net/qq_40374647
|
||||
// 哔哩哔哩视频:https://space.bilibili.com/94253567
|
||||
// Gitee源代码仓库:https://gitee.com/RRQM_Home
|
||||
// Github源代码仓库:https://github.com/RRQM
|
||||
// 交流QQ群:234762506
|
||||
// 感谢您的下载和使用
|
||||
//------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#region License
|
||||
|
||||
// Copyright (c) 2007 James Newton-King
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the "Software"), to deal in the Software without
|
||||
// restriction, including without limitation the rights to use,
|
||||
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following
|
||||
// conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
// OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#endregion License
|
||||
|
||||
using RRQMCore.XREF.Newtonsoft.Json.Utilities;
|
||||
using System;
|
||||
using System.Globalization;
|
||||
|
||||
namespace RRQMCore.XREF.Newtonsoft.Json.Converters
|
||||
{
|
||||
/// <summary>
|
||||
/// Converts a <see cref="Version"/> to and from a string (e.g. <c>"1.2.3.4"</c>).
|
||||
/// </summary>
|
||||
public class VersionConverter : JsonConverter
|
||||
{
|
||||
/// <summary>
|
||||
/// Writes the JSON representation of the object.
|
||||
/// </summary>
|
||||
/// <param name="writer">The <see cref="JsonWriter"/> to write to.</param>
|
||||
/// <param name="value">The value.</param>
|
||||
/// <param name="serializer">The calling serializer.</param>
|
||||
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
writer.WriteNull();
|
||||
}
|
||||
else if (value is Version)
|
||||
{
|
||||
writer.WriteValue(value.ToString());
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new JsonSerializationException("Expected Version object value");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads the JSON representation of the object.
|
||||
/// </summary>
|
||||
/// <param name="reader">The <see cref="JsonReader"/> to read from.</param>
|
||||
/// <param name="objectType">Type of the object.</param>
|
||||
/// <param name="existingValue">The existing property value of the JSON that is being converted.</param>
|
||||
/// <param name="serializer">The calling serializer.</param>
|
||||
/// <returns>The object value.</returns>
|
||||
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
|
||||
{
|
||||
if (reader.TokenType == JsonToken.Null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (reader.TokenType == JsonToken.String)
|
||||
{
|
||||
try
|
||||
{
|
||||
Version v = new Version((string)reader.Value);
|
||||
return v;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw JsonSerializationException.Create(reader, "Error parsing version string: {0}".FormatWith(CultureInfo.InvariantCulture, reader.Value), ex);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw JsonSerializationException.Create(reader, "Unexpected token or value when parsing version. Token: {0}, Value: {1}".FormatWith(CultureInfo.InvariantCulture, reader.TokenType, reader.Value));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether this instance can convert the specified object type.
|
||||
/// </summary>
|
||||
/// <param name="objectType">Type of the object.</param>
|
||||
/// <returns>
|
||||
/// <c>true</c> if this instance can convert the specified object type; otherwise, <c>false</c>.
|
||||
/// </returns>
|
||||
public override bool CanConvert(Type objectType)
|
||||
{
|
||||
return objectType == typeof(Version);
|
||||
}
|
||||
}
|
||||
}
|
||||
2252
RRQMCore/XREF/Newtonsoft.Json/Converters/XmlNodeConverter.cs
Normal file
2252
RRQMCore/XREF/Newtonsoft.Json/Converters/XmlNodeConverter.cs
Normal file
File diff suppressed because it is too large
Load Diff
57
RRQMCore/XREF/Newtonsoft.Json/DateFormatHandling.cs
Normal file
57
RRQMCore/XREF/Newtonsoft.Json/DateFormatHandling.cs
Normal file
@@ -0,0 +1,57 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权(除特别声明或在RRQMCore.XREF命名空间的代码)归作者本人若汝棋茗所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权
|
||||
// CSDN博客:https://blog.csdn.net/qq_40374647
|
||||
// 哔哩哔哩视频:https://space.bilibili.com/94253567
|
||||
// Gitee源代码仓库:https://gitee.com/RRQM_Home
|
||||
// Github源代码仓库:https://github.com/RRQM
|
||||
// 交流QQ群:234762506
|
||||
// 感谢您的下载和使用
|
||||
//------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#region License
|
||||
|
||||
// Copyright (c) 2007 James Newton-King
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the "Software"), to deal in the Software without
|
||||
// restriction, including without limitation the rights to use,
|
||||
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following
|
||||
// conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
// OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#endregion License
|
||||
|
||||
namespace RRQMCore.XREF.Newtonsoft.Json
|
||||
{
|
||||
/// <summary>
|
||||
/// Specifies how dates are formatted when writing JSON text.
|
||||
/// </summary>
|
||||
public enum DateFormatHandling
|
||||
{
|
||||
/// <summary>
|
||||
/// Dates are written in the ISO 8601 format, e.g. <c>"2012-03-21T05:40Z"</c>.
|
||||
/// </summary>
|
||||
IsoDateFormat,
|
||||
|
||||
/// <summary>
|
||||
/// Dates are written in the Microsoft JSON format, e.g. <c>"\/Date(1198908717056)\/"</c>.
|
||||
/// </summary>
|
||||
MicrosoftDateFormat
|
||||
}
|
||||
}
|
||||
64
RRQMCore/XREF/Newtonsoft.Json/DateParseHandling.cs
Normal file
64
RRQMCore/XREF/Newtonsoft.Json/DateParseHandling.cs
Normal file
@@ -0,0 +1,64 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// 此代码版权(除特别声明或在RRQMCore.XREF命名空间的代码)归作者本人若汝棋茗所有
|
||||
// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权
|
||||
// CSDN博客:https://blog.csdn.net/qq_40374647
|
||||
// 哔哩哔哩视频:https://space.bilibili.com/94253567
|
||||
// Gitee源代码仓库:https://gitee.com/RRQM_Home
|
||||
// Github源代码仓库:https://github.com/RRQM
|
||||
// 交流QQ群:234762506
|
||||
// 感谢您的下载和使用
|
||||
//------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#region License
|
||||
|
||||
// Copyright (c) 2007 James Newton-King
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the "Software"), to deal in the Software without
|
||||
// restriction, including without limitation the rights to use,
|
||||
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following
|
||||
// conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
// OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#endregion License
|
||||
|
||||
namespace RRQMCore.XREF.Newtonsoft.Json
|
||||
{
|
||||
/// <summary>
|
||||
/// Specifies how date formatted strings, e.g. <c>"\/Date(1198908717056)\/"</c> and <c>"2012-03-21T05:40Z"</c>, are parsed when reading JSON text.
|
||||
/// </summary>
|
||||
public enum DateParseHandling
|
||||
{
|
||||
/// <summary>
|
||||
/// Date formatted strings are not parsed to a date type and are read as strings.
|
||||
/// </summary>
|
||||
None = 0,
|
||||
|
||||
/// <summary>
|
||||
/// Date formatted strings, e.g. <c>"\/Date(1198908717056)\/"</c> and <c>"2012-03-21T05:40Z"</c>, are parsed to <see cref="DateTime"/>.
|
||||
/// </summary>
|
||||
DateTime = 1,
|
||||
|
||||
#if HAVE_DATE_TIME_OFFSET
|
||||
/// <summary>
|
||||
/// Date formatted strings, e.g. <c>"\/Date(1198908717056)\/"</c> and <c>"2012-03-21T05:40Z"</c>, are parsed to <see cref="DateTimeOffset"/>.
|
||||
/// </summary>
|
||||
DateTimeOffset = 2
|
||||
#endif
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user