重置文件,准备升级版本

This commit is contained in:
若汝棋茗
2022-03-20 10:51:15 +08:00
parent baf5b781ad
commit 8b7825e137
560 changed files with 118480 additions and 0 deletions

341
.gitignore vendored Normal file
View File

@@ -0,0 +1,341 @@
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
##
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
# User-specific files
*.rsuser
*.suo
*.user
*.userosscache
*.sln.docstates
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
[Aa][Rr][Mm]/
[Aa][Rr][Mm]64/
bld/
[Bb]in/
[Oo]bj/
[Ll]og/
# Visual Studio 2015/2017 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/
# Visual Studio 2017 auto generated files
Generated\ Files/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
# NUNIT
*.VisualState.xml
TestResult.xml
# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c
# Benchmark Results
BenchmarkDotNet.Artifacts/
# .NET Core
project.lock.json
project.fragment.lock.json
artifacts/
# StyleCop
StyleCopReport.xml
# Files built by Visual Studio
*_i.c
*_p.c
*_h.h
*.ilk
*.meta
*.obj
*.iobj
*.pch
*.pdb
*.ipdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*_wpftmp.csproj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Chutzpah Test files
_Chutzpah*
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
*.VC.db
*.VC.VC.opendb
# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap
# Visual Studio Trace Files
*.e2e
# TFS 2012 Local Workspace
$tf/
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# JustCode is a .NET coding add-in
.JustCode
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# AxoCover is a Code Coverage Tool
.axoCover/*
!.axoCover/settings.json
# Visual Studio code coverage results
*.coverage
*.coveragexml
# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*
# MightyMoose
*.mm.*
AutoTest.Net/
# Web workbench (sass)
.sass-cache/
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# Note: Comment the next line if you want to checkin your web deploy settings,
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
*.publishproj
# Microsoft Azure Web App publish settings. Comment the next line if you want to
# checkin your Azure Web App publish settings, but sensitive information contained
# in these scripts will be unencrypted
PublishScripts/
# NuGet Packages
*.nupkg
# The packages folder can be ignored because of Package Restore
**/[Pp]ackages/*
# except build/, which is used as an MSBuild target.
!**/[Pp]ackages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/[Pp]ackages/repositories.config
# NuGet v3's project.json files produces more ignorable files
*.nuget.props
*.nuget.targets
# Microsoft Azure Build Output
csx/
*.build.csdef
# Microsoft Azure Emulator
ecf/
rcf/
# Windows Store app package directories and files
AppPackages/
BundleArtifacts/
Package.StoreAssociation.xml
_pkginfo.txt
*.appx
# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!?*.[Cc]ache/
# Others
ClientBin/
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.jfm
*.pfx
*.publishsettings
orleans.codegen.cs
# Including strong name files can present a security risk
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
#*.snk
# Since there are multiple workflows, uncomment next line to ignore bower_components
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
#bower_components/
# ASP.NET Core default setup: bower directory is configured as wwwroot/lib/ and bower restore is true
**/wwwroot/lib/
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
ServiceFabricBackup/
*.rptproj.bak
# SQL Server files
*.mdf
*.ldf
*.ndf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
*.rptproj.rsuser
# Microsoft Fakes
FakesAssemblies/
# GhostDoc plugin setting file
*.GhostDoc.xml
# Node.js Tools for Visual Studio
.ntvs_analysis.dat
node_modules/
# Visual Studio 6 build log
*.plg
# Visual Studio 6 workspace options file
*.opt
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
*.vbw
# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions
# Paket dependency manager
.paket/paket.exe
paket-files/
# FAKE - F# Make
.fake/
# JetBrains Rider
.idea/
*.sln.iml
# CodeRush personal settings
.cr/personal
# Python Tools for Visual Studio (PTVS)
__pycache__/
*.pyc
# Cake - Uncomment if you are using it
# tools/**
# !tools/packages.config
# Tabs Studio
*.tss
# Telerik's JustMock configuration file
*.jmconfig
# BizTalk build output
*.btp.cs
*.btm.cs
*.odx.cs
*.xsd.cs
# OpenCover UI analysis results
OpenCover/
# Azure Stream Analytics local run output
ASALocalRun/
# MSBuild Binary and Structured Log
*.binlog
# NVidia Nsight GPU debugger configuration file
*.nvuser
# MFractors (Xamarin productivity tool) working folder
.mfractor/
# Local History for Visual Studio
.localhistory/
# BeatPulse healthcheck temp database
healthchecksdb

201
LICENSE Normal file
View File

@@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

301
README.md Normal file
View File

