补充仓库

This commit is contained in:
若汝棋茗
2022-01-10 22:06:22 +08:00
parent 8c18bd1035
commit eec1c3eb76
476 changed files with 99906 additions and 25 deletions

View File

@@ -28,20 +28,16 @@
## 💿描述
| 名称 |描述|
|---|---|
| [![NuGet version (RRQMCore)](https://img.shields.io/nuget/v/RRQMCore.svg?label=RRQMCore)](https://www.nuget.org/packages/RRQMCore/) | RRQMCore是为RRQM系提供基础服务功能的库其中包含<br>**内存池**、**对象池**、**等待逻辑池**、**AppMessenger**、**3DES加密**、<br>**Xml快速存储**、**运行时间测量器**、**文件快捷操作**、<br>**高性能序列化器**、**规范日志接口**等。 |
|[![NuGet version (RRQMSocket)](https://img.shields.io/nuget/v/RRQMSocket.svg?label=RRQMSocket)](https://www.nuget.org/packages/RRQMSocket/)| **RRQMSocket**是一个整合性的、超轻量级的、可以免费商用使用<br>的网络通信服务框架。它具有 **高并发连接****高并发处理**<br>**事件订阅** 、 **插件式扩展****多线程处理****内存池****对象池** <br>等特点,让使用者能够更加简单的、快速的搭建网络框架。|
|[![NuGet version](https://img.shields.io/nuget/v/RRQMSocketFramework.svg?label=RRQMSocketFramework)](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)|
## 🎀依赖、扩展库
| 名称 |描述|
|---|---|
| [![NuGet version (RRQMCore)](https://img.shields.io/nuget/v/RRQMCore.svg?label=RRQMCore)](https://gitee.com/RRQM_OS/RRQMCore) | RRQMCore是为RRQM系提供基础服务功能的库其中包含<br>**内存池**、**对象池**、**等待逻辑池**、**AppMessenger**、**3DES加密**、<br>**Xml快速存储**、**运行时间测量器**、**文件快捷操作**、<br>**高性能序列化器**、**规范日志接口**等。 |
| [![NuGet version (RRQMSocket.FileTransfer)](https://img.shields.io/nuget/v/RRQMSocket.FileTransfer.svg?label=RRQMSocket.FileTransfer)](https://gitee.com/RRQM_OS/rrqmsocket.filetransfer) | RRQMSocket.FileTransfer是一个高性能的文件传输框架您可以<br>用它传输**任意大小**的文件,它可以完美支持**上传下载混合式队列传输**、<br>**断点续传**、 **快速上传** 、**传输限速**、**获取文件信息**、**删除文件**等。<br>在实时测试中它的传输速率可达1000Mb/s。 |
| [![NuGet version (RRQMSocket.WebSocket)](https://img.shields.io/nuget/v/RRQMSocket.WebSocket.svg?label=RRQMSocket.WebSocket)](https://gitee.com/RRQM_OS/rrqmsocket.websocket) | RRQMSocket.WebSocket是一个高效超轻量级的WebSocket框架。<br>它包含了Service和Client两大组件同时定义了文本、二进制或<br>其他类型数据的快捷发送、分片发送接口可与js等任意WebSocket组件交互|
| [![NuGet version (RRQMSocket.Http)](https://img.shields.io/nuget/v/RRQMSocket.Http.svg?label=RRQMSocket.Http)](https://gitee.com/RRQM_OS/rrqmsocket.http) | RRQMSocket.Http是一个能够简单解析Http的服务组件<br>能够快速响应Http服务请求。|
|[![NuGet version (RRQMSocket.RPC)](https://img.shields.io/nuget/v/RRQMSocket.RPC.svg?label=RRQMSocket.RPC)](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>其他协议调用性能详看性能评测。
|[![NuGet version (RRQMSocket.RPC.XmlRpc)](https://img.shields.io/nuget/v/RRQMSocket.RPC.XmlRpc.svg?label=RRQMSocket.RPC.XmlRpc)](https://gitee.com/RRQM_OS/rrqmsocket.rpc.xmlrpc)| XmlRpc是一个扩展于RRQMSocket.RPC的XmlRpc组件可以通过<br>该组件创建XmlRpc服务解析器完美支持XmlRpc数据类型类型嵌套<br>Array等也能与CookComputing.XmlRpcV2完美对接。<br>不限WebAndroid等平台。|
| [![NuGet version (RRQMSocket.RPC.JsonRpc)](https://img.shields.io/nuget/v/RRQMSocket.RPC.JsonRpc.svg?label=RRQMSocket.RPC.JsonRpc)](https://gitee.com/RRQM_OS/rrqmsocket.rpc.jsonrpc)| JsonRpc是一个扩展于RRQMSocket.RPC的JsonRpc组件<br>可以通过该组件创建JsonRpc服务解析器支持JsonRpc全部功能可与WebAndroid等平台无缝对接。|
|[![NuGet version (RRQMSocket.RPC.WebApi)](https://img.shields.io/nuget/v/RRQMSocket.RPC.WebApi.svg?label=RRQMSocket.RPC.WebApi)](https://gitee.com/RRQM_OS/rrqmsocket.rpc.webapi)| WebApi是一个扩展于RRQMSocket.RPC的WebApi组件可以通过<br>该组件创建WebApi服务解析器让桌面端、Web端、移动端可以<br>跨语言调用RPC函数。功能支持路由、Get传参、Post传参等。|
|[![NuGet version](https://img.shields.io/nuget/v/RRQMSocketFramework.svg?label=RRQMSocketFramework)](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)|
| [![NuGet version (RRQMSocket.FileTransfer)](https://img.shields.io/nuget/v/RRQMSocket.FileTransfer.svg?label=RRQMSocket.FileTransfer)](https://www.nuget.org/packages/RRQMSocket.FileTransfer/) | RRQMSocket.FileTransfer是一个高性能的文件传输框架您可以<br>用它传输**任意大小**的文件,它可以完美支持**上传下载混合式队列传输**、<br>**断点续传**、 **快速上传** 、**传输限速**、**获取文件信息**、**删除文件**等。<br>在实时测试中它的传输速率可达1000Mb/s。 |
| [![NuGet version (RRQMSocket.WebSocket)](https://img.shields.io/nuget/v/RRQMSocket.WebSocket.svg?label=RRQMSocket.WebSocket)](https://www.nuget.org/packages/RRQMSocket.WebSocket/) | RRQMSocket.WebSocket是一个高效超轻量级的WebSocket框架。<br>它包含了Service和Client两大组件同时定义了文本、二进制或<br>其他类型数据的快捷发送、分片发送接口可与js等任意WebSocket组件交互|
| [![NuGet version (RRQMSocket.Http)](https://img.shields.io/nuget/v/RRQMSocket.Http.svg?label=RRQMSocket.Http)](https://www.nuget.org/packages/RRQMSocket.Http/) | RRQMSocket.Http是一个能够简单解析Http的服务组件<br>能够快速响应Http服务请求。|
|[![NuGet version (RRQMSocket.RPC)](https://img.shields.io/nuget/v/RRQMSocket.RPC.svg?label=RRQMSocket.RPC)](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>其他协议调用性能详看性能评测。
|[![NuGet version (RRQMSocket.RPC.XmlRpc)](https://img.shields.io/nuget/v/RRQMSocket.RPC.XmlRpc.svg?label=RRQMSocket.RPC.XmlRpc)](https://www.nuget.org/packages/RRQMSocket.RPC.XmlRpc/)| XmlRpc是一个扩展于RRQMSocket.RPC的XmlRpc组件可以通过<br>该组件创建XmlRpc服务解析器完美支持XmlRpc数据类型类型嵌套<br>Array等也能与CookComputing.XmlRpcV2完美对接。<br>不限WebAndroid等平台。|
| [![NuGet version (RRQMSocket.RPC.JsonRpc)](https://img.shields.io/nuget/v/RRQMSocket.RPC.JsonRpc.svg?label=RRQMSocket.RPC.JsonRpc)](https://www.nuget.org/packages/RRQMSocket.RPC.JsonRpc/)| JsonRpc是一个扩展于RRQMSocket.RPC的JsonRpc组件<br>可以通过该组件创建JsonRpc服务解析器支持JsonRpc全部功能可与WebAndroid等平台无缝对接。|
|[![NuGet version (RRQMSocket.RPC.WebApi)](https://img.shields.io/nuget/v/RRQMSocket.RPC.WebApi.svg?label=RRQMSocket.RPC.WebApi)](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产品例如HPSocketSuperSocket等那么RRQMSocket在设计时也是借鉴了其他产品的优秀设计理念数据处理适配器就是其中之一但和其他产品的设计不同的是RRQMSocket的适配器功能更加强大它不仅可以提前解析数据包还可以解析数据对象。例如可以使用固定包头对数据进行预处理从而解决**数据分包**、**粘包**的问题。也可以直接解析**HTTP**数据协议、WebSocket数据协议等。
相信大家都使用过其他的Socket产品例如HPSocketSuperSocket等那么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) | [![NuGet version (RRQMSkin)](https://img.shields.io/nuget/v/RRQMSkin.svg?style=flat-square)](https://www.nuget.org/packages/RRQMSkin/) | [![Download](https://img.shields.io/nuget/dt/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});
}
```
## 🧲应用场景模拟

View 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
/// min1.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
}
}

View 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;
//}
}
}
}

View 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();
}
}
}

View 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; }
}
}

View 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);
}
}
}

View 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}";
}
}
}

View File

@@ -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;
}
}
}

View 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;
}
}
}

View 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
}
}

View 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; }
}
}

View 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);
}
}
}
}

View 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
}
}

View 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;
}
}
}
}

View 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
{
}
}

View 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
View 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
View 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}";
}
}
}

View 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
}
}

View 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;
}
}
}

View 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);
}
}
}

View 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
{
}
}

View 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;
}
}
}

View 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();
}
}
}
}
}

View 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;
}
}
}

View 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
{
}
}

View 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;
}
}
}

View 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;
}
}
}

View 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); });
}
}
}

View 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
{
}
}

View 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;
}
}
}

View 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)
{
}
}
}

View 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)
{
}
}
}

View 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) { }
}
}

View 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];
}
}
}

View 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);
}
}
}

View 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; }
}
}
}
}
}

View 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);
}
}
}

View 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
}
}
}

View 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);
}
}
}

View 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;
}
}
}

View 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();
}
}
}

View 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));
}
}
}

View 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;
}
}
}

View 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
View 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);
}
}

View 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
}
}

View 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();
}
}

View 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();
}
}

View 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

Binary file not shown.

After

Width:  |  Height:  |  Size: 244 KiB

BIN
RRQMCore/RRQM.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 121 KiB

90
RRQMCore/RRQMCore.csproj Normal file
View 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,但为防止冲突,已修改其命名空间。
特此感谢其作者!!!
附带其Githubhttps://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
View 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
View 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>

View 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);
});
}
}
}

View 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;
}
}
}

View 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
}
}

View 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("未找到该消息");
}
}
}
}

View 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
{
}
}

View 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; }
}
}

View 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; }
}
}

View 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; }
}
}

View 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);
}
}
}
}

View 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;
}
}
}

View 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
}
}

View 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; }
}
}
}

View 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.Serialization
{
/// <summary>
/// 忽略的RRQN序列化
/// </summary>
[AttributeUsage(AttributeTargets.Property)]
public class RRQMNonSerializedAttribute : Attribute
{
}
}

View 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;
}
}

View 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
}
}

View 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;
}
}
}

View 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
}
}

View 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序列化和反序列化
}
}

View 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
}
}

View 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));
}
}
}
}

View 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;
}
}
}

View 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);
}
}
}

View 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; }
}
}

View 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
}
}

View 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));
}
}
}

View 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
}
}

View 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

View 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
// 感谢您的下载和使用
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
#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));
}
}
}

View File

@@ -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;
}
}

View 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

View 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

View 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 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;
}
}
}

View File

@@ -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

View File

@@ -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

View File

@@ -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

View 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);
}
}
}
}

View File

@@ -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;
}
}
}

View File

@@ -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;
}
}
}

View 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));
}
}
}

View 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();
}
}
}

View 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
// 感谢您的下载和使用
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
#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));
}
}
}
}

View 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);
}
}
}

File diff suppressed because it is too large Load Diff

View 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
}
}

View 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