@@ -0,0 +1,301 @@
<p></p>
<p></p>
<p align="center">
<img src="https://ftp.bmp.ovh/imgs/2021/06/351eeccfadc07014.png" width = "100" height = "100" alt="图片名称" align=center />
</p>
<div align="center">
[![NuGet version (RRQMSocket)](https://img.shields.io/nuget/v/RRQMSocket.svg?style=flat-square)](https://www.nuget.org/packages/RRQMSocket/)
[![License](https://img.shields.io/badge/license-Apache%202-4EB1BA.svg)](https://www.apache.org/licenses/LICENSE-2.0.html)
[![Download](https://img.shields.io/nuget/dt/RRQMSocket)](https://www.nuget.org/packages/RRQMSocket/)
[![star](https://gitee.com/dotnetchina/RRQMSocket/badge/star.svg?theme=gvp)](https://gitee.com/dotnetchina/RRQMSocket/stargazers)
[![fork](https://gitee.com/dotnetchina/RRQMSocket/badge/fork.svg?theme=gvp)](https://gitee.com/dotnetchina/RRQMSocket/members)
<a href="https://jq.qq.com/?_wv=1027&k=gN7UL4fw">
<img src="https://img.shields.io/badge/QQ群-234762506-red" alt="QQ">
</a>
</div>
<div align="center">
合抱之木,生于毫末;九层之台,起于垒土。
</div>
## 🎀描述
| 名称|地址 |描述|
|---|---|---|
|[![NuGet version (RRQMSocket)](https://img.shields.io/nuget/v/RRQMSocket.svg?label=RRQMSocket)](https://www.nuget.org/packages/RRQMSocket/)|[Gitee](https://gitee.com/dotnetchina/RRQMSocket)<br>[Github](https://github.com/RRQM/RRQMSocket)| RRQMSocket是一个整合性的、超轻量级的网络通信框架。<br>包含了TCP、UDP、Ssl、Channel、Protocol、Token、<br>租户模式等一系列的通信模块。其扩展组件包含WebSocket、<br>大文件传输、RPC、WebApi、XmlRpc、JsonRpc等内容|
|[![NuGet version](https://img.shields.io/nuget/v/RRQMSocketFramework.svg?label=RRQMSocketFramework)](https://www.nuget.org/packages/RRQMSocketFramework/)|[Gitee](https://gitee.com/dotnetchina/RRQMSocket)<br>[Github](https://github.com/RRQM/RRQMSocket) |**RRQMSocketFramework**是RRQMSocket系列的增强企业版<br>两者在基础功能上没有区别,但是在扩展功能上有一定差异性,<br>例如RPC中的EventBus、文件传输中的限速功能等<br>具体差异请看[RRQM商业运营](https://www.yuque.com/eo2w71/rrqm/80696720a95e415d94c87fa03642513d)|
| [![NuGet version (RRQMCore)](https://img.shields.io/nuget/v/RRQMCore.svg?label=RRQMCore)](https://www.nuget.org/packages/RRQMCore)|[Gitee](https://gitee.com/dotnetchina/RRQMSocket)<br>[Github](https://github.com/RRQM/RRQMSocket) | RRQMCore是为RRQM系提供基础服务功能的库其中包含<br>**内存池**、**对象池**、**等待逻辑池**、**AppMessenger**、**3DES加密**、<br>**Xml快速存储**、**运行时间测量器**、**文件快捷操作**、<br>**高性能序列化器**、**规范日志接口**等。 |
| [![NuGet version (RRQMSocket.WebSocket)](https://img.shields.io/nuget/v/RRQMSocket.WebSocket.svg?label=RRQMSocket.WebSocket)](https://www.nuget.org/packages/rrqmsocket.websocket)|[Gitee](https://gitee.com/dotnetchina/RRQMSocket)<br>[Github](https://github.com/RRQM/RRQMSocket) | RRQMSocket.WebSocket是一个高效超轻量级的WebSocket框架。<br>它包含了Service和Client两大组件支持Ssl同时定义了文本、二进制或<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)|[Gitee](https://gitee.com/dotnetchina/RRQMSocket)<br>[Github](https://github.com/RRQM/RRQMSocket) | 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)|[Gitee](https://gitee.com/dotnetchina/RRQMSocket)<br>[Github](https://github.com/RRQM/RRQMSocket) |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)|[Gitee](https://gitee.com/dotnetchina/RRQMSocket)<br>[Github](https://github.com/RRQM/RRQMSocket)| 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)|[Gitee](https://gitee.com/dotnetchina/RRQMSocket)<br>[Github](https://github.com/RRQM/RRQMSocket)| 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)|[Gitee](https://gitee.com/dotnetchina/RRQMSocket)<br>[Github](https://github.com/RRQM/RRQMSocket)| WebApi是一个扩展于RRQMSocket.RPC的WebApi组件可以通过<br>该组件创建WebApi服务解析器让桌面端、Web端、移动端可以<br>跨语言调用RPC函数。功能支持路由、Get传参、Post传参等。|
| [![NuGet version (RRQMSocket.FileTransfer)](https://img.shields.io/nuget/v/RRQMSocket.FileTransfer.svg?label=RRQMSocket.FileTransfer)](https://www.nuget.org/packages/rrqmsocket.filetransfer)|[Gitee](https://gitee.com/dotnetchina/RRQMSocket)<br>[Github](https://github.com/RRQM/RRQMSocket) | 这是一个高性能的C/S架构的文件传输框架您可以用它传输<br>**任意大小**的文件,它可以完美支持**上传下载混合式队列传输**、<br>**断点续传**、 **快速上传** 、**传输限速**、**获取文件信息**、**删除文件**等。<br>在实际测试中它的传输速率可达1000Mb/s。 |
## 🖥支持环境
- .NET Framework4.5及以上。
- .NET Core3.1及以上。
- .NET Standard2.0及以上。
## 🥪支持框架
- WPF
- Winform
- Blazor
- Xamarin
- Mono
- Unity在IL2cpp编译时需要导入源码Mono则直接加载dll即可
- 其他即所有C#系
## 🌴RRQMSocket特点速览
#### 传统IOCP和RRQMSocket
RRQMSocket的IOCP和传统也不一样就以微软官方示例为例使用MemoryBuffer开辟一块内存均分然后给每个会话分配一个区接收等收到数据后再**复制**源数据然后把复制的数据进行处理。而RRQMSocket是每次接收之前从内存池拿一个可用内存块然后**直接用于接收**,等收到数据以后,直接就把这个内存块抛出处理,这样就避免了**复制操作**,虽然只是细小的设计,但是在传输**1000w**次**64kb**的数据时,性能相差了**10倍**。
#### 数据处理适配器
相信大家都使用过其他的Socket产品那么RRQMSocket在设计时也是借鉴了其他产品的优秀设计理念数据处理适配器就是其中之一但和其他产品的设计不同的是RRQMSocket的适配器功能更加强大它不仅可以提前解析数据包还可以解析数据对象。例如可以使用固定包头对数据进行预处理从而解决**数据分包**、**粘包**的问题。也可以直接解析**HTTP**数据协议、WebSocket数据协议等。
#### 兼容性与适配
RRQMSocket提供多种框架模型能够完全兼容基于TCP、UDP协议的所有协议。例如TcpService与TcpClient其基础功能和Socket一模一样只是增强了框架的**坚固性**和**并发性**,将**连接**和**接收数据**通过事件的形式抛出,让使用者能够更加友好的使用。
## 🔗联系作者
- [CSDN博客主页](https://blog.csdn.net/qq_40374647)
- [哔哩哔哩视频](https://space.bilibili.com/94253567)
- [源代码仓库主页](https://gitee.com/RRQM_Home)
- 交流QQ群234762506
## 🌟API手册
- [ API首页 ](https://www.yuque.com/eo2w71/rrqm/2c5dab34026d2b45ada6e51ae9e51a5a)
## ✨简单示例
**_以下仅以最简方式创建示例更多详情请查看[API文档](https://www.yuque.com/eo2w71/rrqm/2c5dab34026d2b45ada6e51ae9e51a5a)。_**
**【TcpService】**
```
TcpService service = new TcpService();
service.Connecting += (client, e) =>{};//有客户端正在连接
service.Connected += (client, e) =>{};//有客户端连接
service.Disconnected += (client, e) =>{};//有客户端断开连接
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);
//启动
service.Start();
```
**【TcpClient】**
```
SimpleTcpClient tcpClient = new SimpleTcpClient();
tcpClient.Connected += (client, e) =>{};//成功连接到服务器
tcpClient.Disconnected += (client, e) =>{};//从服务器断开连接,当连接不成功时不会触发。
//载入配置
tcpClient.Setup("127.0.0.1:7789");
tcpClient.Connect();
tcpClient.Send(Encoding.UTF8.GetBytes("RRQM"));
```
**【TcpClient 断线重连】**
```
tcpClient.UseReconnection(tryCount:5,printLog:true);
```
**【FixedHeaderPackageAdapter包模式】**
该适配器主要解决TCP粘分包问题数据格式采用简单而高效的“包头+数据体”的模式,其中包头支持:
- Byte模式1+n一次性最大接收255字节的数据。
- Ushort模式2+n一次最大接收65535字节。
- Int模式4+n一次最大接收2G数据。
以上数据头均采用RRQMBitConverter的默认端模式小端模式使用者可以根据需求切换默认端模式。
```
RRQMBitConverter.DefaultEndianType = EndianType.Little;
```
**【CustomFixedHeaderDataHandlingAdapter】**
用户自定义固定包头适配器主要帮助用户解决具有固定包头的数据帧信息。例如下列数据格式仅需要实现几个接口就能完成解析详细操作请参照API。
|1|1|1|**********|
**【CustomUnfixedHeaderDataHandlingAdapter】**
用户自定义不固定包头适配器主要帮助用户解决具有包头不固定的数据帧信息。例如最典型的HTTP数据包其数据头和数据体由“\r\n”隔开而数据头又因为请求者的请求信息的不同头部数据也不固定而数据体的长度也是由数据头的ContentLength的值显式指定的所以可以考虑使用CustomUnfixedHeaderDataHandlingAdapter解析也是仅通过简单的开发就能实现。
**【Ssl加密】**
在[RRQMBox](https://gitee.com/RRQM_Home/RRQMBox/tree/master/Ssl%E8%AF%81%E4%B9%A6%E7%9B%B8%E5%85%B3)中放置了一个自制Ssl证书密码为“RRQMSocket”以供测试。使用配置非常方便。
在服务器中只需设置配置SslOption属性和接收模式接收模式在Ssl模式下只支持BIO和Select
**服务器配置**
```
config.SslOption = new ServiceSslOption() { Certificate = new X509Certificate2("RRQMSocket.pfx", "RRQMSocket"), SslProtocols = SslProtocols.Tls12 };
config.ReceiveType = ReceiveType.Select;
```
**客户端配置**
```
config.ReceiveType = ReceiveType.BIO;
config.SslOption = new ClientSslOption()
{
ClientCertificates = new X509CertificateCollection() { new X509Certificate2("RRQMSocket.pfx", "RRQMSocket") },
SslProtocols = SslProtocols.Tls12,
TargetHost = "127.0.0.1",
CertificateValidationCallback = (sender, certificate, chain, sslPolicyErrors) => { return true; }
};
```
**【WS服务器】**
```
WSService wSService = new WSService();
wSService.Received += WSService_Received;
wSService.Connected += WSService_Connected;
var config = new WSServiceConfig();
config.ListenIPHosts = new IPHost[] { new IPHost("127.0.0.1:7789"), new IPHost(7790) };//同时监听两个地址
config.ReceiveType = ReceiveType.IOCP;
wSService.Setup(config).Start();
Console.WriteLine("WS服务器已启动");
```
**【WSs服务器】**
创建WSs服务器时其他配置不变只需要在`config`中加入以下代码即可。
在[RRQMBox](https://gitee.com/RRQM_Home/RRQMBox/tree/master/Ssl%E8%AF%81%E4%B9%A6%E7%9B%B8%E5%85%B3)中放置了一个自制Ssl证书密码为“RRQMSocket”以供测试。使用配置非常方便。
```csharp
//config.SslOption = new ServiceSslOption() { Certificate = new X509Certificate2("RRQMSocket.pfx", "RRQMSocket"), SslProtocols = SslProtocols.Tls12 };//Ssl配置当为null的时候相当于创建了ws服务器当赋值的时候相当于wss服务器。
config.ReceiveType = ReceiveType.Select;//在没有ssl配置时请使用IOCP模式速度会好些使用ssl时可以选择Select和BIO区别请看API
```
**【WS客户端】**
```csharp
SimpleWSClient client = new SimpleWSClient();
WSClientConfig config = new WSClientConfig();
config.RemoteIPHost = new IPHost("127.0.0.1:7789");
client .Setup(config);
client .Connect();
Console.WriteLine("连接成功");
while (true)
{
client.Send(Console.ReadLine());
}
```
***注意当使用域名连接时IPHost中的字符串必须显式指定端口例如百度地址IPHost("ws://baidu.com:80")***
**【WSs客户端】**
同样的,在客户端配置中,只需要加入以下代码即可。
***注意当使用域名连接时TargetHost为域名例如连接到IPHost("ws://baidu.com:80")时TargetHost应当填写baidu.com***
```csharp
config.SslOption = new ClientSslOption()
{
ClientCertificates = new X509CertificateCollection() { new X509Certificate2("RRQMSocket.pfx", "RRQMSocket") },
SslProtocols = SslProtocols.Tls12,
TargetHost = "127.0.0.1",
CertificateValidationCallback = (sender, certificate, chain, sslPolicyErrors) => { return true; }
};
config.ReceiveType = ReceiveType.BIO;
```
**【WS 接收数据(服务器、客户端均可用)】**
```
private static void MyWSClient_Received(IWSClientBase client, WSDataFrame dataFrame)
{
switch (dataFrame.Opcode)
{
case WSDataType.Cont:
Console.WriteLine($"收到中间数据,长度为:{dataFrame.PayloadLength}");
break;
case WSDataType.Text:
Console.WriteLine(dataFrame.GetMessage());
break;
case WSDataType.Binary:
if (dataFrame.FIN)
{
Console.WriteLine($"收到二进制数据,长度为:{dataFrame.PayloadLength}");
}
else
{
Console.WriteLine($"收到未结束的二进制数据,长度为:{dataFrame.PayloadLength}");
}
break;
case WSDataType.Close:
break;
case WSDataType.Ping:
break;
case WSDataType.Pong:
break;
default:
break;
}
}
```
**【RPC调用】**
- WebApi下列服务可让浏览器通过`url/XUnitTestServer/Sum?a=10&b=20`来调用结果可选xml或json。
- JsonRpc下列服务可让普通TCP使用`{"jsonrpc":"2.0","method":"Sum","params":[1020],"id":1}`来调用也能让web通过http/https来调用。
- xmlRpc下列服务可通过http+xml的形式调用。
- RRQMRPC使用专有协议调用。
**_其中除WebApi之外其他调用均可生成C#代理调用。_**
```
[Route("/[controller]/[action]")]
public class XUnitTestServer : ControllerBase
{
[XmlRpc]
[JsonRpc]
[Route]
[RRQMRPC]
public int Sum(int a, int b)
{
return a + b;
}
}
```
## 🧲应用场景模拟
[场景入口](https://www.yuque.com/eo2w71/rrqm/b138b52168853afb65369ca8171f14b9)
***
## 致谢
谢谢大家对我的支持如果还有其他问题请加群QQ234762506讨论。
## 支持作者
[支持入口](https://www.yuque.com/eo2w71/rrqm/a5199820843b324f025633fdeee44394)

View File

@@ -0,0 +1,917 @@
//------------------------------------------------------------------------------
// 此代码版权除特别声明或在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
// API首页https://www.yuque.com/eo2w71/rrqm
// 交流QQ群234762506
// 感谢您的下载和使用
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
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="byteSize"></param>
/// <param name="equalSize"></param>
public ByteBlock(int byteSize = 1024 * 10, bool equalSize = false) : this(BytePool.GetByteCore(byteSize, equalSize))
{
}
/// <summary>
/// 还能读取的长度,计算为<see cref="Len"/>与<see cref="Pos"/>的差值。
/// </summary>
public int CanReadLen
{
get { return this.Len - this.Pos; }
}
/// <summary>
/// 还能读取的长度,计算为<see cref="Len"/>与<see cref="Pos"/>的差值。
/// </summary>
public long CanReadLength
{
get { return this.length - this.position; }
}
/// <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 this._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 this.holding; }
}
/// <summary>
/// Int真实长度
/// </summary>
public int Len
{ get { return (int)this.length; } }
/// <summary>
/// 真实长度
/// </summary>
public override long Length
{ get { return this.length; } }
/// <summary>
/// int型流位置
/// </summary>
public int Pos
{
get { return (int)this.position; }
set { this.position = value; }
}
/// <summary>
/// 流位置
/// </summary>
public override long Position
{
get { return this.position; }
set { this.position = value; }
}
/// <summary>
/// 使用状态
/// </summary>
public bool Using
{
get { return this.@using; }
}
/// <summary>
/// 直接完全释放游离该对象然后等待GC
/// </summary>
public void AbsoluteDispose()
{
this.holding = false;
this.@using = false;
this.position = 0;
this.length = 0;
this._buffer = default;
}
/// <summary>
/// 清空数据
/// </summary>
/// <exception cref="ByteBlockDisposedException">内存块已释放</exception>
public void Clear()
{
if (!this.@using)
{
throw new ByteBlockDisposedException(ResType.ByteBlockDisposed.GetResString());
}
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>
/// <exception cref="ByteBlockDisposedException"></exception>
public override int Read(byte[] buffer, int offset, int count)
{
if (!this.@using)
{
throw new ByteBlockDisposedException(ResType.ByteBlockDisposed.GetResString());
}
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 this.Read(buffer, 0, buffer.Length);
}
/// <summary>
/// 设置流位置
/// </summary>
/// <param name="offset"></param>
/// <param name="origin"></param>
/// <returns></returns>
/// <exception cref="ByteBlockDisposedException"></exception>
public override long Seek(long offset, SeekOrigin origin)
{
if (!this.@using)
{
throw new ByteBlockDisposedException(ResType.ByteBlockDisposed.GetResString());
}
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>
/// <exception cref="ByteBlockDisposedException"></exception>
public void SetCapacity(int size, bool retainedData = false)
{
if (!this.@using)
{
throw new ByteBlockDisposedException(ResType.ByteBlockDisposed.GetResString());
}
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>
/// <exception cref="ByteBlockDisposedException"></exception>
public void SetHolding(bool holding)
{
if (!this.@using)
{
throw new ByteBlockDisposedException(ResType.ByteBlockDisposed.GetResString());
}
this.holding = holding;
if (!holding)
{
this.Dispose();
}
}
/// <summary>
/// 设置实际长度
/// </summary>
/// <param name="value"></param>
/// <exception cref="ByteBlockDisposedException"></exception>
public override void SetLength(long value)
{
if (!this.@using)
{
throw new ByteBlockDisposedException(ResType.ByteBlockDisposed.GetResString());
}
if (value > this._buffer.Length)
{
throw new RRQMException("设置值超出容量");
}
this.length = value;
}
/// <summary>
/// 转换为有效内存
/// </summary>
/// <returns></returns>
public byte[] ToArray()
{
return this.ToArray(0);
}
/// <summary>
/// 从指定位置转化到有效内存
/// </summary>
/// <param name="offset"></param>
/// <returns></returns>
/// <exception cref="ByteBlockDisposedException"></exception>
public byte[] ToArray(int offset)
{
return this.ToArray(offset, (int)(this.length - offset));
}
/// <summary>
/// 从指定位置转化到指定长度的有效内存
/// </summary>
/// <param name="offset"></param>
/// <param name="length"></param>
/// <returns></returns>
public byte[] ToArray(int offset, int length)
{
if (!this.@using)
{
throw new ByteBlockDisposedException(ResType.ByteBlockDisposed.GetResString());
}
byte[] buffer = new byte[length];
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>
/// <exception cref="ByteBlockDisposedException"></exception>
public override void Write(byte[] buffer, int offset, int count)
{
if (!this.@using)
{
throw new ByteBlockDisposedException(ResType.ByteBlockDisposed.GetResString());
}
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, this._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 float 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
// API首页https://www.yuque.com/eo2w71/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 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, 1024 * 1024 * 20);
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
// API首页https://www.yuque.com/eo2w71/rrqm
// 交流QQ群234762506
// 感谢您的下载和使用
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
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)
{
this.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,125 @@
//------------------------------------------------------------------------------
// 此代码版权除特别声明或在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
// API首页https://www.yuque.com/eo2w71/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,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
// API首页https://www.yuque.com/eo2w71/rrqm
// 交流QQ群234762506
// 感谢您的下载和使用
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
using System;
using System.Collections;
using System.Collections.Generic;
using System.Threading;
namespace RRQMCore.Collections.Concurrent
{
/// <summary>
/// 线程安全的List其基本操作和List一致。
/// </summary>
/// <typeparam name="T"></typeparam>
public class ConcurrentList<T> : IList<T>
{
private readonly List<T> list;
[NonSerialized]
private readonly ReaderWriterLockSlim locker;
/// <summary>
/// 构造函数
/// </summary>
/// <param name="collection"></param>
public ConcurrentList(IEnumerable<T> collection)
{
this.list = new List<T>(collection);
this.locker = new ReaderWriterLockSlim();
}
/// <summary>
/// 构造函数
/// </summary>
public ConcurrentList()
{
this.list = new List<T>();
this.locker = new ReaderWriterLockSlim();
}
/// <summary>
/// 构造函数
/// </summary>
/// <param name="capacity"></param>
public ConcurrentList(int capacity)
{
this.list = new List<T>(capacity);
this.locker = new ReaderWriterLockSlim();
}
/// <summary>
/// 元素数量
/// </summary>
public int Count
{
get
{
try
{
this.locker.EnterReadLock();
return this.list.Count;
}
finally
{
this.locker.ExitReadLock();
}
}
}
/// <summary>
/// 是否为只读
/// </summary>
public bool IsReadOnly => false;
/// <summary>
/// 获取索引元素
/// </summary>
/// <param name="index"></param>
/// <returns></returns>
public T this[int index]
{
get
{
try
{
this.locker.EnterReadLock();
return this.list[index];
}
finally
{
this.locker.ExitReadLock();
}
}
set
{
try
{
this.locker.EnterWriteLock();
this.list[index] = value;
}
finally
{
this.locker.ExitWriteLock();
}
}
}
/// <summary>
/// 添加元素
/// </summary>
/// <param name="item"></param>
public void Add(T item)
{
try
{
this.locker.EnterWriteLock();
this.list.Add(item);
}
finally
{
this.locker.ExitWriteLock();
}
}
/// <summary>
/// 清空所有元素
/// </summary>
public void Clear()
{
try
{
this.locker.EnterWriteLock();
this.list.Clear();
}
finally
{
this.locker.ExitWriteLock();
}
}
/// <summary>
/// 是否包含某个元素
/// </summary>
/// <param name="item"></param>
/// <returns></returns>
public bool Contains(T item)
{
try
{
this.locker.EnterReadLock();
return this.list.Contains(item);
}
finally
{
this.locker.ExitReadLock();
}
}
/// <summary>
/// 复制到
/// </summary>
/// <param name="array"></param>
/// <param name="arrayIndex"></param>
public void CopyTo(T[] array, int arrayIndex)
{
try
{
this.locker.EnterReadLock();
this.list.CopyTo(array, arrayIndex);
}
finally
{
this.locker.ExitReadLock();
}
}
/// <summary>
/// 返回迭代器
/// </summary>
/// <returns></returns>
public IEnumerator<T> GetEnumerator()
{
try
{
this.locker.EnterReadLock();
foreach (var item in this.list)
{
yield return item;
}
}
finally
{
this.locker.ExitReadLock();
}
}
/// <summary>
/// 返回迭代器组合
/// </summary>
/// <returns></returns>
IEnumerator IEnumerable.GetEnumerator()
{
return this.GetEnumerator();
}
/// <summary>
/// 索引
/// </summary>
/// <param name="item"></param>
/// <returns></returns>
public int IndexOf(T item)
{
try
{
this.locker.EnterReadLock();
return this.list.IndexOf(item);
}
finally
{
this.locker.ExitReadLock();
}
}
/// <summary>
/// 插入
/// </summary>
/// <param name="index"></param>
/// <param name="item"></param>
public void Insert(int index, T item)
{
try
{
this.locker.EnterWriteLock();
this.list.Insert(index, item);
}
finally
{
this.locker.ExitWriteLock();
}
}
/// <summary>
/// 移除元素
/// </summary>
/// <param name="item"></param>
/// <returns></returns>
public bool Remove(T item)
{
try
{
this.locker.EnterWriteLock();
return this.list.Remove(item);
}
finally
{
this.locker.ExitWriteLock();
}
}
/// <summary>
/// 按索引移除
/// </summary>
/// <param name="index"></param>
public void RemoveAt(int index)
{
try
{
this.locker.EnterWriteLock();
if (index < this.list.Count)
{
this.list.RemoveAt(index);
}
}
finally
{
this.locker.ExitWriteLock();
}
}
/// <summary>
/// 获取或设置容量
/// </summary>
public int Capacity
{
get
{
try
{
this.locker.EnterReadLock();
return this.list.Capacity;
}
finally
{
this.locker.ExitReadLock();
}
}
set
{
try
{
this.locker.EnterWriteLock();
this.list.Capacity = value;
}
finally
{
this.locker.ExitWriteLock();
}
}
}
/// <summary>
/// <inheritdoc cref="List{T}.AddRange(IEnumerable{T})"/>
/// </summary>
/// <param name="collection"></param>
public void AddRange(IEnumerable<T> collection)
{
try
{
this.locker.EnterWriteLock();
this.list.AddRange(collection);
}
finally
{
this.locker.ExitWriteLock();
}
}
/// <summary>
/// <inheritdoc cref="List{T}.BinarySearch(T)"/>
/// </summary>
/// <param name="item"></param>
/// <returns></returns>
public int BinarySearch(T item)
{
try
{
this.locker.EnterReadLock();
return this.list.BinarySearch(item);
}
finally
{
this.locker.ExitReadLock();
}
}
/// <summary>
/// <inheritdoc cref="List{T}.BinarySearch(T, IComparer{T})"/>
/// </summary>
/// <param name="item"></param>
/// <param name="comparer"></param>
/// <returns></returns>
public int BinarySearch(T item, IComparer<T> comparer)
{
try
{
this.locker.EnterReadLock();
return this.list.BinarySearch(item, comparer);
}
finally
{
this.locker.ExitReadLock();
}
}
/// <summary>
/// <inheritdoc cref="List{T}.BinarySearch(int, int, T, IComparer{T})"/>
/// </summary>
/// <param name="index"></param>
/// <param name="count"></param>
/// <param name="item"></param>
/// <param name="comparer"></param>
/// <returns></returns>
public int BinarySearch(int index, int count, T item, IComparer<T> comparer)
{
try
{
this.locker.EnterReadLock();
return this.list.BinarySearch(index, count, item, comparer);
}
finally
{
this.locker.ExitReadLock();
}
}
/// <summary>
/// <inheritdoc cref="List{T}.ConvertAll{TOutput}(Converter{T, TOutput})"/>
/// </summary>
/// <typeparam name="TOutput"></typeparam>
/// <param name="converter"></param>
/// <returns></returns>
public List<TOutput> ConvertAll<TOutput>(Converter<T, TOutput> converter)
{
try
{
this.locker.EnterReadLock();
return this.list.ConvertAll(converter);
}
finally
{
this.locker.ExitReadLock();
}
}
/// <summary>
/// <inheritdoc cref="List{T}.Find(Predicate{T})"/>
/// </summary>
/// <param name="match"></param>
/// <returns></returns>
public T Find(Predicate<T> match)
{
try
{
this.locker.EnterReadLock();
return this.list.Find(match);
}
finally
{
this.locker.ExitReadLock();
}
}
/// <summary>
/// <inheritdoc cref="List{T}.FindAll(Predicate{T})"/>
/// </summary>
/// <param name="match"></param>
/// <returns></returns>
public List<T> FindAll(Predicate<T> match)
{
try
{
this.locker.EnterReadLock();
return this.list.FindAll(match);
}
finally
{
this.locker.ExitReadLock();
}
}
/// <summary>
/// <inheritdoc cref="List{T}.FindIndex(int, int, Predicate{T})"/>
/// </summary>
/// <param name="startIndex"></param>
/// <param name="count"></param>
/// <param name="match"></param>
/// <returns></returns>
public int FindIndex(int startIndex, int count, Predicate<T> match)
{
try
{
this.locker.EnterReadLock();
return this.list.FindIndex(startIndex, count, match);
}
finally
{
this.locker.ExitReadLock();
}
}
/// <summary>
/// <inheritdoc cref="List{T}.FindIndex(int, Predicate{T})"/>
/// </summary>
/// <param name="startIndex"></param>
/// <param name="match"></param>
/// <returns></returns>
public int FindIndex(int startIndex, Predicate<T> match)
{
try
{
this.locker.EnterReadLock();
return this.list.FindIndex(startIndex, match);
}
finally { this.locker.ExitReadLock(); }
}
/// <summary>
/// <inheritdoc cref="List{T}.FindIndex(Predicate{T})"/>
/// </summary>
/// <param name="match"></param>
/// <returns></returns>
public int FindIndex(Predicate<T> match)
{
try
{
this.locker.EnterReadLock();
return this.list.FindIndex(match);
}
finally { this.locker.ExitReadLock(); }
}
/// <summary>
/// <inheritdoc cref="List{T}.FindLast(Predicate{T})"/>
/// </summary>
/// <param name="match"></param>
/// <returns></returns>
public T FindLast(Predicate<T> match)
{
try
{
this.locker.EnterReadLock();
return this.list.FindLast(match);
}
finally { this.locker.ExitReadLock(); }
}
/// <summary>
/// <inheritdoc cref="List{T}.FindLastIndex(int, int, Predicate{T})"/>
/// </summary>
/// <param name="startIndex"></param>
/// <param name="count"></param>
/// <param name="match"></param>
/// <returns></returns>
public int FindLastIndex(int startIndex, int count, Predicate<T> match)
{
try
{
this.locker.EnterReadLock();
return this.list.FindLastIndex(startIndex, count, match);
}
finally { this.locker.ExitReadLock(); }
}
/// <summary>
/// <inheritdoc cref="List{T}.FindLastIndex(int, Predicate{T})"/>
/// </summary>
/// <param name="startIndex"></param>
/// <param name="match"></param>
/// <returns></returns>
public int FindLastIndex(int startIndex, Predicate<T> match)
{
try
{
this.locker.EnterReadLock();
return this.list.FindLastIndex(startIndex, match);
}
finally { this.locker.ExitReadLock(); }
}
/// <summary>
/// <inheritdoc cref="List{T}.FindLastIndex(Predicate{T})"/>
/// </summary>
/// <param name="match"></param>
/// <returns></returns>
public int FindLastIndex(Predicate<T> match)
{
try
{
this.locker.EnterReadLock();
return this.list.FindLastIndex(match);
}
finally { this.locker.ExitReadLock(); }
}
/// <summary>
/// <inheritdoc cref="List{T}.ForEach(Action{T})"/>
/// </summary>
/// <param name="action"></param>
public void ForEach(Action<T> action)
{
try
{
this.locker.EnterReadLock();
this.list.ForEach(action);
}
finally
{
this.locker.ExitReadLock();
}
}
/// <summary>
/// <inheritdoc cref="List{T}.GetRange(int, int)"/>
/// </summary>
/// <param name="index"></param>
/// <param name="count"></param>
/// <returns></returns>
public List<T> GetRange(int index, int count)
{
try
{
this.locker.EnterReadLock();
return this.list.GetRange(index, count);
}
finally { this.locker.ExitReadLock(); }
}
/// <summary>
/// <inheritdoc cref="List{T}.IndexOf(T, int)"/>
/// </summary>
/// <param name="item"></param>
/// <param name="index"></param>
/// <returns></returns>
public int IndexOf(T item, int index)
{
try
{
this.locker.EnterReadLock();
return this.list.IndexOf(item, index);
}
finally { this.locker.ExitReadLock(); }
}
/// <summary>
/// <inheritdoc cref="List{T}.IndexOf(T, int, int)"/>
/// </summary>
/// <param name="item"></param>
/// <param name="index"></param>
/// <param name="count"></param>
/// <returns></returns>
public int IndexOf(T item, int index, int count)
{
try
{
this.locker.EnterReadLock();
return this.list.IndexOf(item, index, count);
}
finally { this.locker.ExitReadLock(); }
}
/// <summary>
/// <inheritdoc cref="List{T}.InsertRange(int, IEnumerable{T})"/>
/// </summary>
/// <param name="index"></param>
/// <param name="collection"></param>
public void InsertRange(int index, IEnumerable<T> collection)
{
try
{
this.locker.EnterWriteLock();
this.list.InsertRange(index, collection);
}
finally
{
this.locker.ExitWriteLock();
}
}
/// <summary>
/// <inheritdoc cref="List{T}.LastIndexOf(T)"/>
/// </summary>
/// <param name="item"></param>
/// <returns></returns>
public int LastIndexOf(T item)
{
try
{
this.locker.EnterReadLock();
return this.list.IndexOf(item);
}
finally { this.locker.ExitReadLock(); }
}
/// <summary>
/// <inheritdoc cref="List{T}.LastIndexOf(T, int)"/>
/// </summary>
/// <param name="item"></param>
/// <param name="index"></param>
/// <returns></returns>
public int LastIndexOf(T item, int index)
{
try
{
this.locker.EnterReadLock();
return this.list.LastIndexOf(item, index);
}
finally { this.locker.ExitReadLock(); }
}
/// <summary>
/// <inheritdoc cref="List{T}.LastIndexOf(T, int, int)"/>
/// </summary>
/// <param name="item"></param>
/// <param name="index"></param>
/// <param name="count"></param>
/// <returns></returns>
public int LastIndexOf(T item, int index, int count)
{
try
{
this.locker.EnterReadLock();
return this.list.LastIndexOf(item, index, count);
}
finally { this.locker.ExitReadLock(); }
}
/// <summary>
/// <inheritdoc cref="List{T}.RemoveAll(Predicate{T})"/>
/// </summary>
/// <param name="match"></param>
public void RemoveAll(Predicate<T> match)
{
try
{
this.locker.EnterWriteLock();
this.list.RemoveAll(match);
}
finally
{
this.locker.ExitWriteLock();
}
}
/// <summary>
/// <inheritdoc cref="List{T}.RemoveRange(int, int)"/>
/// </summary>
/// <param name="index"></param>
/// <param name="count"></param>
public void RemoveRange(int index, int count)
{
try
{
this.locker.EnterWriteLock();
this.list.RemoveRange(index, count);
}
finally
{
this.locker.ExitWriteLock();
}
}
/// <summary>
/// <inheritdoc cref="List{T}.Reverse()"/>
/// </summary>
public void Reverse()
{
try
{
this.locker.EnterWriteLock();
this.list.Reverse();
}
finally
{
this.locker.ExitWriteLock();
}
}
/// <summary>
/// <inheritdoc cref="List{T}.Reverse(int, int)"/>
/// </summary>
/// <param name="index"></param>
/// <param name="count"></param>
public void Reverse(int index, int count)
{
try
{
this.locker.EnterWriteLock();
this.list.Reverse(index, count);
}
finally { this.locker.ExitWriteLock(); }
}
/// <summary>
/// <inheritdoc cref="List{T}.Sort()"/>
/// </summary>
public void Sort()
{
try
{
this.locker.EnterWriteLock();
this.list.Sort();
}
finally
{
this.locker.ExitWriteLock();
}
}
/// <summary>
/// <inheritdoc cref="List{T}.Sort(Comparison{T})"/>
/// </summary>
/// <param name="comparison"></param>
public void Sort(Comparison<T> comparison)
{
try
{
this.locker.EnterWriteLock();
this.list.Sort(comparison);
}
finally { this.locker.ExitWriteLock(); }
}
/// <summary>
/// <inheritdoc cref="List{T}.Sort(IComparer{T})"/>
/// </summary>
/// <param name="comparer"></param>
public void Sort(IComparer<T> comparer)
{
try
{
this.locker.EnterWriteLock();
this.list.Sort(comparer);
}
finally { this.locker.ExitWriteLock(); }
}
/// <summary>
/// <inheritdoc cref="List{T}.Sort(int, int, IComparer{T})"/>
/// </summary>
/// <param name="index"></param>
/// <param name="count"></param>
/// <param name="comparer"></param>
public void Sort(int index, int count, IComparer<T> comparer)
{
try
{
this.locker.EnterWriteLock();
this.list.Sort(index, count, comparer);
}
finally { this.locker.ExitWriteLock(); }
}
/// <summary>
/// <inheritdoc cref="List{T}.ToArray"/>
/// </summary>
/// <returns></returns>
public T[] ToArray()
{
try
{
this.locker.EnterReadLock();
return this.list.ToArray();
}
finally
{
this.locker.ExitReadLock();
}
}
/// <summary>
/// <inheritdoc cref="List{T}.TrimExcess"/>
/// </summary>
public void TrimExcess()
{
try
{
this.locker.EnterWriteLock();
this.list.TrimExcess();
}
finally
{
this.locker.ExitWriteLock();
}
}
/// <summary>
/// <inheritdoc cref="List{T}.TrueForAll(Predicate{T})"/>
/// </summary>
/// <param name="match"></param>
/// <returns></returns>
public bool TrueForAll(Predicate<T> match)
{
try
{
this.locker.EnterReadLock();
return this.list.TrueForAll(match);
}
finally { this.locker.ExitReadLock(); }
}
}
}

View File

@@ -0,0 +1,84 @@
//------------------------------------------------------------------------------
// 此代码版权除特别声明或在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
// API首页https://www.yuque.com/eo2w71/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 this.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 this.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 this.count);
return true;
}
return false;
}
private bool Check()
{
return this.count < this.maxCount;
}
}
}

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
// API首页https://www.yuque.com/eo2w71/rrqm
// 交流QQ群234762506
// 感谢您的下载和使用
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
using System;
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 bool overflowWait;
/// <summary>
/// 溢出等待
/// </summary>
public bool OverflowWait
{
get { return this.overflowWait; }
set { this.overflowWait = value; }
}
private Action<bool> onQueueChanged;
/// <summary>
/// 在队列修改时
/// </summary>
public Action<bool> OnQueueChanged
{
get { return this.onQueueChanged; }
set { this.onQueueChanged = value; }
}
private bool free;
/// <summary>
/// 是否有空位允许入队
/// </summary>
public bool Free
{
get { return this.free; }
}
private long actualSize;
private long maxSize;
/// <summary>
/// 构造函数
/// </summary>
/// <param name="maxSize"></param>
public IntelligentDataQueue(long maxSize)
{
this.free = true;
this.overflowWait = true;
this.MaxSize = maxSize;
}
/// <summary>
/// 构造函数
/// </summary>
public IntelligentDataQueue() : this(1024 * 1024 * 10)
{
}
/// <summary>
/// 允许的最大长度
/// </summary>
public long MaxSize
{
get { return this.maxSize; }
set
{
if (value < 1)
{
value = 1;
}
this.maxSize = value;
}
}
/// <summary>
/// 实际尺寸
/// </summary>
public long ActualSize
{
get { return this.actualSize; }
}
/// <summary>
/// 清空队列
/// </summary>
public void Clear(Action<T> onClear)
{
while (base.TryDequeue(out T t))
{
onClear?.Invoke(t);
}
}
/// <summary>
/// 入队
/// </summary>
/// <param name="item"></param>
public new void Enqueue(T item)
{
bool free = this.actualSize < this.maxSize;
if (this.free != free)
{
this.free = free;
this.onQueueChanged?.Invoke(this.free);
}
if (this.overflowWait)
{
SpinWait.SpinUntil(this.Check);
}
Interlocked.Add(ref this.actualSize, item.Size);
base.Enqueue(item);
}
/// <summary>
/// 出队
/// </summary>
/// <param name="result"></param>
/// <returns></returns>
public new bool TryDequeue(out T result)
{
if (base.TryDequeue(out result))
{
Interlocked.Add(ref this.actualSize, -result.Size);
bool free = this.actualSize < this.maxSize;
if (this.free != free)
{
this.free = free;
this.onQueueChanged?.Invoke(this.free);
}
return true;
}
return false;
}
private bool Check()
{
return this.actualSize < this.maxSize;
}
}
/// <summary>
/// 队列数据
/// </summary>
public interface IQueueData
{
/// <summary>
/// 数据长度
/// </summary>
int Size { get; }
}
}

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
// API首页https://www.yuque.com/eo2w71/rrqm
// 交流QQ群234762506
// 感谢您的下载和使用
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
using RRQMCore.Helper;
using RRQMCore.XREF.Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
namespace RRQMCore
{
/// <summary>
/// 运行配置类
/// </summary>
public abstract class AppConfigBase
{
private readonly string fullPath;
/// <summary>
/// 构造函数
/// </summary>
/// <param name="fullPath"></param>
public AppConfigBase(string fullPath)
{
if (string.IsNullOrEmpty(fullPath))
{
throw new ArgumentException($"“{nameof(fullPath)}”不能为 null 或空。", nameof(fullPath));
}
this.fullPath = fullPath;
}
/// <summary>
/// 保存配置
/// </summary>
/// <param name="overwrite"></param>
/// <param name="msg"></param>
/// <returns></returns>
public bool Save(bool overwrite, out string msg)
{
if (overwrite == false && File.Exists(this.fullPath))
{
msg = null;
return true;
}
try
{
File.WriteAllBytes(this.fullPath, Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(this, Formatting.Indented)));
msg = null;
return true;
}
catch (Exception ex)
{
msg = ex.Message;
return false;
}
}
/// <summary>
/// 加载配置
/// </summary>
/// <param name="msg"></param>
/// <returns></returns>
public bool Load(out string msg)
{
try
{
if (!File.Exists(this.fullPath))
{
this.Save(false, out _);
}
var obj = File.ReadAllText(this.fullPath).ToJsonObject(this.GetType());
var ps = this.GetType().GetProperties();
foreach (var item in ps)
{
item.SetValue(this, item.GetValue(obj));
}
msg = null;
return true;
}
catch (Exception ex)
{
msg = ex.Message;
return false;
}
}
/// <summary>
/// 获取默认配置。
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
public static T GetDefault<T>() where T : AppConfigBase, new()
{
Type type = typeof(T);
if (list.TryGetValue(type, out object value))
{
return (T)value;
}
T _default = ((T)Activator.CreateInstance(typeof(T)));
_default.Load(out _);
list.Add(type, _default);
return _default;
}
static Dictionary<Type, object> list = new Dictionary<Type, object>();
/// <summary>
/// 获取默认配置,每次调用该方法时,都会重新加载配置。
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
public static T GetNewDefault<T>() where T : AppConfigBase, new()
{
T _default = ((T)Activator.CreateInstance(typeof(T)));
_default.Load(out _);
if (list.ContainsKey(_default.GetType()))
{
list[_default.GetType()] = _default;
}
else
{
list.Add(_default.GetType(), _default);
}
return _default;
}
}
}

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
// API首页https://www.yuque.com/eo2w71/rrqm
// 交流QQ群234762506
// 感谢您的下载和使用
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
namespace RRQMCore
{
/// <summary>
/// 大小端类型
/// </summary>
public enum EndianType
{
/// <summary>
/// 小端模式
/// </summary>
Little,
/// <summary>
/// 大端模式
/// </summary>
Big
}
}

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
// API首页https://www.yuque.com/eo2w71/rrqm
// 交流QQ群234762506
// 感谢您的下载和使用
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
namespace RRQMCore
{
/// <summary>
/// RRQM资源枚举
/// </summary>
public enum ResType
{
/// <summary>
/// 未知知错误
/// </summary>
UnknownError,
/// <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>
StreamNotFind,
/// <summary>
/// 没有找到客户端
/// </summary>
ClientNotFind,
/// <summary>
/// 流文件正在被应用
/// </summary>
StreamReferencing,
/// <summary>
/// 接收流容器为空
/// </summary>
StreamBucketNull,
/// <summary>
/// 加载流异常。
/// </summary>
LoadStreamFail,
/// <summary>
/// 事件操作器异常
/// </summary>
GetEventArgsFail,
/// <summary>
/// 长时间没有响应。
/// </summary>
NoResponse,
/// <summary>
/// 该Token消息已注册
/// </summary>
TokenExist,
/// <summary>
/// 信息未找到
/// </summary>
MessageNotFound,
/// <summary>
/// 内存块已释放
/// </summary>
ByteBlockDisposed,
/// <summary>
/// 数据处理适配器为空
/// </summary>
NullDataAdapter,
/// <summary>
/// 操作超时
/// </summary>
Overtime,
/// <summary>
/// 名称为“{0}”的事件已存在
/// </summary>
EventExisted,
/// <summary>
/// 名称为“{0}”的事件不存在
/// </summary>
EventNotExist
}
}

View File

@@ -0,0 +1,46 @@
//------------------------------------------------------------------------------
// 此代码版权除特别声明或在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
// API首页https://www.yuque.com/eo2w71/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,30 @@
//------------------------------------------------------------------------------
// 此代码版权除特别声明或在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
// API首页https://www.yuque.com/eo2w71/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,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
// API首页https://www.yuque.com/eo2w71/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,436 @@
//------------------------------------------------------------------------------
// 此代码版权除特别声明或在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
// API首页https://www.yuque.com/eo2w71/rrqm
// 交流QQ群234762506
// 感谢您的下载和使用
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
using System;
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 this.endianType; }
}
/// <summary>
/// 判断当前系统是否为设置的大小端
/// </summary>
/// <returns></returns>
public bool IsSameOfSet()
{
return !(BitConverter.IsLittleEndian ^ (this.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 (!this.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 (!this.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 (!this.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 (!this.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 (!this.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 (!this.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 (!this.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 (!this.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 (!this.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 (!this.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 (!this.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 (!this.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 (!this.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 (!this.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 (!this.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 (!this.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 (!this.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 (!this.IsSameOfSet())
{
Array.Reverse(bytes);
}
return BitConverter.ToDouble(bytes, 0);
}
#endregion
}
}

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
// API首页https://www.yuque.com/eo2w71/rrqm
// 交流QQ群234762506
// 感谢您的下载和使用
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
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,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
// API首页https://www.yuque.com/eo2w71/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 注释
}
}

61
RRQMCore/Common/Result.cs Normal file
View File

@@ -0,0 +1,61 @@
//------------------------------------------------------------------------------
// 此代码版权除特别声明或在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
// API首页https://www.yuque.com/eo2w71/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 $"类型:{this.ResultCode},信息:{this.Message}";
}
}
}

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
// API首页https://www.yuque.com/eo2w71/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 = this.timeGen();
if (this.lastTimestamp == timestamp)
{ //同一微妙中生成ID
SnowflakeIDGenerator.sequence = (SnowflakeIDGenerator.sequence + 1) & SnowflakeIDGenerator.sequenceMask; //用&运算计算该微秒内产生的计数是否已经到达上限
if (SnowflakeIDGenerator.sequence == 0)
{
//一微妙内产生的ID计数已达上限等待下一微妙
timestamp = this.tillNextMillis(this.lastTimestamp);
}
}
else
{ //不同微秒生成ID
SnowflakeIDGenerator.sequence = 0; //计数清0
}
if (timestamp < this.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 = this.timeGen();
while (timestamp <= lastTimestamp)
{
timestamp = this.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,54 @@
//------------------------------------------------------------------------------
// 此代码版权除特别声明或在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
// API首页https://www.yuque.com/eo2w71/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)
{
string res = Resource.ResourceManager.GetString(@enum.ToString());
if (res == null)
{
return @enum.ToString();
}
return res;
}
/// <summary>
/// 获取资源字符
/// </summary>
/// <param name="enum"></param>
/// <param name="objs"></param>
/// <returns></returns>
public static string GetResString(this Enum @enum, params object[] objs)
{
string res = Resource.ResourceManager.GetString(@enum.ToString());
if (res == null)
{
return @enum.ToString();
}
return res.Format(objs);
}
}
}

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
// API首页https://www.yuque.com/eo2w71/rrqm
// 交流QQ群234762506
// 感谢您的下载和使用
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
namespace RRQMCore.Data.Converter
{
/// <summary>
/// 集合转换器
/// </summary>
public class CollectionConvert
{
}
}

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
// API首页https://www.yuque.com/eo2w71/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,69 @@
//------------------------------------------------------------------------------
// 此代码版权除特别声明或在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
// API首页https://www.yuque.com/eo2w71/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,721 @@
//------------------------------------------------------------------------------
// 此代码版权除特别声明或在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
// API首页https://www.yuque.com/eo2w71/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(this.path))
{//存在Xml的文件
XmlDocument xml = new XmlDocument();
xml.Load(this.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(this.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(this.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(this.path))
{//存在Xml的文件
XmlDocument xml = new XmlDocument();
xml.Load(this.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(this.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(this.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(this.path))
{//存在Xml的文件
XmlDocument xml = new XmlDocument();
xml.Load(this.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(this.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(this.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(this.path))
{
//存在Xml的文件
XmlDocument xml = new XmlDocument();
xml.Load(this.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(this.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(this.path);
}
}
}
/// <summary>
/// 节点值存储
/// </summary>
/// <param name="NodeName">节点名</param>
/// <param name="Text">文本</param>
public void NodeStorage(string NodeName, string Text)
{
if (File.Exists(this.path))
{
XmlDocument xml = new XmlDocument();
xml.Load(this.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(this.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(this.path);
}
}
#endregion
#region
/// <summary>
/// 通过节点取值
/// </summary>
/// <param name="NodeName">节点名</param>
/// <returns>取值失败返回null</returns>
public string SearchNode(string NodeName)
{
if (File.Exists(this.path))
{
XmlDocument xml = new XmlDocument();
xml.Load(this.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(this.path))
{
XmlDocument xml = new XmlDocument();
xml.Load(this.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(this.path))
{
XmlDocument xml = new XmlDocument();
xml.Load(this.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(this.path))
{
XmlDocument xml = new XmlDocument();
xml.Load(this.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(this.path))
{
string[] s = new string[NodeName.Length];
XmlDocument xml = new XmlDocument();
xml.Load(this.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(this.path))
{
XmlDocument xml = new XmlDocument();
xml.Load(this.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(this.path))
{
XmlDocument xml = new XmlDocument();
xml.Load(this.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(this.path))
{
XmlDocument xml = new XmlDocument();
xml.Load(this.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(this.path))
{
XmlDocument xml = new XmlDocument();
xml.Load(this.path);
XmlElement root = xml.DocumentElement;
XmlNodeList nodeList = root.ChildNodes;
foreach (XmlNode item in nodeList)
{
if (item.Name == NodeName)
{
root.RemoveChild(item);
xml.Save(this.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(this.path))
{
XmlDocument xml = new XmlDocument();
xml.Load(this.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(this.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(this.path))
{
XmlDocument xml = new XmlDocument();
xml.Load(this.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(this.path);
return true;
}
return false;
}
/// <summary>
/// 判断节点是否存在
/// </summary>
/// <param name="NodeName">节点名</param>
/// <returns>返回结果</returns>
public bool NodeExist(string NodeName)
{
if (File.Exists(this.path))
{
XmlDocument xml = new XmlDocument();
xml.Load(this.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(this.path))
{
XmlDocument xml = new XmlDocument();
xml.Load(this.path);
XmlElement root = xml.DocumentElement;
root.RemoveAll();
xml.Save(this.path);
return true;
}
return false;
}
}
}

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
// API首页https://www.yuque.com/eo2w71/rrqm
// 交流QQ群234762506
// 感谢您的下载和使用
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
using System;
namespace RRQMCore.Dependency
{
/// <summary>
/// 依赖属性数据验证
/// </summary>
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)]
public class DataValidationAttribute : Attribute
{
}
}

View File

@@ -0,0 +1,108 @@
//------------------------------------------------------------------------------
// 此代码版权除特别声明或在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
// API首页https://www.yuque.com/eo2w71/rrqm
// 交流QQ群234762506
// 感谢您的下载和使用
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
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 this.name; }
}
private Type owner;
/// <summary>
/// 所属类型
/// </summary>
public Type Owner
{
get { return this.owner; }
}
private Type valueType;
/// <summary>
/// 值类型
/// </summary>
public Type ValueType
{
get { return this.valueType; }
}
private object value;
/// <summary>
/// 默认值
/// </summary>
public object DefauleValue
{
get { return this.value; }
}
internal void DataValidation(object value)
{
if (value == null)
{
if (typeof(ValueType).IsAssignableFrom(this.valueType))
{
throw new RRQMException($"属性“{this.name}”赋值类型不允许出现Null");
}
}
else if (!this.valueType.IsAssignableFrom(value.GetType()))
{
throw new RRQMException($"属性“{this.name}”赋值类型与注册类型不一致,应当注入“{this.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,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
// API首页https://www.yuque.com/eo2w71/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 (this.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);
this.dp.AddOrUpdate(dependencyProperty, value, (DependencyProperty dp, object v) =>
{
return value;
});
return this;
}
}
}

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
// API首页https://www.yuque.com/eo2w71/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,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
// API首页https://www.yuque.com/eo2w71/rrqm
// 交流QQ群234762506
// 感谢您的下载和使用
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
using System;
namespace RRQMCore
{
/// <summary>
/// 若汝棋茗所有事件基类
/// </summary>
public class RRQMEventArgs : EventArgs
{
}
}

View File

@@ -0,0 +1,121 @@
//------------------------------------------------------------------------------
// 此代码版权除特别声明或在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
// API首页https://www.yuque.com/eo2w71/rrqm
// 交流QQ群234762506
// 感谢您的下载和使用
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
using System;
namespace RRQMCore
{
/// <summary>
/// 若汝棋茗程序集异常类基类
/// </summary>
[Serializable]
public class RRQMException : Exception
{
/// <summary>
/// 构造函数
/// </summary>
public RRQMException() : base()
{
}
/// <summary>
/// 构造函数
/// </summary>
public RRQMException(ResType resType, params object[] fms) : base(resType.GetResString(fms)) { }
/// <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) { }
}
/// <summary>
/// 消息已注册
/// </summary>
[Serializable]
public class MessageRegisteredException : RRQMException
{
/// <summary>
///构造函数
/// </summary>
/// <param name="mes"></param>
public MessageRegisteredException(string mes) : base(mes)
{
}
}
/// <summary>
/// 未找到消息异常类
/// </summary>
[Serializable]
public class MessageNotFoundException : RRQMException
{
/// <summary>
///构造函数
/// </summary>
/// <param name="mes"></param>
public MessageNotFoundException(string mes) : base(mes)
{
}
}
/// <summary>
/// 内存块已释放
/// </summary>
[Serializable]
public class ByteBlockDisposedException : RRQMException
{
/// <summary>
/// 构造函数
/// </summary>
public ByteBlockDisposedException() { }
/// <summary>
/// 构造函数
/// </summary>
/// <param name="message"></param>
public ByteBlockDisposedException(string message) : base(message) { }
/// <summary>
/// 构造函数
/// </summary>
/// <param name="message"></param>
/// <param name="inner"></param>
public ByteBlockDisposedException(string message, Exception inner) : base(message, inner) { }
/// <summary>
/// 构造函数
/// </summary>
/// <param name="info"></param>
/// <param name="context"></param>
protected ByteBlockDisposedException(
System.Runtime.Serialization.SerializationInfo info,
System.Runtime.Serialization.StreamingContext context) : base(info, context) { }
}
}

View File

@@ -0,0 +1,558 @@
//------------------------------------------------------------------------------
// 此代码版权除特别声明或在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
// API首页https://www.yuque.com/eo2w71/rrqm
// 交流QQ群234762506
// 感谢您的下载和使用
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
using RRQMCore.ByteManager;
using RRQMCore.Log;
using RRQMCore.XREF.Newtonsoft.Json;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Globalization;
using System.Reflection;
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;
namespace RRQMCore.Helper
{
/// <summary>
/// 辅助扩展类
/// </summary>
public static class RRQMCoreHelper
{
#region
/// <summary>
/// 输出消息日志
/// </summary>
/// <param name="logger"></param>
/// <param name="msg"></param>
public static void Message(this ILog logger, string msg)
{
logger.Debug(LogType.Message, null, msg);
}
/// <summary>
/// 输出警示日志
/// </summary>
/// <param name="logger"></param>
/// <param name="msg"></param>
public static void Warning(this ILog logger, string msg)
{
logger.Debug(LogType.Warning, null, msg);
}
/// <summary>
/// 输出错误日志
/// </summary>
/// <param name="logger"></param>
/// <param name="msg"></param>
public static void Error(this ILog logger, string msg)
{
logger.Debug(LogType.Error, null, msg);
}
/// <summary>
/// 输出异常日志
/// </summary>
/// <param name="logger"></param>
/// <param name="ex"></param>
public static void Exception(this ILog logger, Exception ex)
{
logger.Debug(LogType.Error, null, ex.Message, ex);
}
/// <summary>
/// 输出消息日志
/// </summary>
/// <param name="logger"></param>
/// <param name="source"></param>
/// <param name="msg"></param>
public static void Message(this ILog logger, object source, string msg)
{
logger.Debug(LogType.Message, source, msg);
}
/// <summary>
/// 输出警示日志
/// </summary>
/// <param name="logger"></param>
/// <param name="source"></param>
/// <param name="msg"></param>
public static void Warning(this ILog logger, object source, string msg)
{
logger.Debug(LogType.Warning, source, msg);
}
/// <summary>
/// 输出错误日志
/// </summary>
/// <param name="logger"></param>
/// <param name="source"></param>
/// <param name="msg"></param>
public static void Error(this ILog logger, object source, string msg)
{
logger.Debug(LogType.Error, source, msg);
}
/// <summary>
/// 输出异常日志
/// </summary>
/// <param name="logger"></param>
/// <param name="source"></param>
/// <param name="ex"></param>
public static void Exception(this ILog logger, object source, Exception ex)
{
logger.Debug(LogType.Error, source, ex.Message, ex);
}
#endregion
/// <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>
/// 索引第一个包含数组的索引位置,例如:在{0,1,2,3,1,2,3}中索引{2,3}则返回3。
/// </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 + offset; i++)
{
if (srcByteArray[i] == subByteArray[hitLength])
{
hitLength++;
}
else
{
hitLength = 0;
}
if (hitLength == subByteArray.Length)
{
return i;
}
}
return -1;
}
#region Json转换
/// <summary>
/// 序列化成Json数据
/// </summary>
/// <param name="obj"></param>
/// <returns></returns>
public static byte[] ToJsonBytes(this object obj)
{
return Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(obj));
}
/// <summary>
/// 反序列化成Json数据
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="buffer"></param>
/// <param name="offset"></param>
/// <param name="len"></param>
/// <returns></returns>
public static T ToJsonObject<T>(this byte[] buffer, int offset, int len)
{
return Encoding.UTF8.GetString(buffer, offset, len).ToJsonObject<T>();
}
/// <summary>
/// 反序列化成Json数据
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="buffer"></param>
/// <returns></returns>
public static T ToJsonObject<T>(this byte[] buffer)
{
return Encoding.UTF8.GetString(buffer).ToJsonObject<T>();
}
/// <summary>
/// 反序列化成Json数据
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="jsonString"></param>
/// <returns></returns>
public static T ToJsonObject<T>(this string jsonString)
{
return JsonConvert.DeserializeObject<T>(jsonString);
}
/// <summary>
/// 反序列化成Json数据
/// </summary>
/// <param name="jsonString"></param>
/// <param name="type"></param>
/// <returns></returns>
public static object ToJsonObject(this string jsonString, Type type)
{
return JsonConvert.DeserializeObject(jsonString, type);
}
#endregion Json转换
/// <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));
}
/// <summary>
/// 转换为UTF-8数据
/// </summary>
/// <param name="value"></param>
/// <returns></returns>
public static byte[] ToUTF8Bytes(this string value)
{
return Encoding.UTF8.GetBytes(value);
}
/// <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;
}
/// <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);
}
/// <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
}
/// <summary>
/// 转Base64。
/// </summary>
/// <param name="data"></param>
/// <returns></returns>
public static string ToBase64(this byte[] data)
{
return Convert.ToBase64String(data);
}
/// <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; }
}
}
}
/// <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);
}
/// <summary>
/// 获取类型
/// </summary>
/// <param name="type"></param>
/// <returns></returns>
public static Type GetRefOutType(this Type type)
{
if (type.IsByRef)
{
return type.GetElementType();
}
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,144 @@
//------------------------------------------------------------------------------
// 此代码版权除特别声明或在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
// API首页https://www.yuque.com/eo2w71/rrqm
// 交流QQ群234762506
// 感谢您的下载和使用
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
using System;
using System.Collections.Generic;
namespace RRQMCore.IO
{
/// <summary>
/// 控制台行为
/// </summary>
public class ConsoleAction
{
private string helpOrder;
/// <summary>
/// 构造函数
/// </summary>
/// <param name="helpOrder">帮助信息指令,如:"h|help|?"</param>
public ConsoleAction(string helpOrder)
{
this.helpOrder = helpOrder;
this.Add(helpOrder, "帮助信息", () =>
{
List<string> s = new List<string>();
foreach (var item in this.actions)
{
if (!s.Contains(item.Value.FullOrder.ToLower()))
{
s.Add(item.Value.FullOrder.ToLower());
Console.WriteLine($"[{item.Value.FullOrder}]-------->{item.Value.Description}");
}
}
});
}
/// <summary>
/// 帮助信息指令
/// </summary>
public string HelpOrder
{
get { return this.helpOrder; }
}
private Dictionary<string, VAction> actions = new Dictionary<string, VAction>();
/// <summary>
/// 添加
/// </summary>
/// <param name="order">指令,多个指令用“|”分割</param>
/// <param name="description">描述</param>
/// <param name="action"></param>
public void Add(string order, string description, Action action)
{
string[] orders = order.ToLower().Split('|');
foreach (var item in orders)
{
this.actions.Add(item, new VAction(description, order, action));
}
}
/// <summary>
/// 执行异常
/// </summary>
public event Action<Exception> OnException;
/// <summary>
/// 执行,返回值仅表示是否有这个指令,异常获取请使用<see cref="OnException"/>
/// </summary>
/// <param name="order"></param>
/// <returns></returns>
public bool Run(string order)
{
if (this.actions.TryGetValue(order.ToLower(), out VAction vAction))
{
try
{
vAction.Action.Invoke();
}
catch (Exception ex)
{
this.OnException?.Invoke(ex);
}
return true;
}
else
{
return false;
}
}
}
internal struct VAction
{
private Action action;
public Action Action
{
get { return this.action; }
}
private string fullOrder;
public string FullOrder
{
get { return this.fullOrder; }
}
private string description;
/// <summary>
/// 构造函数
/// </summary>
/// <param name="action"></param>
/// <param name="description"></param>
/// <param name="fullOrder"></param>
public VAction(string description, string fullOrder, Action action)
{
this.fullOrder = fullOrder;
this.action = action ?? throw new ArgumentNullException(nameof(action));
this.description = description ?? throw new ArgumentNullException(nameof(description));
}
public string Description
{
get { return this.description; }
}
}
}

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
// API首页https://www.yuque.com/eo2w71/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
}
}

View File

@@ -0,0 +1,69 @@
//------------------------------------------------------------------------------
// 此代码版权除特别声明或在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
// API首页https://www.yuque.com/eo2w71/rrqm
// 交流QQ群234762506
// 感谢您的下载和使用
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
using System;
namespace RRQMCore.Log
{
/// <summary>
/// 控制台日志记录器
/// </summary>
public class ConsoleLogger : ILog
{
/// <summary>
/// 记录日志
/// </summary>
/// <param name="logType"></param>
/// <param name="source"></param>
/// <param name="message"></param>
public virtual void Debug(LogType logType, object source, string message)
{
this.Debug(logType, source, message, null);
}
/// <summary>
/// 记录日志
/// </summary>
/// <param name="logType"></param>
/// <param name="source"></param>
/// <param name="message"></param>
/// <param name="exception"></param>
public virtual void Debug(LogType logType, object source, string message, Exception exception)
{
Console.Write(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss ffff"));
Console.Write(" | ");
switch (logType)
{
case LogType.Warning:
Console.ForegroundColor = ConsoleColor.Yellow;
break;
case LogType.Error:
Console.ForegroundColor = ConsoleColor.Red;
break;
case LogType.Message:
default:
break;
}
Console.Write(logType.ToString());
Console.ForegroundColor = ConsoleColor.White;
Console.Write(" | ");
Console.Write(message);
if (exception != null)
{
Console.Write(" | ");
Console.Write($"【堆栈】:{(exception == null ? "" : exception.StackTrace)}");
}
Console.WriteLine();
}
}
}

View File

@@ -0,0 +1,92 @@
//------------------------------------------------------------------------------
// 此代码版权除特别声明或在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
// API首页https://www.yuque.com/eo2w71/rrqm
// 交流QQ群234762506
// 感谢您的下载和使用
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
using System;
using System.IO;
using System.Text;
namespace RRQMCore.Log
{
/// <summary>
/// 文件日志记录器
/// <para>会在指定目录下生成logs文件夹然后按[yyyy-MM-dd].log的形式每日生成日志</para>
/// </summary>
public class FileLogger : ILog
{
private readonly string rootPath;
/// <summary>
/// 构造函数
/// </summary>
/// <param name="rootPath">日志根目录</param>
public FileLogger(string rootPath = null)
{
this.rootPath = Path.Combine(rootPath == null ? AppDomain.CurrentDomain.BaseDirectory : rootPath, "logs");
if (!Directory.Exists(this.rootPath))
{
Directory.CreateDirectory(this.rootPath);
}
}
/// <summary>
/// <inheritdoc/>
/// </summary>
/// <param name="logType"></param>
/// <param name="source"></param>
/// <param name="message"></param>
public void Debug(LogType logType, object source, string message)
{
this.Debug(logType, source, message, null);
}
/// <summary>
/// <inheritdoc/>
/// </summary>
/// <param name="logType"></param>
/// <param name="source"></param>
/// <param name="message"></param>
/// <param name="exception"></param>
public void Debug(LogType logType, object source, string message, Exception exception)
{
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.Append(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss ffff"));
stringBuilder.Append(" | ");
stringBuilder.Append(logType.ToString());
stringBuilder.Append(" | ");
stringBuilder.Append(message);
if (exception != null)
{
stringBuilder.Append(" | ");
stringBuilder.Append($"【堆栈】:{(exception == null ? "" : exception.StackTrace)}");
}
stringBuilder.AppendLine();
this.Print(stringBuilder.ToString());
}
private void Print(string logString)
{
try
{
lock (this)
{
string path = Path.Combine(this.rootPath, DateTime.Now.ToString("[yyyy-MM-dd]") + ".log");
File.AppendAllText(path, logString);
}
}
catch
{
}
}
}
}

40
RRQMCore/Logger/ILog.cs Normal file
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
// API首页https://www.yuque.com/eo2w71/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,36 @@
//------------------------------------------------------------------------------
// 此代码版权除特别声明或在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
// API首页https://www.yuque.com/eo2w71/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,102 @@
//------------------------------------------------------------------------------
// 此代码版权除特别声明或在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
// API首页https://www.yuque.com/eo2w71/rrqm
// 交流QQ群234762506
// 感谢您的下载和使用
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
using System;
namespace RRQMCore.Log
{
/// <summary>
/// 一组日志记录器
/// </summary>
public class LoggerGroup : ILog
{
private readonly ILog[] logs;
/// <summary>
/// 构造函数
/// </summary>
/// <param name="logs"></param>
public LoggerGroup(params ILog[] logs)
{
this.logs = logs ?? throw new ArgumentNullException(nameof(logs));
}
/// <summary>
/// <inheritdoc/>
/// </summary>
/// <param name="logType"></param>
/// <param name="source"></param>
/// <param name="message"></param>
/// <param name="exception"></param>
public void Debug(LogType logType, object source, string message, Exception exception)
{
foreach (var log in this.logs)
{
try
{
log.Debug(logType, source, message, exception);
}
catch
{
}
}
}
/// <summary>
/// <inheritdoc/>
/// </summary>
/// <param name="logType"></param>
/// <param name="source"></param>
/// <param name="message"></param>
public void Debug(LogType logType, object source, string message)
{
this.Debug(logType, source, message, null);
}
/// <summary>
/// 使用指定类型的记录器输出
/// </summary>
/// <param name="logType"></param>
/// <param name="source"></param>
/// <param name="message"></param>
/// <param name="exception"></param>
public void Debug<T>(LogType logType, object source, string message, Exception exception) where T : ILog
{
foreach (var log in this.logs)
{
if (log.GetType() == typeof(T))
{
try
{
log.Debug(logType, source, message, exception);
}
catch
{
}
}
}
}
/// <summary>
/// 使用指定类型的记录器输出
/// </summary>
/// <param name="logType"></param>
/// <param name="source"></param>
/// <param name="message"></param>
public void Debug<T>(LogType logType, object source, string message) where T : ILog
{
this.Debug(logType, source, message, null);
}
}
}

View File

@@ -0,0 +1,32 @@
//------------------------------------------------------------------------------
// 此代码版权除特别声明或在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
// API首页https://www.yuque.com/eo2w71/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,41 @@
//------------------------------------------------------------------------------
// 此代码版权除特别声明或在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
// API首页https://www.yuque.com/eo2w71/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,148 @@
//------------------------------------------------------------------------------
// 此代码版权除特别声明或在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
// API首页https://www.yuque.com/eo2w71/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 this.autoCreate; }
set { this.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

92
RRQMCore/RRQMCore.csproj Normal file
View File

@@ -0,0 +1,92 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net45;net5;netcoreapp3.1;netstandard2.0</TargetFrameworks>
<Authors>若汝棋茗</Authors>
<PackageIcon>RRQM.png</PackageIcon>
<Copyright>Copyright © 2022 若汝棋茗</Copyright>
<Version>7.0.1</Version>
<LangVersion>9.0</LangVersion>
<SignAssembly>true</SignAssembly>
<Description>此程序集是RRQM的核心开源库其中包含了内存池、高性能序列化、日志接口在内的很多基本内容。
更新内容:
增加AppConfigBase更加方便的使用APP配置文件。
增加FileLogger将日志按日期在本地文件保存。
增加LoggerGroup能够在一个日志记录中使用多个记录器。
修改Log修改为ConsoleLogger将日志进行控制台输出。
特别说明本程序集在源码里内嵌了Newtonsoft.Json 11.0.3,但为防止冲突,已修改其命名空间。
特此感谢其作者!!!
附带其Githubhttps://github.com/JamesNK/Newtonsoft.Json</Description>
<PackageProjectUrl>https://gitee.com/dotnetchina/RRQMSocket</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>PublicResXFileCodeGenerator</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>

324
RRQMCore/Resource.Designer.cs generated Normal file
View File

@@ -0,0 +1,324 @@
//------------------------------------------------------------------------------
// <auto-generated>
// 此代码由工具生成。
// 运行时版本:4.0.30319.42000
//
// 对此文件的更改可能会导致不正确的行为,并且如果
// 重新生成代码,这些更改将会丢失。
// </auto-generated>
//------------------------------------------------------------------------------
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()]
public 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)]
public 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)]
public static global::System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set {
resourceCulture = value;
}
}
/// <summary>
/// 查找类似 参数‘{0}’为空。 的本地化字符串。
/// </summary>
public static string ArgumentNull {
get {
return ResourceManager.GetString("ArgumentNull", resourceCulture);
}
}
/// <summary>
/// 查找类似 内存块已释放。 的本地化字符串。
/// </summary>
public static string ByteBlockDisposed {
get {
return ResourceManager.GetString("ByteBlockDisposed", resourceCulture);
}
}
/// <summary>
/// 查找类似 取消操作 的本地化字符串。
/// </summary>
public static string Canceled {
get {
return ResourceManager.GetString("Canceled", resourceCulture);
}
}
/// <summary>
/// 查找类似 没有找到ID为{0}的客户端。 的本地化字符串。
/// </summary>
public static string ClientNotFind {
get {
return ResourceManager.GetString("ClientNotFind", resourceCulture);
}
}
/// <summary>
/// 查找类似 从‘{0}’创建写入流失败,信息:{1}。 的本地化字符串。
/// </summary>
public static string CreateWriteStreamFail {
get {
return ResourceManager.GetString("CreateWriteStreamFail", resourceCulture);
}
}
/// <summary>
/// 查找类似 默认设置值。 的本地化字符串。
/// </summary>
public static string Default {
get {
return ResourceManager.GetString("Default", resourceCulture);
}
}
/// <summary>
/// 查找类似 发生未知错误。 的本地化字符串。
/// </summary>
public static string Error {
get {
return ResourceManager.GetString("Error", resourceCulture);
}
}
/// <summary>
/// 查找类似 名称为“{0}”的事件已存在。 的本地化字符串。
/// </summary>
public static string EventExisted {
get {
return ResourceManager.GetString("EventExisted", resourceCulture);
}
}
/// <summary>
/// 查找类似 名称为“{0}”的事件不存在。 的本地化字符串。
/// </summary>
public static string EventNotExist {
get {
return ResourceManager.GetString("EventNotExist", resourceCulture);
}
}
/// <summary>
/// 查找类似 其他异常消息。 的本地化字符串。
/// </summary>
public static string Exception {
get {
return ResourceManager.GetString("Exception", resourceCulture);
}
}
/// <summary>
/// 查找类似 文件‘{0}’已存在。 的本地化字符串。
/// </summary>
public static string FileExists {
get {
return ResourceManager.GetString("FileExists", resourceCulture);
}
}
/// <summary>
/// 查找类似 事件操作器异常。 的本地化字符串。
/// </summary>
public static string GetEventArgsFail {
get {
return ResourceManager.GetString("GetEventArgsFail", resourceCulture);
}
}
/// <summary>
/// 查找类似 从‘{0}’路径加载流异常,信息:‘{1}’。 的本地化字符串。
/// </summary>
public static string LoadStreamFail {
get {
return ResourceManager.GetString("LoadStreamFail", resourceCulture);
}
}
/// <summary>
/// 查找类似 Token消息为{0}’的未注册。 的本地化字符串。
/// </summary>
public static string MessageNotFound {
get {
return ResourceManager.GetString("MessageNotFound", resourceCulture);
}
}
/// <summary>
/// 查找类似 长时间没有响应。 的本地化字符串。
/// </summary>
public static string NoResponse {
get {
return ResourceManager.GetString("NoResponse", resourceCulture);
}
}
/// <summary>
/// 查找类似 数据处理适配器为空,可能客户端已掉线。 的本地化字符串。
/// </summary>
public static string NullDataAdapter {
get {
return ResourceManager.GetString("NullDataAdapter", resourceCulture);
}
}
/// <summary>
/// 查找类似 操作超时 的本地化字符串。
/// </summary>
public static string Overtime {
get {
return ResourceManager.GetString("Overtime", resourceCulture);
}
}
/// <summary>
/// 查找类似 参数‘{0}’设置的路径‘{1}’不合法。 的本地化字符串。
/// </summary>
public static string PathInvalid {
get {
return ResourceManager.GetString("PathInvalid", resourceCulture);
}
}
/// <summary>
/// 查找类似 远程终端异常,信息:{0}。 的本地化字符串。
/// </summary>
public static string RemoteException {
get {
return ResourceManager.GetString("RemoteException", resourceCulture);
}
}
/// <summary>
/// 查找类似 远程文件‘{0}’不存在。 的本地化字符串。
/// </summary>
public static string RemoteFileNotExists {
get {
return ResourceManager.GetString("RemoteFileNotExists", resourceCulture);
}
}
/// <summary>
/// 查找类似 远程终端不支持响应该操作。 的本地化字符串。
/// </summary>
public static string RemoteNotSupported {
get {
return ResourceManager.GetString("RemoteNotSupported", resourceCulture);
}
}
/// <summary>
/// 查找类似 远程终端拒绝该操作,反馈信息:{0}。 的本地化字符串。
/// </summary>
public static string RemoteRefuse {
get {
return ResourceManager.GetString("RemoteRefuse", resourceCulture);
}
}
/// <summary>
/// 查找类似 通道设置失败。 的本地化字符串。
/// </summary>
public static string SetChannelFail {
get {
return ResourceManager.GetString("SetChannelFail", resourceCulture);
}
}
/// <summary>
/// 查找类似 接收流容器为空。 的本地化字符串。
/// </summary>
public static string StreamBucketNull {
get {
return ResourceManager.GetString("StreamBucketNull", resourceCulture);
}
}
/// <summary>
/// 查找类似 没有找到路径‘{0}’对应的流文件。 的本地化字符串。
/// </summary>
public static string StreamNotFind {
get {
return ResourceManager.GetString("StreamNotFind", resourceCulture);
}
}
/// <summary>
/// 查找类似 路径‘{0}’对应的流文件,仍然被‘{1}’对象应用。 的本地化字符串。
/// </summary>
public static string StreamReferencing {
get {
return ResourceManager.GetString("StreamReferencing", resourceCulture);
}
}
/// <summary>
/// 查找类似 操作成功。 的本地化字符串。
/// </summary>
public static string Success {
get {
return ResourceManager.GetString("Success", resourceCulture);
}
}
/// <summary>
/// 查找类似 Token消息为{0}’的已注册。 的本地化字符串。
/// </summary>
public static string TokenExist {
get {
return ResourceManager.GetString("TokenExist", resourceCulture);
}
}
/// <summary>
/// 查找类似 未知原因错误。 的本地化字符串。
/// </summary>
public static string UnknownError {
get {
return ResourceManager.GetString("UnknownError", resourceCulture);
}
}
}
}

207
RRQMCore/Resource.resx Normal file
View File

@@ -0,0 +1,207 @@
<?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="ByteBlockDisposed" xml:space="preserve">
<value>内存块已释放。</value>
</data>
<data name="Canceled" xml:space="preserve">
<value>取消操作</value>
</data>
<data name="ClientNotFind" xml:space="preserve">
<value>没有找到ID为{0}的客户端。</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="EventExisted" xml:space="preserve">
<value>名称为“{0}”的事件已存在。</value>
</data>
<data name="EventNotExist" xml:space="preserve">
<value>名称为“{0}”的事件不存在。</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}’路径加载流异常,信息:‘{1}’。</value>
</data>
<data name="MessageNotFound" xml:space="preserve">
<value>Token消息为{0}’的未注册。</value>
</data>
<data name="NoResponse" xml:space="preserve">
<value>长时间没有响应。</value>
</data>
<data name="NullDataAdapter" xml:space="preserve">
<value>数据处理适配器为空,可能客户端已掉线。</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="StreamNotFind" xml:space="preserve">
<value>没有找到路径‘{0}’对应的流文件。</value>
</data>
<data name="StreamReferencing" xml:space="preserve">
<value>路径‘{0}’对应的流文件,仍然被‘{1}’对象应用。</value>
</data>
<data name="Success" xml:space="preserve">
<value>操作成功。</value>
</data>
<data name="TokenExist" xml:space="preserve">
<value>Token消息为{0}’的已注册。</value>
</data>
<data name="UnknownError" xml:space="preserve">
<value>未知原因错误。</value>
</data>
</root>

View File

@@ -0,0 +1,61 @@
//------------------------------------------------------------------------------
// 此代码版权除特别声明或在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
// API首页https://www.yuque.com/eo2w71/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,274 @@
//------------------------------------------------------------------------------
// 此代码版权除特别声明或在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
// API首页https://www.yuque.com/eo2w71/rrqm
// 交流QQ群234762506
// 感谢您的下载和使用
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
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 this.executedCount; }
}
/// <summary>
/// 执行间隔
/// </summary>
public TimeSpan Interval
{
get { return this.interval; }
}
/// <summary>
/// 循环次数
/// </summary>
public int LoopCount
{
get { return this.loopCount; }
}
private Action<LoopAction> action;
/// <summary>
/// 执行委托
/// </summary>
public Action<LoopAction> ExecuteAction
{
get { return this.action; }
}
private RunStatus runStatus;
/// <summary>
/// 是否在运行
/// </summary>
public RunStatus RunStatus
{
get { return this.runStatus; }
}
/// <summary>
/// 运行
/// </summary>
public void Run()
{
if (this.runStatus == RunStatus.None)
{
this.runStatus = RunStatus.Running;
if (this.loopCount >= 0)
{
for (int i = 0; i < this.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,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
// API首页https://www.yuque.com/eo2w71/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,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
// API首页https://www.yuque.com/eo2w71/rrqm
// 交流QQ群234762506
// 感谢您的下载和使用
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
using System;
namespace RRQMCore.Run
{
/// <summary>
/// 注册为消息
/// </summary>
[AttributeUsage(AttributeTargets.Method, Inherited = false, AllowMultiple = true)]
public sealed class AppMessageAttribute : Attribute
{
/// <summary>
/// 构造函数
/// </summary>
public AppMessageAttribute()
{
}
/// <summary>
/// 构造函数
/// </summary>
/// <param name="token"></param>
public AppMessageAttribute(string token)
{
this.Token = token;
}
/// <summary>
/// 标识
/// </summary>
public string Token { get; set; }
}
}

View File

@@ -0,0 +1,370 @@
//------------------------------------------------------------------------------
// 此代码版权除特别声明或在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
// API首页https://www.yuque.com/eo2w71/rrqm
// 交流QQ群234762506
// 感谢您的下载和使用
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
namespace RRQMCore.Run
{
/// <summary>
/// 消息通知类
/// </summary>
public class AppMessenger<TMessage> where TMessage : IMessage
{
private bool allowMultiple = false;
private ConcurrentDictionary<string, List<TokenInstance>> tokenAndInstance = new ConcurrentDictionary<string, List<TokenInstance>>();
/// <summary>
/// 允许多广播注册
/// </summary>
public bool AllowMultiple
{
get { return this.allowMultiple; }
set { this.allowMultiple = value; }
}
/// <summary>
/// 判断能否触发该消息,意味着该消息是否已经注册。
/// </summary>
/// <param name="token"></param>
/// <returns></returns>
public bool CanSendMessage(string token)
{
return this.tokenAndInstance.ContainsKey(token);
}
/// <summary>
/// 清除所有消息
/// </summary>
public void Clear()
{
this.tokenAndInstance.Clear();
}
/// <summary>
/// 获取所有消息
/// </summary>
/// <returns></returns>
public string[] GetAllMessage()
{
return this.tokenAndInstance.Keys.ToArray();
}
/// <summary>
/// 注册已加载程序集中直接或间接继承自IMassage接口的所有类并创建新实例
/// </summary>
public void RegistAll()
{
var types = AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(a => a.GetTypes().Where(t => t.GetInterfaces().Contains(typeof(TMessage))))
.ToArray();
foreach (var v in types)
{
TMessage message = (TMessage)Activator.CreateInstance(v);
this.Register(message);
}
}
/// <summary>
/// 注册消息
/// </summary>
/// <param name="messageObject"></param>
/// <param name="action"></param>
public void Register(TMessage messageObject, Action action)
{
this.Register(messageObject, action.Method.Name, action);
}
/// <summary>
/// 注册消息
/// </summary>
/// <typeparam name="T"></typeparam>
public void Register<T>() where T : TMessage
{
this.Register((T)Activator.CreateInstance(typeof(T)));
}
/// <summary>
/// 注册消息
/// </summary>
/// <param name="messageObject"></param>
/// <param name="token"></param>
/// <param name="action"></param>
/// <exception cref="MessageRegisteredException"></exception>
public void Register(TMessage messageObject, string token, Action action)
{
if (this.allowMultiple || !this.tokenAndInstance.ContainsKey(token))
{
TokenInstance tokenInstance = new TokenInstance();
tokenInstance.MessageObject = messageObject;
tokenInstance.MethodInfo = action.Method;
var list = this.tokenAndInstance.GetOrAdd(token, (s) => { return new List<TokenInstance>(); });
list.Add(tokenInstance);
}
else
{
throw new MessageRegisteredException(ResType.TokenExist.GetResString(token));
}
}
/// <summary>
/// 注册消息
/// </summary>
/// <param name="messageObject"></param>
public void Register(TMessage messageObject)
{
MethodInfo[] methods = messageObject.GetType().GetMethods();
foreach (var method in methods)
{
IEnumerable<Attribute> attributes = method.GetCustomAttributes();
foreach (var attribute in attributes)
{
if (attribute is AppMessageAttribute att)
{
if (string.IsNullOrEmpty(att.Token))
{
this.Register(messageObject, method.Name, method);
}
else
{
this.Register(messageObject, att.Token, method);
}
}
}
}
}
/// <summary>
/// 注册消息
/// </summary>
/// <param name="messageObject"></param>
/// <param name="token"></param>
/// <param name="methodInfo"></param>
/// <exception cref="MessageRegisteredException"></exception>
public void Register(TMessage messageObject, string token, MethodInfo methodInfo)
{
if (this.allowMultiple || !this.tokenAndInstance.ContainsKey(token))
{
TokenInstance tokenInstance = new TokenInstance();
tokenInstance.MessageObject = messageObject;
tokenInstance.MethodInfo = methodInfo;
var list = this.tokenAndInstance.GetOrAdd(token, (s) => { return new List<TokenInstance>(); });
list.Add(tokenInstance);
}
else
{
throw new MessageRegisteredException(ResType.TokenExist.GetResString(token));
}
}
/// <summary>
/// 注册消息
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="messageObject"></param>
/// <param name="action"></param>
public void Register<T>(TMessage messageObject, Action<T> action)
{
this.Register(messageObject, action.Method.Name, action);
}
/// <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>(TMessage messageObject, string token, Action<T> action)
{
if (this.allowMultiple || !this.tokenAndInstance.ContainsKey(token))
{
TokenInstance tokenInstance = new TokenInstance();
tokenInstance.MessageObject = messageObject;
tokenInstance.MethodInfo = action.Method;
var list = this.tokenAndInstance.GetOrAdd(token, (s) => { return new List<TokenInstance>(); });
list.Add(tokenInstance);
}
else
{
throw new MessageRegisteredException(ResType.TokenExist.GetResString(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>(TMessage messageObject, string token, Func<T, TReturn> action)
{
if (this.allowMultiple || !this.tokenAndInstance.ContainsKey(token))
{
TokenInstance tokenInstance = new TokenInstance();
tokenInstance.MessageObject = messageObject;
tokenInstance.MethodInfo = action.Method;
var list = this.tokenAndInstance.GetOrAdd(token, (s) => { return new List<TokenInstance>(); });
list.Add(tokenInstance);
}
else
{
throw new MessageRegisteredException(ResType.TokenExist.GetResString(token));
}
}
/// <summary>
/// 注册
/// </summary>
/// <typeparam name="TReturn">返回值类型</typeparam>
/// <param name="messageObject"></param>
/// <param name="token"></param>
/// <param name="action"></param>
public void Register<TReturn>(TMessage messageObject, string token, Func<TReturn> action)
{
if (this.allowMultiple || !this.tokenAndInstance.ContainsKey(token))
{
TokenInstance tokenInstance = new TokenInstance();
tokenInstance.MessageObject = messageObject;
tokenInstance.MethodInfo = action.Method;
var list = this.tokenAndInstance.GetOrAdd(token, (s) => { return new List<TokenInstance>(); });
list.Add(tokenInstance);
}
else
{
throw new MessageRegisteredException(ResType.TokenExist.GetResString(token));
}
}
/// <summary>
/// 发送消息
/// </summary>
/// <param name="token"></param>
/// <param name="parameters"></param>
/// <exception cref="MessageNotFoundException"></exception>
public void Send(string token, params object[] parameters)
{
if (this.tokenAndInstance.TryGetValue(token, out List<TokenInstance> list))
{
foreach (var item in list)
{
item.MethodInfo.Invoke(item.MessageObject, parameters);
}
}
else
{
throw new MessageNotFoundException(ResType.MessageNotFound.GetResString(token));
}
}
/// <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)
{
if (this.tokenAndInstance.TryGetValue(token, out List<TokenInstance> list))
{
for (int i = 0; i < list.Count; i++)
{
var item = list[i];
if (i == list.Count - 1)
{
return (T)item.MethodInfo.Invoke(item.MessageObject, parameters);
}
else
{
item.MethodInfo.Invoke(item.MessageObject, parameters);
}
}
return default;
}
else
{
throw new MessageNotFoundException(ResType.MessageNotFound.GetResString(token));
}
}
/// <summary>
/// 卸载消息
/// </summary>
/// <param name="messageObject"></param>
public void Unregister(TMessage messageObject)
{
List<string> key = new List<string>();
foreach (var item in this.tokenAndInstance.Keys)
{
foreach (var item2 in this.tokenAndInstance[item].ToArray())
{
if ((IMessage)messageObject == item2.MessageObject)
{
this.tokenAndInstance[item].Remove(item2);
if (this.tokenAndInstance[item].Count == 0)
{
key.Add(item);
}
}
}
}
foreach (var item in key)
{
this.tokenAndInstance.TryRemove(item, out _);
}
}
/// <summary>
/// 卸载消息
/// </summary>
public void Unregister(string token)
{
this.tokenAndInstance.TryRemove(token, out _);
}
}
/// <summary>
/// 消息通知类
/// </summary>
public class AppMessenger : AppMessenger<IMessage>
{
private static AppMessenger instance;
/// <summary>
/// 默认单例实例
/// </summary>
public static AppMessenger Default
{
get
{
if (instance == null)
{
instance = new AppMessenger();
}
return instance;
}
}
}
}

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
// API首页https://www.yuque.com/eo2w71/rrqm
// 交流QQ群234762506
// 感谢您的下载和使用
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
namespace RRQMCore.Run
{
/// <summary>
/// 消息接口
/// </summary>
public interface IMessage
{
}
}

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
// API首页https://www.yuque.com/eo2w71/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,36 @@
//------------------------------------------------------------------------------
// 此代码版权除特别声明或在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
// API首页https://www.yuque.com/eo2w71/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,142 @@
//------------------------------------------------------------------------------
// 此代码版权除特别声明或在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
// API首页https://www.yuque.com/eo2w71/rrqm
// 交流QQ群234762506
// 感谢您的下载和使用
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
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 this.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 (this.signCount == int.MaxValue)
{
this.signCount = 0;
}
WaitData<T> waitData;
if (this.waitQueue.TryDequeue(out waitData))
{
result.Sign = Interlocked.Increment(ref this.signCount);
waitData.SetResult(result);
this.waitDic.TryAdd(result.Sign, waitData);
return waitData;
}
waitData = new WaitData<T>();
result.Sign = Interlocked.Increment(ref this.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,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
// API首页https://www.yuque.com/eo2w71/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 => this.status; }
/// <summary>
/// 等待数据结果
/// </summary>
public T WaitResult
{
get { return this.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,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
// API首页https://www.yuque.com/eo2w71/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,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
// API首页https://www.yuque.com/eo2w71/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 this.message; }
set { this.message = value; }
}
/// <summary>
/// 标记号
/// </summary>
public int Sign
{
get { return this.sign; }
set { this.sign = value; }
}
/// <summary>
/// 状态
/// </summary>
public byte Status
{
get { return this.status; }
set { this.status = value; }
}
}
}

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
// API首页https://www.yuque.com/eo2w71/rrqm
// 交流QQ群234762506
// 感谢您的下载和使用
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
using System;
namespace RRQMCore.Serialization
{
/// <summary>
/// 忽略的RRQN序列化
/// </summary>
[AttributeUsage(AttributeTargets.Property)]
public class RRQMNonSerializedAttribute : Attribute
{
}
}

View File

@@ -0,0 +1,32 @@
//------------------------------------------------------------------------------
// 此代码版权除特别声明或在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
// API首页https://www.yuque.com/eo2w71/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(this.Type);
}
internal Type[] ArgTypes;
internal Type ArrayType;
internal Type[] ProTypes;
internal PropertyInfo[] Properties;
internal MethodInfo AddMethod;
}
}

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
// API首页https://www.yuque.com/eo2w71/rrqm
// 交流QQ群234762506
// 感谢您的下载和使用
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
namespace RRQMCore.Serialization
{
internal enum InstanceType
{
Class,
List,
Array,
Dictionary
}
}

View File

@@ -0,0 +1,550 @@
//------------------------------------------------------------------------------
// 此代码版权除特别声明或在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
// API首页https://www.yuque.com/eo2w71/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;
this.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(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 += this.SerializeIEnumerable(stream, (IEnumerable)graph);
}
else
{
len += this.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 RRQMException($"属性名:{property.Name}超长");
}
byte lenBytes = (byte)propertyBytes.Length;
stream.Write(lenBytes);
stream.Write(propertyBytes, 0, propertyBytes.Length);
len += propertyBytes.Length + 1;
len += this.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 += this.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 RRQMException("数据流解析错误");
}
offset += 1;
return this.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 = this.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 = this.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 = this.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 = this.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 = this.Deserialize(instanceObject.ArgTypes[0], datas, ref offset);
offset += datas[offset] + 1;
object value = this.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,36 @@
//------------------------------------------------------------------------------
// 此代码版权除特别声明或在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
// API首页https://www.yuque.com/eo2w71/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,379 @@
//------------------------------------------------------------------------------
// 此代码版权除特别声明或在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
// API首页https://www.yuque.com/eo2w71/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,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
// API首页https://www.yuque.com/eo2w71/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,363 @@
//------------------------------------------------------------------------------
// 此代码版权除特别声明或在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
// API首页https://www.yuque.com/eo2w71/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)
{
this.DateTimeKindHandling = DateTimeKind.Utc;
this._writer = writer;
}
public void Flush()
{
this._writer.Flush();
}
public void Close()
{
#if HAVE_STREAM_READER_WRITER_CLOSE
_writer.Close();
#else
this._writer.Dispose();
#endif
}
public void WriteToken(BsonToken t)
{
this.CalculateSize(t);
this.WriteTokenInternal(t);
}
private void WriteTokenInternal(BsonToken t)
{
switch (t.Type)
{
case BsonType.Object:
{
BsonObject value = (BsonObject)t;
this._writer.Write(value.CalculatedSize);
foreach (BsonProperty property in value)
{
this._writer.Write((sbyte)property.Value.Type);
this.WriteString((string)property.Name.Value, property.Name.ByteCount, null);
this.WriteTokenInternal(property.Value);
}
this._writer.Write((byte)0);
}
break;
case BsonType.Array:
{
BsonArray value = (BsonArray)t;
this._writer.Write(value.CalculatedSize);
ulong index = 0;
foreach (BsonToken c in value)
{
this._writer.Write((sbyte)c.Type);
this.WriteString(index.ToString(CultureInfo.InvariantCulture), MathUtils.IntLength(index), null);
this.WriteTokenInternal(c);
index++;
}
this._writer.Write((byte)0);
}
break;
case BsonType.Integer:
{
BsonValue value = (BsonValue)t;
this._writer.Write(Convert.ToInt32(value.Value, CultureInfo.InvariantCulture));
}
break;
case BsonType.Long:
{
BsonValue value = (BsonValue)t;
this._writer.Write(Convert.ToInt64(value.Value, CultureInfo.InvariantCulture));
}
break;
case BsonType.Number:
{
BsonValue value = (BsonValue)t;
this._writer.Write(Convert.ToDouble(value.Value, CultureInfo.InvariantCulture));
}
break;
case BsonType.String:
{
BsonString value = (BsonString)t;
this.WriteString((string)value.Value, value.ByteCount, value.CalculatedSize - 4);
}
break;
case BsonType.Boolean:
this._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 (this.DateTimeKindHandling == DateTimeKind.Utc)
{
dateTime = dateTime.ToUniversalTime();
}
else if (this.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
this._writer.Write(ticks);
}
break;
case BsonType.Binary:
{
BsonBinary value = (BsonBinary)t;
byte[] data = (byte[])value.Value;
this._writer.Write(data.Length);
this._writer.Write((byte)value.BinaryType);
this._writer.Write(data);
}
break;
case BsonType.Oid:
{
BsonValue value = (BsonValue)t;
byte[] data = (byte[])value.Value;
this._writer.Write(data);
}
break;
case BsonType.Regex:
{
BsonRegex value = (BsonRegex)t;
this.WriteString((string)value.Pattern.Value, value.Pattern.ByteCount, null);
this.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)
{
this._writer.Write(calculatedlengthPrefix.GetValueOrDefault());
}
this.WriteUtf8Bytes(s, byteCount);
this._writer.Write((byte)0);
}
public void WriteUtf8Bytes(string s, int byteCount)
{
if (s != null)
{
if (byteCount <= 256)
{
if (this._largeByteBuffer == null)
{
this._largeByteBuffer = new byte[256];
}
Encoding.GetBytes(s, 0, s.Length, this._largeByteBuffer, 0);
this._writer.Write(this._largeByteBuffer, 0, byteCount);
}
else
{
byte[] bytes = Encoding.GetBytes(s);
this._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 += this.CalculateSize(p.Name);
size += this.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 += this.CalculateSize(MathUtils.IntLength(index));
size += this.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 = this.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 += this.CalculateSize(value.Pattern);
size += this.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,73 @@
//------------------------------------------------------------------------------
// 此代码版权除特别声明或在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
// API首页https://www.yuque.com/eo2w71/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));
}
this.Value = value;
}
}
}

View File

@@ -0,0 +1,871 @@
//------------------------------------------------------------------------------
// 此代码版权除特别声明或在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
// API首页https://www.yuque.com/eo2w71/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)
{
this.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 => this._jsonNet35BinaryCompatibility;
set => this._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 => this._readRootValueAsArray;
set => this._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 => this._dateTimeKindHandling;
set => this._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));
this._reader = new BinaryReader(stream);
this._stack = new List<ContainerContext>();
this._readRootValueAsArray = readRootValueAsArray;
this._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));
this._reader = reader;
this._stack = new List<ContainerContext>();
this._readRootValueAsArray = readRootValueAsArray;
this._dateTimeKindHandling = dateTimeKindHandling;
}
private string ReadElement()
{
this._currentElementType = this.ReadType();
string elementName = this.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 (this._bsonReaderState)
{
case BsonReaderState.Normal:
success = this.ReadNormal();
break;
case BsonReaderState.ReferenceStart:
case BsonReaderState.ReferenceRef:
case BsonReaderState.ReferenceId:
success = this.ReadReference();
break;
case BsonReaderState.CodeWScopeStart:
case BsonReaderState.CodeWScopeCode:
case BsonReaderState.CodeWScopeScope:
case BsonReaderState.CodeWScopeScopeObject:
case BsonReaderState.CodeWScopeScopeEnd:
success = this.ReadCodeWScope();
break;
default:
throw JsonReaderException.Create(this, "Unexpected state: {0}".FormatWith(CultureInfo.InvariantCulture, this._bsonReaderState));
}
if (!success)
{
this.SetToken(JsonToken.None);
return false;
}
return true;
}
catch (EndOfStreamException)
{
this.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 (this.CloseInput)
{
#if HAVE_STREAM_READER_WRITER_CLOSE
_reader?.Close();
#else
this._reader?.Dispose();
#endif
}
}
private bool ReadCodeWScope()
{
switch (this._bsonReaderState)
{
case BsonReaderState.CodeWScopeStart:
this.SetToken(JsonToken.PropertyName, "$code");
this._bsonReaderState = BsonReaderState.CodeWScopeCode;
return true;
case BsonReaderState.CodeWScopeCode:
// total CodeWScope size - not used
this.ReadInt32();
this.SetToken(JsonToken.String, this.ReadLengthString());
this._bsonReaderState = BsonReaderState.CodeWScopeScope;
return true;
case BsonReaderState.CodeWScopeScope:
if (this.CurrentState == State.PostValue)
{
this.SetToken(JsonToken.PropertyName, "$scope");
return true;
}
else
{
this.SetToken(JsonToken.StartObject);
this._bsonReaderState = BsonReaderState.CodeWScopeScopeObject;
ContainerContext newContext = new ContainerContext(BsonType.Object);
this.PushContext(newContext);
newContext.Length = this.ReadInt32();
return true;
}
case BsonReaderState.CodeWScopeScopeObject:
bool result = this.ReadNormal();
if (result && this.TokenType == JsonToken.EndObject)
{
this._bsonReaderState = BsonReaderState.CodeWScopeScopeEnd;
}
return result;
case BsonReaderState.CodeWScopeScopeEnd:
this.SetToken(JsonToken.EndObject);
this._bsonReaderState = BsonReaderState.Normal;
return true;
default:
throw new ArgumentOutOfRangeException();
}
}
private bool ReadReference()
{
switch (this.CurrentState)
{
case State.ObjectStart:
{
this.SetToken(JsonToken.PropertyName, JsonTypeReflector.RefPropertyName);
this._bsonReaderState = BsonReaderState.ReferenceRef;
return true;
}
case State.Property:
{
if (this._bsonReaderState == BsonReaderState.ReferenceRef)
{
this.SetToken(JsonToken.String, this.ReadLengthString());
return true;
}
else if (this._bsonReaderState == BsonReaderState.ReferenceId)
{
this.SetToken(JsonToken.Bytes, this.ReadBytes(12));
return true;
}
else
{
throw JsonReaderException.Create(this, "Unexpected state when reading BSON reference: " + this._bsonReaderState);
}
}
case State.PostValue:
{
if (this._bsonReaderState == BsonReaderState.ReferenceRef)
{
this.SetToken(JsonToken.PropertyName, JsonTypeReflector.IdPropertyName);
this._bsonReaderState = BsonReaderState.ReferenceId;
return true;
}
else if (this._bsonReaderState == BsonReaderState.ReferenceId)
{
this.SetToken(JsonToken.EndObject);
this._bsonReaderState = BsonReaderState.Normal;
return true;
}
else
{
throw JsonReaderException.Create(this, "Unexpected state when reading BSON reference: " + this._bsonReaderState);
}
}
default:
throw JsonReaderException.Create(this, "Unexpected state when reading BSON reference: " + this.CurrentState);
}
}
private bool ReadNormal()
{
switch (this.CurrentState)
{
case State.Start:
{
JsonToken token = (!this._readRootValueAsArray) ? JsonToken.StartObject : JsonToken.StartArray;
BsonType type = (!this._readRootValueAsArray) ? BsonType.Object : BsonType.Array;
this.SetToken(token);
ContainerContext newContext = new ContainerContext(type);
this.PushContext(newContext);
newContext.Length = this.ReadInt32();
return true;
}
case State.Complete:
case State.Closed:
return false;
case State.Property:
{
this.ReadType(this._currentElementType);
return true;
}
case State.ObjectStart:
case State.ArrayStart:
case State.PostValue:
ContainerContext context = this._currentContext;
if (context == null)
{
return false;
}
int lengthMinusEnd = context.Length - 1;
if (context.Position < lengthMinusEnd)
{
if (context.Type == BsonType.Array)
{
this.ReadElement();
this.ReadType(this._currentElementType);
return true;
}
else
{
this.SetToken(JsonToken.PropertyName, this.ReadElement());
return true;
}
}
else if (context.Position == lengthMinusEnd)
{
if (this.ReadByte() != 0)
{
throw JsonReaderException.Create(this, "Unexpected end of object byte value.");
}
this.PopContext();
if (this._currentContext != null)
{
this.MovePosition(context.Length);
}
JsonToken endToken = (context.Type == BsonType.Object) ? JsonToken.EndObject : JsonToken.EndArray;
this.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()
{
this._stack.RemoveAt(this._stack.Count - 1);
if (this._stack.Count == 0)
{
this._currentContext = null;
}
else
{
this._currentContext = this._stack[this._stack.Count - 1];
}
}
private void PushContext(ContainerContext newContext)
{
this._stack.Add(newContext);
this._currentContext = newContext;
}
private byte ReadByte()
{
this.MovePosition(1);
return this._reader.ReadByte();
}
private void ReadType(BsonType type)
{
switch (type)
{
case BsonType.Number:
double d = this.ReadDouble();
if (this._floatParseHandling == FloatParseHandling.Decimal)
{
this.SetToken(JsonToken.Float, Convert.ToDecimal(d, CultureInfo.InvariantCulture));
}
else
{
this.SetToken(JsonToken.Float, d);
}
break;
case BsonType.String:
case BsonType.Symbol:
this.SetToken(JsonToken.String, this.ReadLengthString());
break;
case BsonType.Object:
{
this.SetToken(JsonToken.StartObject);
ContainerContext newContext = new ContainerContext(BsonType.Object);
this.PushContext(newContext);
newContext.Length = this.ReadInt32();
break;
}
case BsonType.Array:
{
this.SetToken(JsonToken.StartArray);
ContainerContext newContext = new ContainerContext(BsonType.Array);
this.PushContext(newContext);
newContext.Length = this.ReadInt32();
break;
}
case BsonType.Binary:
BsonBinaryType binaryType;
byte[] data = this.ReadBinary(out binaryType);
object value = (binaryType != BsonBinaryType.Uuid)
? data
: new Guid(data);
this.SetToken(JsonToken.Bytes, value);
break;
case BsonType.Undefined:
this.SetToken(JsonToken.Undefined);
break;
case BsonType.Oid:
byte[] oid = this.ReadBytes(12);
this.SetToken(JsonToken.Bytes, oid);
break;
case BsonType.Boolean:
bool b = Convert.ToBoolean(this.ReadByte());
this.SetToken(JsonToken.Boolean, b);
break;
case BsonType.Date:
long ticks = this.ReadInt64();
DateTime utcDateTime = DateTimeUtils.ConvertJavaScriptTicksToDateTime(ticks);
DateTime dateTime;
switch (this.DateTimeKindHandling)
{
case DateTimeKind.Unspecified:
dateTime = DateTime.SpecifyKind(utcDateTime, DateTimeKind.Unspecified);
break;
case DateTimeKind.Local:
dateTime = utcDateTime.ToLocalTime();
break;
default:
dateTime = utcDateTime;
break;
}
this.SetToken(JsonToken.Date, dateTime);
break;
case BsonType.Null:
this.SetToken(JsonToken.Null);
break;
case BsonType.Regex:
string expression = this.ReadString();
string modifiers = this.ReadString();
string regex = @"/" + expression + @"/" + modifiers;
this.SetToken(JsonToken.String, regex);
break;
case BsonType.Reference:
this.SetToken(JsonToken.StartObject);
this._bsonReaderState = BsonReaderState.ReferenceStart;
break;
case BsonType.Code:
this.SetToken(JsonToken.String, this.ReadLengthString());
break;
case BsonType.CodeWScope:
this.SetToken(JsonToken.StartObject);
this._bsonReaderState = BsonReaderState.CodeWScopeStart;
break;
case BsonType.Integer:
this.SetToken(JsonToken.Integer, (long)this.ReadInt32());
break;
case BsonType.TimeStamp:
case BsonType.Long:
this.SetToken(JsonToken.Integer, this.ReadInt64());
break;
default:
throw new ArgumentOutOfRangeException(nameof(type), "Unexpected BsonType value: " + type);
}
}
private byte[] ReadBinary(out BsonBinaryType binaryType)
{
int dataLength = this.ReadInt32();
binaryType = (BsonBinaryType)this.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 && !this._jsonNet35BinaryCompatibility)
{
dataLength = this.ReadInt32();
}
#pragma warning restore 612,618
return this.ReadBytes(dataLength);
}
private string ReadString()
{
this.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 = this._reader.ReadByte()) > 0)
{
this._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(this._byteBuffer, 0, byteCount, this._charBuffer, 0);
this.MovePosition(totalBytesRead + 1);
return new string(this._charBuffer, 0, length);
}
else
{
// calculate the index of the end of the last full character in the buffer
int lastFullCharStop = this.GetLastFullCharStop(count - 1);
int charCount = Encoding.UTF8.GetChars(this._byteBuffer, 0, lastFullCharStop + 1, this._charBuffer, 0);
if (builder == null)
{
builder = new StringBuilder(MaxCharBytesSize * 2);
}
builder.Append(this._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(this._byteBuffer, lastFullCharStop + 1, this._byteBuffer, 0, offset);
}
else
{
// reached end of string
if (count < MaxCharBytesSize)
{
this.MovePosition(totalBytesRead + 1);
return builder.ToString();
}
offset = 0;
}
}
}
}
private string ReadLengthString()
{
int length = this.ReadInt32();
this.MovePosition(length);
string s = this.GetString(length - 1);
this._reader.ReadByte();
return s;
}
private string GetString(int length)
{
if (length == 0)
{
return string.Empty;
}
this.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 = this._reader.Read(this._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(this._byteBuffer, 0, byteCount, this._charBuffer, 0);
return new string(this._charBuffer, 0, charCount);
}
else
{
int lastFullCharStop = this.GetLastFullCharStop(byteCount - 1);
if (builder == null)
{
builder = new StringBuilder(length);
}
int charCount = Encoding.UTF8.GetChars(this._byteBuffer, 0, lastFullCharStop + 1, this._charBuffer, 0);
builder.Append(this._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(this._byteBuffer, lastFullCharStop + 1, this._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 = this.BytesInSequence(this._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 (this._byteBuffer == null)
{
this._byteBuffer = new byte[MaxCharBytesSize];
}
if (this._charBuffer == null)
{
int charBufferSize = Encoding.UTF8.GetMaxCharCount(MaxCharBytesSize);
this._charBuffer = new char[charBufferSize];
}
}
private double ReadDouble()
{
this.MovePosition(8);
return this._reader.ReadDouble();
}
private int ReadInt32()
{
this.MovePosition(4);
return this._reader.ReadInt32();
}
private long ReadInt64()
{
this.MovePosition(8);
return this._reader.ReadInt64();
}
private BsonType ReadType()
{
this.MovePosition(1);
return (BsonType)this._reader.ReadSByte();
}
private void MovePosition(int count)
{
this._currentContext.Position += count;
}
private byte[] ReadBytes(int count)
{
this.MovePosition(count);
return this._reader.ReadBytes(count);
}
}
}

View File

@@ -0,0 +1,181 @@
//------------------------------------------------------------------------------
// 此代码版权除特别声明或在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
// API首页https://www.yuque.com/eo2w71/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)
{
this._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 this._children.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return this.GetEnumerator();
}
}
internal class BsonArray : BsonToken, IEnumerable<BsonToken>
{
private readonly List<BsonToken> _children = new List<BsonToken>();
public void Add(BsonToken token)
{
this._children.Add(token);
token.Parent = this;
}
public override BsonType Type => BsonType.Array;
public IEnumerator<BsonToken> GetEnumerator()
{
return this._children.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return this.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)
{
this.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)
{
this._value = value;
this._type = type;
}
public object Value => this._value;
public override BsonType Type => this._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)
{
this.IncludeLength = includeLength;
}
}
internal class BsonBinary : BsonValue
{
public BsonBinaryType BinaryType { get; set; }
public BsonBinary(byte[] value, BsonBinaryType binaryType)
: base(value, BsonType.Binary)
{
this.BinaryType = binaryType;
}
}
internal class BsonRegex : BsonToken
{
public BsonString Pattern { get; set; }
public BsonString Options { get; set; }
public BsonRegex(string pattern, string options)
{
this.Pattern = new BsonString(pattern, false);
this.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,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
// API首页https://www.yuque.com/eo2w71/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,553 @@
//------------------------------------------------------------------------------
// 此代码版权除特别声明或在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
// API首页https://www.yuque.com/eo2w71/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 => this._writer.DateTimeKindHandling;
set => this._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));
this._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));
this._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()
{
this._writer.Flush();
}
/// <summary>
/// Writes the end.
/// </summary>
/// <param name="token">The token.</param>
protected override void WriteEnd(JsonToken token)
{
base.WriteEnd(token);
this.RemoveParent();
if (this.Top == 0)
{
this._writer.WriteToken(this._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();
this.AddParent(new BsonArray());
}
/// <summary>
/// Writes the beginning of a JSON object.
/// </summary>
public override void WriteStartObject()
{
base.WriteStartObject();
this.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);
this._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 (this.CloseOutput)
{
this._writer?.Close();
}
}
private void AddParent(BsonToken container)
{
this.AddToken(container);
this._parent = container;
}
private void RemoveParent()
{
this._parent = this._parent.Parent;
}
private void AddValue(object value, BsonType type)
{
this.AddToken(new BsonValue(value, type));
}
internal void AddToken(BsonToken token)
{
if (this._parent != null)
{
BsonObject bo = this._parent as BsonObject;
if (bo != null)
{
bo.Add(this._propertyName, token);
this._propertyName = null;
}
else
{
((BsonArray)this._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);
}
this._parent = token;
this._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();
this.AddToken(BsonEmpty.Null);
}
/// <summary>
/// Writes an undefined value.
/// </summary>
public override void WriteUndefined()
{
base.WriteUndefined();
this.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);
this.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);
this.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);
this.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);
this.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);
this.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);
this.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);
this.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);
this.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);
this.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);
this.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
this.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);
this.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);
this.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);
this.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, this.DateTimeZoneHandling);
this.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)
{
this.WriteNull();
return;
}
base.WriteValue(value);
this.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);
this.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);
this.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)
{
this.WriteNull();
return;
}
base.WriteValue(value);
this.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
this.SetWriteState(JsonToken.Undefined, null);
this.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
this.SetWriteState(JsonToken.Undefined, null);
this.AddToken(new BsonRegex(pattern, options));
}
}
}

View File

@@ -0,0 +1,58 @@
//------------------------------------------------------------------------------
// 此代码版权除特别声明或在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
// API首页https://www.yuque.com/eo2w71/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,226 @@
//------------------------------------------------------------------------------
// 此代码版权除特别声明或在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
// API首页https://www.yuque.com/eo2w71/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,106 @@
//------------------------------------------------------------------------------
// 此代码版权除特别声明或在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
// API首页https://www.yuque.com/eo2w71/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,114 @@
//------------------------------------------------------------------------------
// 此代码版权除特别声明或在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
// API首页https://www.yuque.com/eo2w71/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 = this.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,140 @@
//------------------------------------------------------------------------------
// 此代码版权除特别声明或在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
// API首页https://www.yuque.com/eo2w71/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,271 @@
//------------------------------------------------------------------------------
// 此代码版权除特别声明或在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
// API首页https://www.yuque.com/eo2w71/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,73 @@
//------------------------------------------------------------------------------
// 此代码版权除特别声明或在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
// API首页https://www.yuque.com/eo2w71/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,297 @@
//------------------------------------------------------------------------------
// 此代码版权除特别声明或在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
// API首页https://www.yuque.com/eo2w71/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,171 @@
//------------------------------------------------------------------------------
// 此代码版权除特别声明或在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
// API首页https://www.yuque.com/eo2w71/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,189 @@
//------------------------------------------------------------------------------
// 此代码版权除特别声明或在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
// API首页https://www.yuque.com/eo2w71/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,209 @@
//------------------------------------------------------------------------------
// 此代码版权除特别声明或在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
// API首页https://www.yuque.com/eo2w71/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 => this._dateTimeStyles;
set => this._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 => this._dateTimeFormat ?? string.Empty;
set => this._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 => this._culture ?? CultureInfo.CurrentCulture;
set => this._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 ((this._dateTimeStyles & DateTimeStyles.AdjustToUniversal) == DateTimeStyles.AdjustToUniversal
|| (this._dateTimeStyles & DateTimeStyles.AssumeUniversal) == DateTimeStyles.AssumeUniversal)
{
dateTime = dateTime.ToUniversalTime();
}
text = dateTime.ToString(this._dateTimeFormat ?? DefaultDateTimeFormat, this.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(this._dateTimeFormat))
{
return DateTime.ParseExact(dateText, this._dateTimeFormat, this.Culture, this._dateTimeStyles);
}
else
{
return DateTime.Parse(dateText, this.Culture, this._dateTimeStyles);
}
}
}
}

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
// API首页https://www.yuque.com/eo2w71/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,167 @@
//------------------------------------------------------------------------------
// 此代码版权除特别声明或在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
// API首页https://www.yuque.com/eo2w71/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,255 @@
//------------------------------------------------------------------------------
// 此代码版权除特别声明或在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
// API首页https://www.yuque.com/eo2w71/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)
{
this.WriteBson(bsonWriter, regex);
}
#pragma warning restore 618
else
{
this.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 (this.HasFlag(regex.Options, RegexOptions.IgnoreCase))
{
options += "i";
}
if (this.HasFlag(regex.Options, RegexOptions.Multiline))
{
options += "m";
}
if (this.HasFlag(regex.Options, RegexOptions.Singleline))
{
options += "s";
}
options += "u";
if (this.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 this.ReadRegexObject(reader, serializer);
case JsonToken.String:
return this.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) && this.IsRegex(objectType);
}
[MethodImpl(MethodImplOptions.NoInlining)]
private bool IsRegex(Type objectType)
{
return (objectType == typeof(Regex));
}
}
}

View File

@@ -0,0 +1,194 @@
//------------------------------------------------------------------------------
// 此代码版权除特别声明或在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
// API首页https://www.yuque.com/eo2w71/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()
{
this.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()
{
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, this.CamelCaseText, out string enumName))
{
if (!this.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, !this.AllowIntegerValues);
}
if (reader.TokenType == JsonToken.Integer)
{
if (!this.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,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
// API首页https://www.yuque.com/eo2w71/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,121 @@
//------------------------------------------------------------------------------
// 此代码版权除特别声明或在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
// API首页https://www.yuque.com/eo2w71/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,58 @@
//------------------------------------------------------------------------------
// 此代码版权除特别声明或在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
// API首页https://www.yuque.com/eo2w71/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,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
// API首页https://www.yuque.com/eo2w71/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
}
}

View File

@@ -0,0 +1,71 @@
//------------------------------------------------------------------------------
// 此代码版权除特别声明或在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
// API首页https://www.yuque.com/eo2w71/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
{
/// <summary>
/// Specifies how to treat the time value when converting between string and <see cref="DateTime"/>.
/// </summary>
public enum DateTimeZoneHandling
{
/// <summary>
/// Treat as local time. If the <see cref="DateTime"/> object represents a Coordinated Universal Time (UTC), it is converted to the local time.
/// </summary>
Local = 0,
/// <summary>
/// Treat as a UTC. If the <see cref="DateTime"/> object represents a local time, it is converted to a UTC.
/// </summary>
Utc = 1,
/// <summary>
/// Treat as a local time if a <see cref="DateTime"/> is being converted to a string.
/// If a string is being converted to <see cref="DateTime"/>, convert to a local time if a time zone is specified.
/// </summary>
Unspecified = 2,
/// <summary>
/// Time zone information should be preserved when converting.
/// </summary>
RoundtripKind = 3
}
}

View File

@@ -0,0 +1,82 @@
//------------------------------------------------------------------------------
// 此代码版权除特别声明或在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
// API首页https://www.yuque.com/eo2w71/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.ComponentModel;
namespace RRQMCore.XREF.Newtonsoft.Json
{
/// <summary>
/// Specifies default value handling options for the <see cref="JsonSerializer"/>.
/// </summary>
/// <example>
/// <code lang="cs" source="..\Src\RRQMCore.XREF.Newtonsoft.Json.Tests\Documentation\SerializationTests.cs" region="ReducingSerializedJsonSizeDefaultValueHandlingObject" title="DefaultValueHandling Class" />
/// <code lang="cs" source="..\Src\RRQMCore.XREF.Newtonsoft.Json.Tests\Documentation\SerializationTests.cs" region="ReducingSerializedJsonSizeDefaultValueHandlingExample" title="DefaultValueHandling Ignore Example" />
/// </example>
[Flags]
public enum DefaultValueHandling
{
/// <summary>
/// Include members where the member value is the same as the member's default value when serializing objects.
/// Included members are written to JSON. Has no effect when deserializing.
/// </summary>
Include = 0,
/// <summary>
/// Ignore members where the member value is the same as the member's default value when serializing objects
/// so that it is not written to JSON.
/// This option will ignore all default values (e.g. <c>null</c> for objects and nullable types; <c>0</c> for integers,
/// decimals and floating point numbers; and <c>false</c> for booleans). The default value ignored can be changed by
/// placing the <see cref="DefaultValueAttribute"/> on the property.
/// </summary>
Ignore = 1,
/// <summary>
/// Members with a default value but no JSON will be set to their default value when deserializing.
/// </summary>
Populate = 2,
/// <summary>
/// Ignore members where the member value is the same as the member's default value when serializing objects
/// and set members to their default value when deserializing.
/// </summary>
IgnoreAndPopulate = Ignore | Populate
}
}

View File

@@ -0,0 +1,67 @@
//------------------------------------------------------------------------------
// 此代码版权除特别声明或在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
// API首页https://www.yuque.com/eo2w71/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
{
/// <summary>
/// Specifies float format handling options when writing special floating point numbers, e.g. <see cref="Double.NaN"/>,
/// <see cref="Double.PositiveInfinity"/> and <see cref="Double.NegativeInfinity"/> with <see cref="JsonWriter"/>.
/// </summary>
public enum FloatFormatHandling
{
/// <summary>
/// Write special floating point values as strings in JSON, e.g. <c>"NaN"</c>, <c>"Infinity"</c>, <c>"-Infinity"</c>.
/// </summary>
String = 0,
/// <summary>
/// Write special floating point values as symbols in JSON, e.g. <c>NaN</c>, <c>Infinity</c>, <c>-Infinity</c>.
/// Note that this will produce non-valid JSON.
/// </summary>
Symbol = 1,
/// <summary>
/// Write special floating point values as the property's default value in JSON, e.g. 0.0 for a <see cref="Double"/> property, <c>null</c> for a <see cref="Nullable{T}"/> of <see cref="Double"/> property.
/// </summary>
DefaultValue = 2
}
}

View File

@@ -0,0 +1,58 @@
//------------------------------------------------------------------------------
// 此代码版权除特别声明或在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
// API首页https://www.yuque.com/eo2w71/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 floating point numbers, e.g. 1.0 and 9.9, are parsed when reading JSON text.
/// </summary>
public enum FloatParseHandling
{
/// <summary>
/// Floating point numbers are parsed to <see cref="Double"/>.
/// </summary>
Double = 0,
/// <summary>
/// Floating point numbers are parsed to <see cref="Decimal"/>.
/// </summary>
Decimal = 1
}
}

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
// API首页https://www.yuque.com/eo2w71/rrqm
// 交流QQ群234762506
// 感谢您的下载和使用
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
#if HAVE_OBSOLETE_FORMATTER_ASSEMBLY_STYLE
namespace System.Runtime.Serialization.Formatters
{
/// <summary>
/// Indicates the method that will be used during deserialization for locating and loading assemblies.
/// </summary>
[Obsolete("FormatterAssemblyStyle is obsolete. Use TypeNameAssemblyFormatHandling instead.")]
public enum FormatterAssemblyStyle
{
/// <summary>
/// In simple mode, the assembly used during deserialization need not match exactly the assembly used during serialization. Specifically, the version numbers need not match as the <see cref="M:System.Reflection.Assembly.LoadWithPartialName(String)"/> method is used to load the assembly.
/// </summary>
Simple = 0,
/// <summary>
/// In full mode, the assembly used during deserialization must match exactly the assembly used during serialization. The <see cref="System.Reflection.Assembly.Load"/> is used to load the assembly.
/// </summary>
Full = 1
}
}
#endif

View File

@@ -0,0 +1,58 @@
//------------------------------------------------------------------------------
// 此代码版权除特别声明或在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
// API首页https://www.yuque.com/eo2w71/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 formatting options for the <see cref="JsonTextWriter"/>.
/// </summary>
public enum Formatting
{
/// <summary>
/// No special formatting is applied. This is the default.
/// </summary>
None = 0,
/// <summary>
/// Causes child objects to be indented according to the <see cref="JsonTextWriter.Indentation"/> and <see cref="JsonTextWriter.IndentChar"/> settings.
/// </summary>
Indented = 1
}
}

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
// API首页https://www.yuque.com/eo2w71/rrqm
// 交流QQ群234762506
// 感谢您的下载和使用
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
namespace RRQMCore.XREF.Newtonsoft.Json
{
/// <summary>
/// Provides an interface for using pooled arrays.
/// </summary>
/// <typeparam name="T">The array type content.</typeparam>
public interface IArrayPool<T>
{
/// <summary>
/// Rent an array from the pool. This array must be returned when it is no longer needed.
/// </summary>
/// <param name="minimumLength">The minimum required length of the array. The returned array may be longer.</param>
/// <returns>The rented array from the pool. This array must be returned when it is no longer needed.</returns>
T[] Rent(int minimumLength);
/// <summary>
/// Return an array to the pool.
/// </summary>
/// <param name="array">The array that is being returned.</param>
void Return(T[] array);
}
}

Some files were not shown because too many files have changed in this diff Show More