mirror of
https://github.com/nsnail/ns-ext.git
synced 2025-04-20 00:42:51 +08:00
Compare commits
18 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
05ca80acda | ||
![]() |
cc761e4939 | ||
![]() |
d23092e8fc | ||
![]() |
13f8ae51c2 | ||
![]() |
52b3170e10 | ||
![]() |
f3d0f98970 | ||
![]() |
485e7a0ead | ||
![]() |
943d151048 | ||
![]() |
09352ac5ea | ||
![]() |
8c1083f732 | ||
![]() |
31e31c5d49 | ||
![]() |
3095dc783e | ||
![]() |
9ae1046dca | ||
![]() |
cb63791dbc | ||
![]() |
3a1a71d1c1 | ||
![]() |
54082a82f1 | ||
![]() |
1ea481e749 | ||
![]() |
d9aae8fe95 |
65
.editorconfig
Normal file
65
.editorconfig
Normal file
@ -0,0 +1,65 @@
|
||||
root = true
|
||||
|
||||
[*]
|
||||
charset = utf-8
|
||||
end_of_line = lf
|
||||
ij_xml_attribute_wrap = off
|
||||
ij_xml_text_wrap = off
|
||||
indent_size = 4
|
||||
indent_style = space
|
||||
insert_final_newline = false
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
[*.cs]
|
||||
dotnet_analyzer_diagnostic.severity = warning
|
||||
dotnet_diagnostic.CA1707.severity = none
|
||||
dotnet_diagnostic.CA1720.severity = none
|
||||
dotnet_diagnostic.CA5350.severity = none
|
||||
dotnet_diagnostic.CA5351.severity = none
|
||||
dotnet_diagnostic.IDE0008.severity = none
|
||||
dotnet_diagnostic.IDE0017.severity = none
|
||||
dotnet_diagnostic.IDE0048.severity = none
|
||||
dotnet_diagnostic.IDE0055.severity = none
|
||||
dotnet_diagnostic.IDE0058.severity = none
|
||||
dotnet_diagnostic.IDE0160.severity = none
|
||||
|
||||
|
||||
# ReSharper properties
|
||||
resharper_align_linq_query = true
|
||||
resharper_align_multiline_argument = true
|
||||
resharper_align_multiline_array_and_object_initializer = true
|
||||
resharper_align_multiline_binary_patterns = true
|
||||
resharper_align_multiline_calls_chain = true
|
||||
resharper_align_multiline_extends_list = true
|
||||
resharper_align_multiline_parameter = true
|
||||
resharper_align_multiline_property_pattern = true
|
||||
resharper_align_multiline_switch_expression = true
|
||||
resharper_align_multiple_declaration = true
|
||||
resharper_align_multline_type_parameter_constrains = true
|
||||
resharper_align_multline_type_parameter_list = true
|
||||
resharper_align_tuple_components = true
|
||||
resharper_allow_comment_after_lbrace = true
|
||||
resharper_blank_lines_before_single_line_comment = 1
|
||||
resharper_csharp_empty_block_style = together_same_line
|
||||
resharper_csharp_outdent_commas = true
|
||||
resharper_csharp_place_type_constraints_on_same_line = false
|
||||
resharper_csharp_stick_comment = false
|
||||
resharper_csharp_wrap_before_comma = true
|
||||
resharper_indent_nested_for_stmt = true
|
||||
resharper_indent_nested_foreach_stmt = true
|
||||
resharper_indent_nested_while_stmt = true
|
||||
resharper_indent_preprocessor_if = usual_indent
|
||||
resharper_indent_preprocessor_other = usual_indent
|
||||
resharper_int_align = true
|
||||
resharper_keep_existing_arrangement = false
|
||||
resharper_place_linq_into_on_new_line = false
|
||||
resharper_place_simple_embedded_statement_on_same_line = false
|
||||
resharper_place_simple_switch_expression_on_single_line = true
|
||||
resharper_wrap_before_eq = true
|
||||
resharper_wrap_chained_method_calls = chop_if_long
|
||||
resharper_wrap_switch_expression = chop_if_long
|
||||
|
||||
|
||||
# Microsoft .NET properties
|
||||
csharp_indent_braces = false
|
||||
csharp_new_line_before_open_brace = local_functions, methods, types
|
415
.gitignore
vendored
415
.gitignore
vendored
@ -1,23 +1,404 @@
|
||||
pkg
|
||||
build
|
||||
bin
|
||||
obj
|
||||
packages
|
||||
Migrations
|
||||
_gsdata_
|
||||
_ReSharper*
|
||||
TestResults
|
||||
app_data
|
||||
## 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/main/VisualStudio.gitignore
|
||||
|
||||
# User-specific files
|
||||
*.rsuser
|
||||
*.suo
|
||||
*.user
|
||||
*.userosscache
|
||||
*.sln.docstates
|
||||
|
||||
# User-specific files (MonoDevelop/Xamarin Studio)
|
||||
*.userprefs
|
||||
|
||||
# Mono auto generated files
|
||||
mono_crash.*
|
||||
|
||||
# Build results
|
||||
[Dd]ebug/
|
||||
[Dd]ebugPublic/
|
||||
[Rr]elease/
|
||||
[Rr]eleases/
|
||||
x64/
|
||||
x86/
|
||||
[Ww][Ii][Nn]32/
|
||||
[Aa][Rr][Mm]/
|
||||
[Aa][Rr][Mm]64/
|
||||
bld/
|
||||
[Bb]in/
|
||||
[Oo]bj/
|
||||
[Ll]og/
|
||||
[Ll]ogs/
|
||||
|
||||
# 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
|
||||
nunit-*.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/
|
||||
|
||||
# ASP.NET Scaffolding
|
||||
ScaffoldingReadMe.txt
|
||||
|
||||
# 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
|
||||
*.tlog
|
||||
*.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
|
||||
|
||||
# TeamCity is a build add-in
|
||||
_TeamCity*
|
||||
|
||||
# DotCover is a Code Coverage Tool
|
||||
*.dotCover
|
||||
|
||||
# AxoCover is a Code Coverage Tool
|
||||
.axoCover/*
|
||||
!.axoCover/settings.json
|
||||
|
||||
# Coverlet is a free, cross platform Code Coverage Tool
|
||||
coverage*.json
|
||||
coverage*.xml
|
||||
coverage*.info
|
||||
|
||||
# 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
|
||||
*.publish.xml
|
||||
.svn
|
||||
.vs
|
||||
*.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
|
||||
# NuGet Symbol Packages
|
||||
*.snupkg
|
||||
# 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
|
||||
*.appxbundle
|
||||
*.appxupload
|
||||
|
||||
# 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
|
||||
*.exe
|
||||
.idea
|
||||
node_modules
|
||||
dist
|
||||
*.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/
|
||||
|
||||
# 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
|
||||
*- [Bb]ackup.rdl
|
||||
*- [Bb]ackup ([0-9]).rdl
|
||||
*- [Bb]ackup ([0-9][0-9]).rdl
|
||||
|
||||
# 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 6 auto-generated project file (contains which files were open etc.)
|
||||
*.vbp
|
||||
|
||||
# Visual Studio 6 workspace and project file (working project files containing files to include in project)
|
||||
*.dsw
|
||||
*.dsp
|
||||
|
||||
# Visual Studio 6 technical files
|
||||
*.ncb
|
||||
*.aps
|
||||
|
||||
# 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/
|
||||
|
||||
# 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/
|
||||
|
||||
# Visual Studio History (VSHistory) files
|
||||
.vshistory/
|
||||
|
||||
# BeatPulse healthcheck temp database
|
||||
healthchecksdb
|
||||
|
||||
# Backup folder for Package Reference Convert tool in Visual Studio 2017
|
||||
MigrationBackup/
|
||||
|
||||
# Ionide (cross platform F# VS Code tools) working folder
|
||||
.ionide/
|
||||
|
||||
# Fody - auto-generated XML schema
|
||||
FodyWeavers.xsd
|
||||
|
||||
# VS Code files for those working on multiple tools
|
||||
.vscode/*
|
||||
!.vscode/settings.json
|
||||
!.vscode/tasks.json
|
||||
!.vscode/launch.json
|
||||
!.vscode/extensions.json
|
||||
*.code-workspace
|
||||
|
||||
# Local History for Visual Studio Code
|
||||
.history/
|
||||
|
||||
# Windows Installer files from build outputs
|
||||
*.cab
|
||||
*.msi
|
||||
*.msix
|
||||
*.msm
|
||||
*.msp
|
||||
|
||||
# JetBrains Rider
|
||||
*.sln.iml
|
||||
.idea/
|
||||
|
||||
# User Define
|
||||
build/
|
||||
nuget.config
|
||||
*.[Dd]esigner.cs
|
14
AddMetaFilesToSln.csx
Normal file
14
AddMetaFilesToSln.csx
Normal file
@ -0,0 +1,14 @@
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
var slnFile = Directory.GetFiles(@".", "*.sln").First();
|
||||
var content = File.ReadAllText(slnFile);
|
||||
content = Regex.Replace(content,@"ProjectSection\(SolutionItems\) = preProject(?:.|\n)*?EndProjectSection",
|
||||
$"""
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
{string.Join('\n',
|
||||
Directory.GetFiles(@".", "*").Where(x => !x.EndsWith(".sln"))
|
||||
.Select(x=>$"\t\t{Path.GetFileName(x)} = {Path.GetFileName(x)}"))}
|
||||
{'\t'}EndProjectSection
|
||||
""");
|
||||
Console.WriteLine(content);
|
||||
File.WriteAllText(slnFile, content);
|
16
CodeCleanupOnSave.csx
Normal file
16
CodeCleanupOnSave.csx
Normal file
@ -0,0 +1,16 @@
|
||||
var path = Directory.GetFiles(@".idea", "workspace.xml", SearchOption.AllDirectories).First();
|
||||
const string findStr = """
|
||||
"keyToString": {
|
||||
""";
|
||||
const string replaceStr = """
|
||||
"keyToString": {
|
||||
"rider.code.cleanup.on.save": "true",
|
||||
""";
|
||||
var content = File.ReadAllText(path);
|
||||
if(content.Contains("rider.code.cleanup.on.save")){
|
||||
Console.WriteLine("alreay added");
|
||||
return;
|
||||
}
|
||||
content = content.Replace(findStr, replaceStr);
|
||||
Console.WriteLine(content);
|
||||
File.WriteAllText(path, content);
|
17
CodeQuality.props
Normal file
17
CodeQuality.props
Normal file
@ -0,0 +1,17 @@
|
||||
<Project>
|
||||
<PropertyGroup>
|
||||
<CodeAnalysisRuleSet>../StyleCopAnalyzers.ruleset</CodeAnalysisRuleSet>
|
||||
<CodeAnalysisTreatWarningsAsErrors>true</CodeAnalysisTreatWarningsAsErrors>
|
||||
<EnforceCodeStyleInBuild>true</EnforceCodeStyleInBuild>
|
||||
<MSBuildTreatWarningsAsErrors>true</MSBuildTreatWarningsAsErrors>
|
||||
<MSBuildWarningsAsErrors>true</MSBuildWarningsAsErrors>
|
||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||
<WarningsAsErrors>true</WarningsAsErrors>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.435">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
</Project>
|
@ -1,7 +1,22 @@
|
||||
<Project>
|
||||
<PropertyGroup>
|
||||
<BaseOutputPath>../build/temp/bin</BaseOutputPath>
|
||||
<BaseIntermediateOutputPath>../build/temp/obj</BaseIntermediateOutputPath>
|
||||
<MSBuildProjectExtensionsPath>../build/temp/obj</MSBuildProjectExtensionsPath>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<BaseOutputPath>../dist</BaseOutputPath>
|
||||
<BaseIntermediateOutputPath>../dist</BaseIntermediateOutputPath>
|
||||
<OutputPath>$(BaseOutputPath)/$(MSBuildProjectName)/bin</OutputPath>
|
||||
<IntermediateOutputPath>$(BaseIntermediateOutputPath)/$(MSBuildProjectName)/obj</IntermediateOutputPath>
|
||||
<MSBuildProjectExtensionsPath>$(BaseIntermediateOutputPath)/$(MSBuildProjectName)/obj</MSBuildProjectExtensionsPath>
|
||||
<Authors>nsnail</Authors>
|
||||
<Product>NSExt</Product>
|
||||
<Copyright>© 2006-2022 nsnail</Copyright>
|
||||
<RepositoryUrl>https://github.com/nsnail/ns-ext.git</RepositoryUrl>
|
||||
<PublishRepositoryUrl>true</PublishRepositoryUrl>
|
||||
<EmbedUntrackedSource>true</EmbedUntrackedSource>
|
||||
<EmbedAllSources>true</EmbedAllSources>
|
||||
<RepositoryType>Git</RepositoryType>
|
||||
<IncludeSymbols>true</IncludeSymbols>
|
||||
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
|
||||
<PackageLicenseExpression>MIT</PackageLicenseExpression>
|
||||
<PackageProjectUrl>https://github.com/nsnail/ns-ext.git</PackageProjectUrl>
|
||||
</PropertyGroup>
|
||||
</Project>
|
45
ImageOptimize.csx
Normal file
45
ImageOptimize.csx
Normal file
@ -0,0 +1,45 @@
|
||||
/*
|
||||
for %%i in (*.png) do pngquant %%i --force --output %%i --skip-if-larger
|
||||
for %%i in (*.jpg) do jpegtran -copy none -optimize -perfect %%i %%i
|
||||
*
|
||||
*/
|
||||
|
||||
var files = Directory.EnumerateFiles(".", "*.png"
|
||||
, new EnumerationOptions {
|
||||
RecurseSubdirectories = true
|
||||
, AttributesToSkip = FileAttributes.ReparsePoint
|
||||
, IgnoreInaccessible = true
|
||||
})
|
||||
.ToArray();
|
||||
|
||||
|
||||
Parallel.ForEach(files, file => {
|
||||
var startInfo = new ProcessStartInfo {
|
||||
FileName = "pngquant"
|
||||
, Arguments
|
||||
= $"\"{file}\" --force --output \"{file}\" --skip-if-larger"
|
||||
};
|
||||
using var p = Process.Start(startInfo);
|
||||
p.WaitForExit();
|
||||
Console.WriteLine($"{file}: {p.ExitCode}");
|
||||
});
|
||||
|
||||
files = new[] { "*.jpg", "*.jpeg" }
|
||||
.SelectMany(x => Directory.EnumerateFiles(
|
||||
".", x
|
||||
, new EnumerationOptions {
|
||||
RecurseSubdirectories = true
|
||||
, AttributesToSkip = FileAttributes.ReparsePoint
|
||||
, IgnoreInaccessible = true
|
||||
}))
|
||||
.ToArray();
|
||||
|
||||
Parallel.ForEach(files, file => {
|
||||
var startInfo = new ProcessStartInfo {
|
||||
FileName = "jpegtran"
|
||||
, Arguments = $"-copy none -optimize -perfect \"{file}\" \"{file}\""
|
||||
};
|
||||
using var p = Process.Start(startInfo);
|
||||
p.WaitForExit();
|
||||
Console.WriteLine($"{file}: {p.ExitCode}");
|
||||
});
|
21
LICENSE
Normal file
21
LICENSE
Normal file
@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2022 nsnail
|
||||
|
||||
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.
|
46
NSExt.sln
Normal file
46
NSExt.sln
Normal file
@ -0,0 +1,46 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 17
|
||||
VisualStudioVersion = 17.0.31903.59
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NSExt", "src\NSExt.csproj", "{70DD1C27-7ACB-4BE0-A9CD-D781E4050DE5}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "meta", "meta", "{85E669CB-FC0A-4C1D-92DE-38D0662C257D}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
.editorconfig = .editorconfig
|
||||
.gitattributes = .gitattributes
|
||||
.gitignore = .gitignore
|
||||
.tgitconfig = .tgitconfig
|
||||
AddMetaFilesToSln.csx = AddMetaFilesToSln.csx
|
||||
build.cake = build.cake
|
||||
code-format.cmd = code-format.cmd
|
||||
CodeCleanupOnSave.csx = CodeCleanupOnSave.csx
|
||||
CodeQuality.props = CodeQuality.props
|
||||
Directory.Build.props = Directory.Build.props
|
||||
dot.sln.DotSettings = dot.sln.DotSettings
|
||||
dotnet-tools.json = dotnet-tools.json
|
||||
git-clean.cmd = git-clean.cmd
|
||||
global.json = global.json
|
||||
ImageOptimize.csx = ImageOptimize.csx
|
||||
LICENSE = LICENSE
|
||||
push2nuget.ps1 = push2nuget.ps1
|
||||
README.md = README.md
|
||||
stylecop.json = stylecop.json
|
||||
StyleCopAnalyzers.ruleset = StyleCopAnalyzers.ruleset
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{70DD1C27-7ACB-4BE0-A9CD-D781E4050DE5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{70DD1C27-7ACB-4BE0-A9CD-D781E4050DE5}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{70DD1C27-7ACB-4BE0-A9CD-D781E4050DE5}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{70DD1C27-7ACB-4BE0-A9CD-D781E4050DE5}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
EndGlobal
|
@ -1,4 +1,18 @@
|
||||
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
|
||||
<wpf:ResourceDictionary xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xml:space="preserve">
|
||||
<s:Boolean x:Key="/Default/ReSpeller/ReSpellerEnabled/@EntryValue">False</s:Boolean>
|
||||
<s:Int64 x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/KEEP_BLANK_LINES_IN_CODE/@EntryValue">1</s:Int64>
|
||||
<s:Int64 x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/KEEP_BLANK_LINES_IN_DECLARATIONS/@EntryValue">1</s:Int64>
|
||||
<s:String x:Key="/Default/CodeInspection/Highlighting/AnalysisEnabled/@EntryValue">OFF</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=TooWideLocalVariableScope/@EntryIndexedValue">HINT</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/BRACES_FOR_FOR/@EntryValue">Required</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/BRACES_FOR_FOREACH/@EntryValue">Required</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/BRACES_FOR_IFELSE/@EntryValue">Required</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/BRACES_FOR_WHILE/@EntryValue">Required</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=Constants/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="AA_BB" /></s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateConstants/@EntryIndexedValue"><Policy Inspect="True" Prefix="_" Suffix="" Style="AA_BB" /></s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateStaticReadonly/@EntryIndexedValue"><Policy Inspect="True" Prefix="_" Suffix="" Style="aaBb" /></s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=StaticReadonly/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /></s:String>
|
||||
|
||||
<s:String x:Key="/Default/CodeStyle/CSharpFileLayoutPatterns/Pattern/@EntryValue"><?xml version="1.0" encoding="utf-16"?>
|
||||
<Patterns xmlns="urn:schemas-jetbrains-com:member-reordering-patterns">
|
||||
<TypePattern>
|
||||
@ -6,40 +20,38 @@
|
||||
<Entry.SortBy>
|
||||
<Kind>
|
||||
<Kind.Order>
|
||||
<DeclarationKind>Interface</DeclarationKind>
|
||||
<DeclarationKind>Class</DeclarationKind>
|
||||
<DeclarationKind>Enum</DeclarationKind>
|
||||
<DeclarationKind>Struct</DeclarationKind>
|
||||
<DeclarationKind>Delegate</DeclarationKind>
|
||||
<DeclarationKind>Event</DeclarationKind>
|
||||
<DeclarationKind>Constant</DeclarationKind>
|
||||
<DeclarationKind>Field</DeclarationKind>
|
||||
<DeclarationKind>Property</DeclarationKind>
|
||||
<DeclarationKind>Constructor</DeclarationKind>
|
||||
<DeclarationKind>Destructor</DeclarationKind>
|
||||
<DeclarationKind>Delegate</DeclarationKind>
|
||||
<DeclarationKind>Event</DeclarationKind>
|
||||
<DeclarationKind>Enum</DeclarationKind>
|
||||
<DeclarationKind>Interface</DeclarationKind>
|
||||
<DeclarationKind>Property</DeclarationKind>
|
||||
<DeclarationKind>Indexer</DeclarationKind>
|
||||
<DeclarationKind>Method</DeclarationKind>
|
||||
<DeclarationKind>Struct</DeclarationKind>
|
||||
<DeclarationKind>Record</DeclarationKind>
|
||||
<DeclarationKind>Class</DeclarationKind>
|
||||
</Kind.Order>
|
||||
</Kind>
|
||||
<Access>
|
||||
<Access.Order>
|
||||
<AccessModifier>Private</AccessModifier>
|
||||
<AccessModifier>PrivateProtected</AccessModifier>
|
||||
<AccessModifier>Protected</AccessModifier>
|
||||
<AccessModifier>ProtectedInternal</AccessModifier>
|
||||
<AccessModifier>Internal</AccessModifier>
|
||||
<AccessModifier>Public</AccessModifier>
|
||||
<AccessModifier>Internal</AccessModifier>
|
||||
<AccessModifier>ProtectedInternal</AccessModifier>
|
||||
<AccessModifier>Protected</AccessModifier>
|
||||
<AccessModifier>PrivateProtected</AccessModifier>
|
||||
<AccessModifier>Private</AccessModifier>
|
||||
</Access.Order>
|
||||
</Access>
|
||||
<Static />
|
||||
<Readonly />
|
||||
<Name />
|
||||
</Entry.SortBy>
|
||||
</Entry>
|
||||
</TypePattern>
|
||||
</Patterns></s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=Constants/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="AA_BB" /></s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateConstants/@EntryIndexedValue"><Policy Inspect="True" Prefix="_" Suffix="" Style="AA_BB" /></s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateStaticReadonly/@EntryIndexedValue"><Policy Inspect="True" Prefix="_" Suffix="" Style="aaBb" /></s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=StaticReadonly/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /></s:String>
|
||||
<s:Boolean x:Key="/Default/ReSpeller/ReSpellerEnabled/@EntryValue">False</s:Boolean>
|
||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=TooWideLocalVariableScope/@EntryIndexedValue">HINT</s:String>
|
||||
|
||||
</wpf:ResourceDictionary>
|
64
README.md
64
README.md
@ -1 +1,65 @@
|
||||
# ns-ext
|
||||
|
||||
[中](README.zh-CN.md) | **En**
|
||||
The **ns-ext** is a .NET extension function library, containing the following types of extension modules:
|
||||
|
||||
| Features | File name |
|
||||
|------------------------------------------|------------------------------------|
|
||||
| Byte type extension | ByteExtensions.cs |
|
||||
| Character Type Extensions | CharExtensions.cs |
|
||||
| Date Type Extensions | DateTimeExtensions.cs |
|
||||
| Database command type extension | DbCommandExtensions.cs |
|
||||
| Decimal Number Type extension | DecimalExtensions.cs |
|
||||
| Enumable type extension | EnumerableExtensions.cs |
|
||||
| Enumeration type extension | EnumExtensions.cs |
|
||||
| General type extension | GenericExtensions.cs |
|
||||
| Integer type extension | IntExtensions.cs |
|
||||
| Json Serialization option type extension | JsonSerializerOptionsExtensions.cs |
|
||||
| Log type extension | LoggerExtensions.cs |
|
||||
| Long integer extension | LongExtensions.cs |
|
||||
| Object type extension | ObjectExtensions.cs |
|
||||
| Stream type extension | StreamExtensions.cs |
|
||||
| String type extension | StringExtensions.cs |
|
||||
| Prototype type extension | TypeExtensions.cs |
|
||||
| Resource locator type extension | UriExtensions.cs |
|
||||
|
||||
## Quick start
|
||||
|
||||
### Install
|
||||
|
||||
```shell
|
||||
dotnet add package NSExt --prerelease
|
||||
```
|
||||
|
||||
### Example
|
||||
|
||||
```c#
|
||||
using NSExt.Extensions;
|
||||
|
||||
internal static class Program
|
||||
{
|
||||
private class Person
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public int Age { get; set; }
|
||||
}
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
var person =
|
||||
"""
|
||||
{
|
||||
"Name": "Jason",
|
||||
"Age": "30"
|
||||
}
|
||||
""".Object<Person>();
|
||||
|
||||
Console.WriteLine(person.Json());
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Output
|
||||
|
||||
```json
|
||||
{"name":"Jason","age":30}
|
||||
```
|
65
README.zh-CN.md
Normal file
65
README.zh-CN.md
Normal file
@ -0,0 +1,65 @@
|
||||
# ns-ext
|
||||
[En](README.md) | **中**
|
||||
**ns-ext** 是一个.NET扩展函数库,包含以下类型扩展模块:
|
||||
|
||||
|
||||
| 功能 | 文件名 |
|
||||
| -------- | ---------------------------------- |
|
||||
| 字节类型扩展 | ByteExtensions.cs |
|
||||
| 字符类型扩展 | CharExtensions.cs |
|
||||
| 日期类型扩展 | DateTimeExtensions.cs |
|
||||
| 数据库命令类型扩展 | DbCommandExtensions.cs |
|
||||
| 十进制数类型扩展 | DecimalExtensions.cs |
|
||||
| 可枚举类型扩展 | EnumerableExtensions.cs |
|
||||
| 枚举类型扩展 | EnumExtensions.cs |
|
||||
| 泛型类型扩展 | GenericExtensions.cs |
|
||||
| 整数型扩展 | IntExtensions.cs |
|
||||
| Json序列化选项类型扩展 | JsonSerializerOptionsExtensions.cs |
|
||||
| 日志类型扩展 | LoggerExtensions.cs |
|
||||
| 长整型扩展 | LongExtensions.cs |
|
||||
| 对象类型扩展 | ObjectExtensions.cs |
|
||||
| 流类型扩展 | StreamExtensions.cs |
|
||||
| 字符串类型扩展 | StringExtensions.cs |
|
||||
| 原型类型扩展 | TypeExtensions.cs |
|
||||
| 资源定位符类型扩展 | UriExtensions.cs |
|
||||
|
||||
## 快速开始
|
||||
|
||||
### 安装
|
||||
|
||||
```shell
|
||||
dotnet add package NSExt --prerelease
|
||||
```
|
||||
|
||||
### 示例
|
||||
|
||||
```c#
|
||||
using NSExt.Extensions;
|
||||
|
||||
internal static class Program
|
||||
{
|
||||
private class Person
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public int Age { get; set; }
|
||||
}
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
var person =
|
||||
"""
|
||||
{
|
||||
"Name": "Jason",
|
||||
"Age": "30"
|
||||
}
|
||||
""".Object<Person>();
|
||||
|
||||
Console.WriteLine(person.Json());
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 输出
|
||||
|
||||
```json
|
||||
{"name":"Jason","age":30}
|
||||
```
|
221
StyleCopAnalyzers.ruleset
Normal file
221
StyleCopAnalyzers.ruleset
Normal file
@ -0,0 +1,221 @@
|
||||
<?xml version="1.0"?>
|
||||
<RuleSet Name="StyleCop.Analyzers rules with default action"
|
||||
Description="StyleCop.Analyzers with default action. Rules with IsEnabledByDefault = false are disabled."
|
||||
ToolsVersion="14.0">
|
||||
<Rules AnalyzerId="StyleCop.Analyzers" RuleNamespace="StyleCop.Analyzers.SpecialRules">
|
||||
<Rule Id="SA0001" Action="Warning"/> <!-- XML comment analysis disabled -->
|
||||
<Rule Id="SA0002" Action="Warning"/> <!-- Invalid settings file -->
|
||||
</Rules>
|
||||
|
||||
<Rules AnalyzerId="StyleCop.Analyzers" RuleNamespace="StyleCop.Analyzers.SpacingRules">
|
||||
<Rule Id="SA1000" Action="Warning"/> <!-- Keywords should be spaced correctly -->
|
||||
<Rule Id="SA1001" Action="None"/> <!-- Commas should be spaced correctly -->
|
||||
<Rule Id="SA1002" Action="Warning"/> <!-- Semicolons should be spaced correctly -->
|
||||
<Rule Id="SA1003" Action="Warning"/> <!-- Symbols should be spaced correctly -->
|
||||
<Rule Id="SA1004" Action="Warning"/> <!-- Documentation lines should begin with single space -->
|
||||
<Rule Id="SA1005" Action="None"/> <!-- Single line comments should begin with single space -->
|
||||
<Rule Id="SA1006" Action="Warning"/> <!-- Preprocessor keywords should not be preceded by space -->
|
||||
<Rule Id="SA1007" Action="Warning"/> <!-- Operator keyword should be followed by space -->
|
||||
<Rule Id="SA1008" Action="None"/> <!-- Opening parenthesis should be spaced correctly -->
|
||||
<Rule Id="SA1009" Action="Warning"/> <!-- Closing parenthesis should be spaced correctly -->
|
||||
<Rule Id="SA1010" Action="Warning"/> <!-- Opening square brackets should be spaced correctly -->
|
||||
<Rule Id="SA1011" Action="Warning"/> <!-- Closing square brackets should be spaced correctly -->
|
||||
<Rule Id="SA1012" Action="Warning"/> <!-- Opening braces should be spaced correctly -->
|
||||
<Rule Id="SA1013" Action="Warning"/> <!-- Closing braces should be spaced correctly -->
|
||||
<Rule Id="SA1014" Action="Warning"/> <!-- Opening generic brackets should be spaced correctly -->
|
||||
<Rule Id="SA1015" Action="Warning"/> <!-- Closing generic brackets should be spaced correctly -->
|
||||
<Rule Id="SA1016" Action="Warning"/> <!-- Opening attribute brackets should be spaced correctly -->
|
||||
<Rule Id="SA1017" Action="Warning"/> <!-- Closing attribute brackets should be spaced correctly -->
|
||||
<Rule Id="SA1018" Action="Warning"/> <!-- Nullable type symbols should be spaced correctly -->
|
||||
<Rule Id="SA1019" Action="Warning"/> <!-- Member access symbols should be spaced correctly -->
|
||||
<Rule Id="SA1020" Action="Warning"/> <!-- Increment decrement symbols should be spaced correctly -->
|
||||
<Rule Id="SA1021" Action="Warning"/> <!-- Negative signs should be spaced correctly -->
|
||||
<Rule Id="SA1022" Action="Warning"/> <!-- Positive signs should be spaced correctly -->
|
||||
<Rule Id="SA1023" Action="Warning"/> <!-- Dereference and access of symbols should be spaced correctly -->
|
||||
<Rule Id="SA1024" Action="Warning"/> <!-- Colons should be spaced correctly -->
|
||||
<Rule Id="SA1025" Action="None"/> <!-- Code should not contain multiple whitespace in a row -->
|
||||
<Rule Id="SA1026" Action="Warning"/> <!-- Code should not contain space after new or stackalloc keyword in implicitly typed array allocation -->
|
||||
<Rule Id="SA1027" Action="Warning"/> <!-- Use tabs correctly -->
|
||||
<Rule Id="SA1028" Action="Warning"/> <!-- Code should not contain trailing whitespace -->
|
||||
</Rules>
|
||||
|
||||
<Rules AnalyzerId="StyleCop.Analyzers" RuleNamespace="StyleCop.Analyzers.ReadabilityRules">
|
||||
<Rule Id="SA1100" Action="Warning"/> <!-- Do not prefix calls with base unless local implementation exists -->
|
||||
<Rule Id="SA1101" Action="None"/> <!-- Prefix local calls with this -->
|
||||
<Rule Id="SA1102" Action="Warning"/> <!-- Query clause should follow previous clause -->
|
||||
<Rule Id="SA1103" Action="Warning"/> <!-- Query clauses should be on separate lines or all on one line -->
|
||||
<Rule Id="SA1104" Action="Warning"/> <!-- Query clause should begin on new line when previous clause spans multiple lines -->
|
||||
<Rule Id="SA1105" Action="Warning"/> <!-- Query clauses spanning multiple lines should begin on own line -->
|
||||
<Rule Id="SA1106" Action="Warning"/> <!-- Code should not contain empty statements -->
|
||||
<Rule Id="SA1107" Action="Warning"/> <!-- Code should not contain multiple statements on one line -->
|
||||
<Rule Id="SA1108" Action="Warning"/> <!-- Block statements should not contain embedded comments -->
|
||||
<Rule Id="SA1109" Action="Warning"/> <!-- Block statements should not contain embedded regions -->
|
||||
<Rule Id="SA1110" Action="Warning"/> <!-- Opening parenthesis or bracket should be on declaration line -->
|
||||
<Rule Id="SA1111" Action="Warning"/> <!-- Closing parenthesis should be on line of last parameter -->
|
||||
<Rule Id="SA1112" Action="Warning"/> <!-- Closing parenthesis should be on line of opening parenthesis -->
|
||||
<Rule Id="SA1113" Action="None"/> <!-- Comma should be on the same line as previous parameter -->
|
||||
<Rule Id="SA1114" Action="Warning"/> <!-- Parameter list should follow declaration -->
|
||||
<Rule Id="SA1115" Action="Warning"/> <!-- Parameter should follow comma -->
|
||||
<Rule Id="SA1116" Action="Warning"/> <!-- Split parameters should start on line after declaration -->
|
||||
<Rule Id="SA1117" Action="None"/> <!-- Parameters should be on same line or separate lines -->
|
||||
<Rule Id="SA1118" Action="Warning"/> <!-- Parameter should not span multiple lines -->
|
||||
<Rule Id="SA1120" Action="None"/> <!-- Comments should contain text -->
|
||||
<Rule Id="SA1121" Action="Warning"/> <!-- Use built-in type alias -->
|
||||
<Rule Id="SA1122" Action="Warning"/> <!-- Use string.Empty for empty strings -->
|
||||
<Rule Id="SA1123" Action="Warning"/> <!-- Do not place regions within elements -->
|
||||
<Rule Id="SA1124" Action="Warning"/> <!-- Do not use regions -->
|
||||
<Rule Id="SA1125" Action="Warning"/> <!-- Use shorthand for nullable types -->
|
||||
<Rule Id="SA1126" Action="Warning"/> <!-- Prefix calls correctly -->
|
||||
<Rule Id="SA1127" Action="Warning"/> <!-- Generic type constraints should be on their own line -->
|
||||
<Rule Id="SA1128" Action="Warning"/> <!-- Put constructor initializers on their own line -->
|
||||
<Rule Id="SA1129" Action="Warning"/> <!-- Do not use default value type constructor -->
|
||||
<Rule Id="SA1130" Action="Warning"/> <!-- Use lambda syntax -->
|
||||
<Rule Id="SA1131" Action="Warning"/> <!-- Use readable conditions -->
|
||||
<Rule Id="SA1132" Action="Warning"/> <!-- Do not combine fields -->
|
||||
<Rule Id="SA1133" Action="Warning"/> <!-- Do not combine attributes -->
|
||||
<Rule Id="SA1134" Action="None"/> <!-- Attributes should not share line -->
|
||||
<Rule Id="SA1135" Action="Warning"/> <!-- Using directives should be qualified -->
|
||||
<Rule Id="SA1136" Action="Warning"/> <!-- Enum values should be on separate lines -->
|
||||
<Rule Id="SA1137" Action="Warning"/> <!-- Elements should have the same indentation -->
|
||||
<Rule Id="SA1139" Action="Warning"/> <!-- Use literal suffix notation instead of casting -->
|
||||
<Rule Id="SX1101" Action="Warning"/> <!-- Do not prefix local calls with 'this.' -->
|
||||
</Rules>
|
||||
|
||||
<Rules AnalyzerId="StyleCop.Analyzers" RuleNamespace="StyleCop.Analyzers.OrderingRules">
|
||||
<Rule Id="SA1200" Action="None"/> <!-- Using directives should be placed correctly -->
|
||||
<Rule Id="SA1201" Action="Warning"/> <!-- Elements should appear in the correct order -->
|
||||
<Rule Id="SA1202" Action="Warning"/> <!-- Elements should be ordered by access -->
|
||||
<Rule Id="SA1203" Action="Warning"/> <!-- Constants should appear before fields -->
|
||||
<Rule Id="SA1204" Action="Warning"/> <!-- Static elements should appear before instance elements -->
|
||||
<Rule Id="SA1205" Action="Warning"/> <!-- Partial elements should declare access -->
|
||||
<Rule Id="SA1206" Action="Warning"/> <!-- Declaration keywords should follow order -->
|
||||
<Rule Id="SA1207" Action="Warning"/> <!-- Protected should come before internal -->
|
||||
<Rule Id="SA1208" Action="Warning"/> <!-- System using directives should be placed before other using directives -->
|
||||
<Rule Id="SA1209" Action="Warning"/> <!-- Using alias directives should be placed after other using directives -->
|
||||
<Rule Id="SA1210" Action="Warning"/> <!-- Using directives should be ordered alphabetically by namespace -->
|
||||
<Rule Id="SA1211" Action="Warning"/> <!-- Using alias directives should be ordered alphabetically by alias name -->
|
||||
<Rule Id="SA1212" Action="Warning"/> <!-- Property accessors should follow order -->
|
||||
<Rule Id="SA1213" Action="Warning"/> <!-- Event accessors should follow order -->
|
||||
<Rule Id="SA1214" Action="Warning"/> <!-- Readonly fields should appear before non-readonly fields -->
|
||||
<Rule Id="SA1216" Action="Warning"/> <!-- Using static directives should be placed at the correct location -->
|
||||
<Rule Id="SA1217" Action="Warning"/> <!-- Using static directives should be ordered alphabetically -->
|
||||
</Rules>
|
||||
|
||||
<Rules AnalyzerId="StyleCop.Analyzers" RuleNamespace="StyleCop.Analyzers.NamingRules">
|
||||
<Rule Id="SA1300" Action="Warning"/> <!-- Element should begin with upper-case letter -->
|
||||
<Rule Id="SA1301" Action="Warning"/> <!-- Element should begin with lower-case letter -->
|
||||
<Rule Id="SA1302" Action="Warning"/> <!-- Interface names should begin with I -->
|
||||
<Rule Id="SA1303" Action="Warning"/> <!-- Const field names should begin with upper-case letter -->
|
||||
<Rule Id="SA1304" Action="Warning"/> <!-- Non-private readonly fields should begin with upper-case letter -->
|
||||
<Rule Id="SA1305" Action="None"/> <!-- Field names should not use Hungarian notation -->
|
||||
<Rule Id="SA1306" Action="Warning"/> <!-- Field names should begin with lower-case letter -->
|
||||
<Rule Id="SA1307" Action="Warning"/> <!-- Accessible fields should begin with upper-case letter -->
|
||||
<Rule Id="SA1308" Action="Warning"/> <!-- Variable names should not be prefixed -->
|
||||
<Rule Id="SA1309" Action="None"/> <!-- Field names should not begin with underscore -->
|
||||
<Rule Id="SA1310" Action="None"/> <!-- Field names should not contain underscore -->
|
||||
<Rule Id="SA1311" Action="Warning"/> <!-- Static readonly fields should begin with upper-case letter -->
|
||||
<Rule Id="SA1312" Action="Warning"/> <!-- Variable names should begin with lower-case letter -->
|
||||
<Rule Id="SA1313" Action="None"/> <!-- Parameter names should begin with lower-case letter -->
|
||||
<Rule Id="SA1314" Action="Warning"/> <!-- Type parameter names should begin with T -->
|
||||
<Rule Id="SX1309" Action="Warning"/> <!-- Field names should begin with underscore -->
|
||||
<Rule Id="SX1309S" Action="Warning"/> <!-- Static field names should begin with underscore -->
|
||||
</Rules>
|
||||
|
||||
<Rules AnalyzerId="StyleCop.Analyzers" RuleNamespace="StyleCop.Analyzers.MaintainabilityRules">
|
||||
<Rule Id="SA1119" Action="Warning"/> <!-- Statement should not use unnecessary parenthesis -->
|
||||
<Rule Id="SA1400" Action="Warning"/> <!-- Access modifier should be declared -->
|
||||
<Rule Id="SA1401" Action="Warning"/> <!-- Fields should be private -->
|
||||
<Rule Id="SA1402" Action="Warning"/> <!-- File may only contain a single type -->
|
||||
<Rule Id="SA1403" Action="Warning"/> <!-- File may only contain a single namespace -->
|
||||
<Rule Id="SA1404" Action="Warning"/> <!-- Code analysis suppression should have justification -->
|
||||
<Rule Id="SA1405" Action="Warning"/> <!-- Debug.Assert should provide message text -->
|
||||
<Rule Id="SA1406" Action="Warning"/> <!-- Debug.Fail should provide message text -->
|
||||
<Rule Id="SA1407" Action="None"/> <!-- Arithmetic expressions should declare precedence -->
|
||||
<Rule Id="SA1408" Action="Warning"/> <!-- Conditional expressions should declare precedence -->
|
||||
<Rule Id="SA1409" Action="Warning"/> <!-- Remove unnecessary code -->
|
||||
<Rule Id="SA1410" Action="Warning"/> <!-- Remove delegate parenthesis when possible -->
|
||||
<Rule Id="SA1411" Action="Warning"/> <!-- Attribute constructor should not use unnecessary parenthesis -->
|
||||
<Rule Id="SA1412" Action="None"/> <!-- Store files as UTF-8 with byte order mark -->
|
||||
<Rule Id="SA1413" Action="None"/> <!-- Use trailing comma in multi-line initializers -->
|
||||
</Rules>
|
||||
|
||||
<Rules AnalyzerId="StyleCop.Analyzers" RuleNamespace="StyleCop.Analyzers.LayoutRules">
|
||||
<Rule Id="SA1500" Action="None"/> <!-- Braces for multi-line statements should not share line -->
|
||||
<Rule Id="SA1501" Action="Warning"/> <!-- Statement should not be on a single line -->
|
||||
<Rule Id="SA1502" Action="None"/> <!-- Element should not be on a single line -->
|
||||
<Rule Id="SA1503" Action="None"/> <!-- Braces should not be omitted -->
|
||||
<Rule Id="SA1504" Action="Warning"/> <!-- All accessors should be single-line or multi-line -->
|
||||
<Rule Id="SA1505" Action="Warning"/> <!-- Opening braces should not be followed by blank line -->
|
||||
<Rule Id="SA1506" Action="Warning"/> <!-- Element documentation headers should not be followed by blank line -->
|
||||
<Rule Id="SA1507" Action="Warning"/> <!-- Code should not contain multiple blank lines in a row -->
|
||||
<Rule Id="SA1508" Action="Warning"/> <!-- Closing braces should not be preceded by blank line -->
|
||||
<Rule Id="SA1509" Action="Warning"/> <!-- Opening braces should not be preceded by blank line -->
|
||||
<Rule Id="SA1510" Action="Warning"/> <!-- Chained statement blocks should not be preceded by blank line -->
|
||||
<Rule Id="SA1511" Action="Warning"/> <!-- While-do footer should not be preceded by blank line -->
|
||||
<Rule Id="SA1512" Action="Warning"/> <!-- Single-line comments should not be followed by blank line -->
|
||||
<Rule Id="SA1513" Action="Warning"/> <!-- Closing brace should be followed by blank line -->
|
||||
<Rule Id="SA1514" Action="Warning"/> <!-- Element documentation header should be preceded by blank line -->
|
||||
<Rule Id="SA1515" Action="Warning"/> <!-- Single-line comment should be preceded by blank line -->
|
||||
<Rule Id="SA1516" Action="Warning"/> <!-- Elements should be separated by blank line -->
|
||||
<Rule Id="SA1517" Action="Warning"/> <!-- Code should not contain blank lines at start of file -->
|
||||
<Rule Id="SA1518" Action="Warning"/> <!-- Use line endings correctly at end of file -->
|
||||
<Rule Id="SA1519" Action="Warning"/> <!-- Braces should not be omitted from multi-line child statement -->
|
||||
<Rule Id="SA1520" Action="Warning"/> <!-- Use braces consistently -->
|
||||
</Rules>
|
||||
|
||||
<Rules AnalyzerId="StyleCop.Analyzers" RuleNamespace="StyleCop.Analyzers.DocumentationRules">
|
||||
<Rule Id="SA1600" Action="None"/> <!-- Elements should be documented -->
|
||||
<Rule Id="SA1601" Action="None"/> <!-- Partial elements should be documented -->
|
||||
<Rule Id="SA1602" Action="None"/> <!-- Enumeration items should be documented -->
|
||||
<Rule Id="SA1603" Action="Warning"/> <!-- Documentation should contain valid XML -->
|
||||
<Rule Id="SA1604" Action="Warning"/> <!-- Element documentation should have summary -->
|
||||
<Rule Id="SA1605" Action="Warning"/> <!-- Partial element documentation should have summary -->
|
||||
<Rule Id="SA1606" Action="Warning"/> <!-- Element documentation should have summary text -->
|
||||
<Rule Id="SA1607" Action="Warning"/> <!-- Partial element documentation should have summary text -->
|
||||
<Rule Id="SA1608" Action="Warning"/> <!-- Element documentation should not have default summary -->
|
||||
<Rule Id="SA1609" Action="Warning"/> <!-- Property documentation should have value -->
|
||||
<Rule Id="SA1610" Action="Warning"/> <!-- Property documentation should have value text -->
|
||||
<Rule Id="SA1611" Action="None"/> <!-- Element parameters should be documented -->
|
||||
<Rule Id="SA1612" Action="Warning"/> <!-- Element parameter documentation should match element parameters -->
|
||||
<Rule Id="SA1613" Action="Warning"/> <!-- Element parameter documentation should declare parameter name -->
|
||||
<Rule Id="SA1614" Action="Warning"/> <!-- Element parameter documentation should have text -->
|
||||
<Rule Id="SA1615" Action="None"/> <!-- Element return value should be documented -->
|
||||
<Rule Id="SA1616" Action="Warning"/> <!-- Element return value documentation should have text -->
|
||||
<Rule Id="SA1617" Action="Warning"/> <!-- Void return value should not be documented -->
|
||||
<Rule Id="SA1618" Action="None"/> <!-- Generic type parameters should be documented -->
|
||||
<Rule Id="SA1619" Action="None"/> <!-- Generic type parameters should be documented partial class -->
|
||||
<Rule Id="SA1620" Action="Warning"/> <!-- Generic type parameter documentation should match type parameters -->
|
||||
<Rule Id="SA1621" Action="Warning"/> <!-- Generic type parameter documentation should declare parameter name -->
|
||||
<Rule Id="SA1622" Action="Warning"/> <!-- Generic type parameter documentation should have text -->
|
||||
<Rule Id="SA1623" Action="Warning"/> <!-- Property summary documentation should match accessors -->
|
||||
<Rule Id="SA1624" Action="Warning"/> <!-- Property summary documentation should omit accessor with restricted access -->
|
||||
<Rule Id="SA1625" Action="Warning"/> <!-- Element documentation should not be copied and pasted -->
|
||||
<Rule Id="SA1626" Action="Warning"/> <!-- Single-line comments should not use documentation style slashes -->
|
||||
<Rule Id="SA1627" Action="Warning"/> <!-- Documentation text should not be empty -->
|
||||
<Rule Id="SA1628" Action="Warning"/> <!-- Documentation text should begin with a capital letter -->
|
||||
<Rule Id="SA1629" Action="None"/> <!-- Documentation text should end with a period -->
|
||||
<Rule Id="SA1630" Action="Warning"/> <!-- Documentation text should contain whitespace -->
|
||||
<Rule Id="SA1631" Action="Warning"/> <!-- Documentation should meet character percentage -->
|
||||
<Rule Id="SA1632" Action="Warning"/> <!-- Documentation text should meet minimum character length -->
|
||||
<Rule Id="SA1633" Action="None"/> <!-- File should have header -->
|
||||
<Rule Id="SA1634" Action="Warning"/> <!-- File header should show copyright -->
|
||||
<Rule Id="SA1635" Action="Warning"/> <!-- File header should have copyright text -->
|
||||
<Rule Id="SA1636" Action="Warning"/> <!-- File header copyright text should match -->
|
||||
<Rule Id="SA1637" Action="Warning"/> <!-- File header should contain file name -->
|
||||
<Rule Id="SA1638" Action="Warning"/> <!-- File header file name documentation should match file name -->
|
||||
<Rule Id="SA1639" Action="Warning"/> <!-- File header should have summary -->
|
||||
<Rule Id="SA1640" Action="Warning"/> <!-- File header should have valid company text -->
|
||||
<Rule Id="SA1641" Action="Warning"/> <!-- File header company name text should match -->
|
||||
<Rule Id="SA1642" Action="Warning"/> <!-- Constructor summary documentation should begin with standard text -->
|
||||
<Rule Id="SA1643" Action="Warning"/> <!-- Destructor summary documentation should begin with standard text -->
|
||||
<Rule Id="SA1644" Action="Warning"/> <!-- Documentation headers should not contain blank lines -->
|
||||
<Rule Id="SA1645" Action="Warning"/> <!-- Included documentation file does not exist -->
|
||||
<Rule Id="SA1646" Action="Warning"/> <!-- Included documentation XPath does not exist -->
|
||||
<Rule Id="SA1647" Action="Warning"/> <!-- Include node does not contain valid file and path -->
|
||||
<Rule Id="SA1648" Action="Warning"/> <!-- Inheritdoc should be used with inheriting class -->
|
||||
<Rule Id="SA1649" Action="Warning"/> <!-- File name should match first type name -->
|
||||
<Rule Id="SA1650" Action="Warning"/> <!-- Element documentation should be spelled correctly -->
|
||||
<Rule Id="SA1651" Action="Warning"/> <!-- Do not use placeholder elements -->
|
||||
|
||||
</Rules>
|
||||
</RuleSet>
|
132
build.cake
Normal file
132
build.cake
Normal file
@ -0,0 +1,132 @@
|
||||
var target = Argument("target", "Default");
|
||||
var configuration = Argument("configuration", "Release");
|
||||
var pkgOutPath = $"./dist/NSExt/pkg/{configuration}";
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
// Tasks
|
||||
|
||||
Task("Clean")
|
||||
.Does(context =>
|
||||
{
|
||||
context.CleanDirectory(pkgOutPath);
|
||||
});
|
||||
|
||||
Task("Build")
|
||||
.IsDependentOn("Clean")
|
||||
.Does(context =>
|
||||
{
|
||||
DotNetBuild("./NSExt.sln", new DotNetBuildSettings {
|
||||
Configuration = configuration,
|
||||
NoIncremental = context.HasArgument("rebuild"),
|
||||
MSBuildSettings = new DotNetMSBuildSettings()
|
||||
.TreatAllWarningsAs(MSBuildTreatAllWarningsAs.Error)
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
Task("Test")
|
||||
.IsDependentOn("Build")
|
||||
.Does(context =>
|
||||
{
|
||||
DotNetTest("./test/Spectre.Console.Tests/Spectre.Console.Tests.csproj", new DotNetTestSettings {
|
||||
Configuration = configuration,
|
||||
NoRestore = true,
|
||||
NoBuild = true,
|
||||
});
|
||||
|
||||
DotNetTest("./test/Spectre.Console.Cli.Tests/Spectre.Console.Cli.Tests.csproj", new DotNetTestSettings {
|
||||
Configuration = configuration,
|
||||
NoRestore = true,
|
||||
NoBuild = true,
|
||||
});
|
||||
|
||||
DotNetTest("./test/Spectre.Console.Analyzer.Tests/Spectre.Console.Analyzer.Tests.csproj", new DotNetTestSettings {
|
||||
Configuration = configuration,
|
||||
NoRestore = true,
|
||||
NoBuild = true,
|
||||
});
|
||||
});
|
||||
|
||||
Task("Package")
|
||||
.IsDependentOn("Build")
|
||||
.Does(context =>
|
||||
{
|
||||
context.DotNetPack("./NSExt.sln", new DotNetPackSettings {
|
||||
Configuration = configuration,
|
||||
NoRestore = true,
|
||||
NoBuild = true,
|
||||
OutputDirectory = pkgOutPath,
|
||||
MSBuildSettings = new DotNetMSBuildSettings()
|
||||
.TreatAllWarningsAs(MSBuildTreatAllWarningsAs.Error)
|
||||
});
|
||||
});
|
||||
|
||||
Task("Publish-GitHub")
|
||||
.WithCriteria(ctx => BuildSystem.IsRunningOnGitHubActions, "Not running on GitHub Actions")
|
||||
.IsDependentOn("Package")
|
||||
.Does(context =>
|
||||
{
|
||||
var apiKey = Argument<string>("github-key", null);
|
||||
if(string.IsNullOrWhiteSpace(apiKey)) {
|
||||
throw new CakeException("No GitHub API key was provided.");
|
||||
}
|
||||
|
||||
// Publish to GitHub Packages
|
||||
var exitCode = 0;
|
||||
foreach(var file in context.GetFiles("./.artifacts/*.nupkg"))
|
||||
{
|
||||
context.Information("Publishing {0}...", file.GetFilename().FullPath);
|
||||
exitCode += StartProcess("dotnet",
|
||||
new ProcessSettings {
|
||||
Arguments = new ProcessArgumentBuilder()
|
||||
.Append("gpr")
|
||||
.Append("push")
|
||||
.AppendQuoted(file.FullPath)
|
||||
.AppendSwitchSecret("-k", " ", apiKey)
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
if(exitCode != 0)
|
||||
{
|
||||
throw new CakeException("Could not push GitHub packages.");
|
||||
}
|
||||
});
|
||||
|
||||
Task("Publish-NuGet")
|
||||
// .WithCriteria(ctx => BuildSystem.IsRunningOnGitHubActions, "Not running on GitHub Actions")
|
||||
.IsDependentOn("Package")
|
||||
.Does(context =>
|
||||
{
|
||||
var apiKey = Argument<string>("nuget-key", null);
|
||||
if(string.IsNullOrWhiteSpace(apiKey)) {
|
||||
throw new CakeException("No NuGet API key was provided.");
|
||||
}
|
||||
|
||||
// Publish to GitHub Packages
|
||||
foreach(var file in context.GetFiles($"{pkgOutPath}/*.*nupkg"))
|
||||
{
|
||||
context.Information("Publishing {0}...", file.GetFilename().FullPath);
|
||||
DotNetNuGetPush(file.FullPath, new DotNetNuGetPushSettings
|
||||
{
|
||||
Source = "https://api.nuget.org/v3/index.json",
|
||||
ApiKey = apiKey,
|
||||
SkipDuplicate = true
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
// Targets
|
||||
|
||||
Task("Publish")
|
||||
//.IsDependentOn("Publish-GitHub")
|
||||
.IsDependentOn("Publish-NuGet");
|
||||
|
||||
Task("Default")
|
||||
.IsDependentOn("Package");
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
// Execution
|
||||
|
||||
RunTarget(target)
|
@ -1,3 +1,3 @@
|
||||
do.exe trim-utf8-bom
|
||||
do.exe remove-whitespace
|
||||
do.exe convert-lf
|
||||
dot rbom -w
|
||||
dot trim -w
|
||||
dot tolf -w
|
6
dotnet-tools.json
Normal file
6
dotnet-tools.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"version": 1,
|
||||
"isRoot": true,
|
||||
"tools": {
|
||||
}
|
||||
}
|
10
global.json
Normal file
10
global.json
Normal file
@ -0,0 +1,10 @@
|
||||
{
|
||||
"sdk": {
|
||||
"version": "7.0.100",
|
||||
"allowPrerelease": true,
|
||||
"rollForward": "major"
|
||||
},
|
||||
"tools": {
|
||||
"dotnet": "7.0.100"
|
||||
}
|
||||
}
|
@ -1,25 +0,0 @@
|
||||
Param(
|
||||
# Nuget APIKey
|
||||
[string] $apikey
|
||||
)
|
||||
|
||||
if ($apikey -eq $null -or $apikey -eq "")
|
||||
{
|
||||
Write-Error "require apiKey";
|
||||
return;
|
||||
}
|
||||
|
||||
rm -r ./build/nupkgs
|
||||
dotnet build -c Release ./src/NSExt.sln
|
||||
$files = Get-ChildItem -Path ./build/nupkgs/ -Filter *.nupkg
|
||||
foreach($file in $files)
|
||||
{
|
||||
dotnet nuget push $file.fullName --skip-duplicate --api-key $apikey --source https://api.nuget.org/v3/index.json
|
||||
nuget add $file.fullName -source d:\nuget-pkg
|
||||
}
|
||||
$files = Get-ChildItem -Path ./build/nupkgs/ -Filter *.snupkg
|
||||
foreach($file in $files)
|
||||
{
|
||||
dotnet nuget push $file.fullName --skip-duplicate --api-key $apikey --source https://api.nuget.org/v3/index.json
|
||||
nuget add $file.fullName -source d:\nuget-pkg
|
||||
}
|
@ -1,89 +0,0 @@
|
||||
[*.{appxmanifest,asax,ascx,aspx,axaml,axml,build,config,cs,cshtml,csproj,css,dbml,discomap,dtd,htm,html,js,json,jsproj,jsx,lsproj,master,njsproj,nuspec,paml,proj,props,proto,razor,resjson,resw,resx,skin,StyleCop,targets,tasks,ts,tsx,vb,vbproj,xaml,xamlx,xml,xoml,xsd}]
|
||||
indent_style = space
|
||||
indent_size = space
|
||||
tab_width = 4
|
||||
|
||||
[*]
|
||||
|
||||
# Microsoft .NET properties
|
||||
csharp_indent_braces = false
|
||||
csharp_new_line_before_members_in_object_initializers = true
|
||||
csharp_new_line_before_open_brace = local_functions, methods, types
|
||||
csharp_preferred_modifier_order = public, private, protected, internal, new, abstract, virtual, sealed, override, static, readonly, extern, unsafe, volatile, async:suggestion
|
||||
csharp_style_var_elsewhere = true:suggestion
|
||||
csharp_style_var_for_built_in_types = true:suggestion
|
||||
csharp_style_var_when_type_is_apparent = true:suggestion
|
||||
dotnet_style_parentheses_in_arithmetic_binary_operators = never_if_unnecessary:none
|
||||
dotnet_style_parentheses_in_other_binary_operators = never_if_unnecessary:none
|
||||
dotnet_style_parentheses_in_relational_binary_operators = never_if_unnecessary:none
|
||||
dotnet_style_predefined_type_for_locals_parameters_members = true:suggestion
|
||||
dotnet_style_predefined_type_for_member_access = true:suggestion
|
||||
dotnet_style_qualification_for_event = false:suggestion
|
||||
dotnet_style_qualification_for_field = false:suggestion
|
||||
dotnet_style_qualification_for_method = false:suggestion
|
||||
dotnet_style_qualification_for_property = false:suggestion
|
||||
dotnet_style_require_accessibility_modifiers = for_non_interface_members:suggestion
|
||||
|
||||
# ReSharper inspection severities
|
||||
resharper_arrange_redundant_parentheses_highlighting = hint
|
||||
resharper_arrange_this_qualifier_highlighting = hint
|
||||
resharper_arrange_type_member_modifiers_highlighting = hint
|
||||
resharper_arrange_type_modifiers_highlighting = hint
|
||||
resharper_built_in_type_reference_style_for_member_access_highlighting = hint
|
||||
resharper_built_in_type_reference_style_highlighting = hint
|
||||
resharper_redundant_base_qualifier_highlighting = warning
|
||||
resharper_suggest_var_or_type_built_in_types_highlighting = hint
|
||||
resharper_suggest_var_or_type_elsewhere_highlighting = hint
|
||||
resharper_suggest_var_or_type_simple_types_highlighting = hint
|
||||
|
||||
# ReSharper properties
|
||||
resharper_align_first_arg_by_paren = true
|
||||
resharper_align_linq_query = true
|
||||
resharper_align_multiline_argument = true
|
||||
resharper_align_multiline_array_and_object_initializer = false
|
||||
resharper_align_multiline_calls_chain = true
|
||||
resharper_align_multiline_expression = true
|
||||
resharper_align_multiline_extends_list = true
|
||||
resharper_align_multiline_for_stmt = true
|
||||
resharper_align_multiline_property_pattern = true
|
||||
resharper_align_multiline_switch_expression = true
|
||||
resharper_align_multline_type_parameter_constrains = true
|
||||
resharper_align_multline_type_parameter_list = true
|
||||
resharper_align_tuple_components = true
|
||||
resharper_csharp_align_multiline_parameter = true
|
||||
resharper_csharp_align_multiple_declaration = true
|
||||
resharper_csharp_empty_block_style = together
|
||||
resharper_csharp_indent_size = 4
|
||||
resharper_csharp_indent_style = space
|
||||
resharper_csharp_insert_final_newline = true
|
||||
resharper_csharp_max_line_length = 120
|
||||
resharper_csharp_stick_comment = false
|
||||
resharper_csharp_tab_width = 4
|
||||
resharper_csharp_wrap_arguments_style = chop_if_long
|
||||
resharper_csharp_wrap_before_comma = false
|
||||
resharper_csharp_wrap_chained_method_calls = chop_if_long
|
||||
resharper_csharp_wrap_extends_list_style = chop_if_long
|
||||
resharper_csharp_wrap_parameters_style = chop_if_long
|
||||
resharper_indent_anonymous_method_block = true
|
||||
resharper_indent_nested_fixed_stmt = true
|
||||
resharper_indent_nested_foreach_stmt = true
|
||||
resharper_indent_nested_for_stmt = true
|
||||
resharper_indent_nested_lock_stmt = true
|
||||
resharper_indent_nested_usings_stmt = true
|
||||
resharper_indent_nested_while_stmt = true
|
||||
resharper_indent_preprocessor_if = usual_indent
|
||||
resharper_indent_preprocessor_other = usual_indent
|
||||
resharper_int_align = true
|
||||
resharper_keep_existing_arrangement = false
|
||||
resharper_keep_existing_linebreaks = false
|
||||
resharper_max_initializer_elements_on_line = 1
|
||||
resharper_outdent_commas = true
|
||||
resharper_outdent_dots = true
|
||||
resharper_wrap_array_initializer_style = chop_always
|
||||
resharper_wrap_before_comma = false
|
||||
resharper_wrap_object_and_collection_initializer_style = chop_always
|
||||
|
||||
[*.cs]
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
tab_width = 4
|
24
src/Attributes/LocalizationAttribute.cs
Normal file
24
src/Attributes/LocalizationAttribute.cs
Normal file
@ -0,0 +1,24 @@
|
||||
namespace NSExt.Attributes;
|
||||
|
||||
/// <summary>
|
||||
/// 指定本地化资源类型
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Class | AttributeTargets.Field)]
|
||||
public class LocalizationAttribute : Attribute
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="LocalizationAttribute" /> class.
|
||||
/// </summary>
|
||||
public LocalizationAttribute(Type resourceClass)
|
||||
{
|
||||
ResourceClass = resourceClass;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets 资源类型
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// 资源类型
|
||||
/// </value>
|
||||
public Type ResourceClass { get; set; }
|
||||
}
|
19
src/Constant/Regexes.cs
Normal file
19
src/Constant/Regexes.cs
Normal file
@ -0,0 +1,19 @@
|
||||
namespace NSExt.Constant;
|
||||
#pragma warning disable SYSLIB1045
|
||||
|
||||
// 使用 RegexGenerator 新特性会生成重复key值的xmlcomment导致出错
|
||||
internal static class Regexes
|
||||
{
|
||||
public static readonly Regex RegexBacksLantUnicode
|
||||
= new("\\\\u([a-fA-F0-9]{4})", RegexOptions.Compiled | RegexOptions.IgnoreCase);
|
||||
|
||||
public static readonly Regex RegexHtmlTag = new("<[^>]*>", RegexOptions.Compiled | RegexOptions.IgnoreCase);
|
||||
|
||||
public static readonly Regex RegexMobile
|
||||
= new("^(\\d{3})\\d{4}(\\d{4})$", RegexOptions.Compiled | RegexOptions.IgnoreCase);
|
||||
|
||||
public static readonly Regex RegexPercentUnicode
|
||||
= new("\\\\u([a-fA-F0-9]{4})", RegexOptions.Compiled | RegexOptions.IgnoreCase);
|
||||
|
||||
public static readonly Regex RegexUpLetter = new("([A-Z])", RegexOptions.Compiled | RegexOptions.IgnoreCase);
|
||||
}
|
@ -1,18 +0,0 @@
|
||||
<Project>
|
||||
<PropertyGroup>
|
||||
<Authors>nsnail</Authors>
|
||||
<Product>NSExt</Product>
|
||||
<Copyright>© 2006-2022 nsnail</Copyright>
|
||||
<RepositoryUrl>https://github.com/nsnail/ns-ext.git</RepositoryUrl>
|
||||
<PublishRepositoryUrl>true</PublishRepositoryUrl>
|
||||
<EmbedUntrackedSource>true</EmbedUntrackedSource>
|
||||
<EmbedAllSources>true</EmbedAllSources>
|
||||
<RepositoryType>Git</RepositoryType>
|
||||
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
|
||||
<IncludeSymbols>true</IncludeSymbols>
|
||||
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
|
||||
<PackageLicenseExpression>MIT</PackageLicenseExpression>
|
||||
<PackageProjectUrl>https://github.com/nsnail/ns-ext.git</PackageProjectUrl>
|
||||
<PackageOutputPath>../../build/nupkgs</PackageOutputPath>
|
||||
</PropertyGroup>
|
||||
</Project>
|
@ -1,5 +1,8 @@
|
||||
namespace NSExt.Extensions;
|
||||
|
||||
/// <summary>
|
||||
/// ByteExtensions
|
||||
/// </summary>
|
||||
public static class ByteExtensions
|
||||
{
|
||||
/// <summary>
|
||||
@ -12,7 +15,6 @@ public static class ByteExtensions
|
||||
return Convert.ToBase64String(me);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 将字节数组解码成字符串
|
||||
/// </summary>
|
||||
@ -24,7 +26,6 @@ public static class ByteExtensions
|
||||
return e.GetString(me);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 将字节数组解码成字符串
|
||||
/// </summary>
|
||||
@ -38,15 +39,23 @@ public static class ByteExtensions
|
||||
/// <summary>
|
||||
/// 将字节数组转换成16进制字符串
|
||||
/// </summary>
|
||||
/// <param name="me"></param>
|
||||
/// <param name="me">me</param>
|
||||
/// <param name="upperCase">是否大写</param>
|
||||
/// <param name="splitShar">字节间分隔符</param>
|
||||
/// <returns></returns>
|
||||
public static string String(this byte[] me, bool upperCase = true, string splitShar = null)
|
||||
/// <param name="splitInterval">分隔符跳跃字节数</param>
|
||||
public static string String(this IEnumerable<byte> me, bool upperCase = true, string splitShar = ""
|
||||
, int splitInterval = 1)
|
||||
{
|
||||
var ret = BitConverter.ToString(me);
|
||||
if (!upperCase) ret = ret.ToLower();
|
||||
if (splitShar != "-") ret = ret.Replace("-", splitShar ?? string.Empty);
|
||||
return ret;
|
||||
var sb = new StringBuilder();
|
||||
var i = 0;
|
||||
foreach (var c in me.Select(x => x.ToString(upperCase ? "X2" : "x2", CultureInfo.InvariantCulture))) {
|
||||
if (i++ % splitInterval == 0) {
|
||||
sb.Append(splitShar);
|
||||
}
|
||||
|
||||
sb.Append(c);
|
||||
}
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
}
|
@ -1,12 +1,13 @@
|
||||
namespace NSExt.Extensions;
|
||||
|
||||
/// <summary>
|
||||
/// CharExtensions
|
||||
/// </summary>
|
||||
public static class CharExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// 是否数字或大小写字母
|
||||
/// </summary>
|
||||
/// <param name="me"></param>
|
||||
/// <returns></returns>
|
||||
public static bool IsAsciiLetterOrDigit(this char me)
|
||||
{
|
||||
return (((uint)me - 'A') & ~0x20) < 26 || (uint)me - '0' < 10;
|
||||
@ -15,8 +16,6 @@ public static class CharExtensions
|
||||
/// <summary>
|
||||
/// 是否base64字符
|
||||
/// </summary>
|
||||
/// <param name="me"></param>
|
||||
/// <returns></returns>
|
||||
public static bool IsBase64Character(this char me)
|
||||
{
|
||||
return IsAsciiLetterOrDigit(me) || me is '+' or '/' or '=';
|
@ -1,27 +1,28 @@
|
||||
// ReSharper disable InconsistentNaming
|
||||
// ReSharper disable UnusedMember.Global
|
||||
|
||||
#pragma warning disable SA1300
|
||||
#pragma warning disable IDE1006
|
||||
namespace NSExt.Extensions;
|
||||
|
||||
/// <summary>
|
||||
/// DateTimeExtensions
|
||||
/// </summary>
|
||||
public static class DateTimeExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// 将一个过去时间对象与当前时间相减转换成“xx以前”的字符串,如2秒以前,3天以前
|
||||
/// 将一个过去时间对象与当前时间相减转换成“xx以前”的字符串, 如2秒以前, 3天以前
|
||||
/// </summary>
|
||||
/// <param name="me">时间对象</param>
|
||||
/// <returns>字符串</returns>
|
||||
public static string TimeAgo(this DateTime me)
|
||||
{
|
||||
var ts = DateTime.Now - me;
|
||||
if (ts.Days > 0) return ts.Days + "天前";
|
||||
|
||||
if (ts.Hours > 0) return ts.Hours + "小时前";
|
||||
|
||||
if (ts.Minutes > 0) return ts.Minutes + "分钟前";
|
||||
|
||||
return ts.Seconds + "秒前";
|
||||
return ts.Days > 0 ? ts.Days + "天前" :
|
||||
ts.Hours > 0 ? ts.Hours + "小时前" :
|
||||
ts.Minutes > 0 ? ts.Minutes + "分钟前" : ts.Seconds + "秒前";
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 指定时间的世界协调时的unix时间戳形式
|
||||
/// </summary>
|
||||
@ -35,55 +36,64 @@ public static class DateTimeExtensions
|
||||
/// <summary>
|
||||
/// 指定时间的世界协调时的unix时间戳形式(毫秒)
|
||||
/// </summary>
|
||||
/// <param name="me"></param>
|
||||
/// <returns></returns>
|
||||
public static long TimeUnixUtcMs(this DateTime me)
|
||||
{
|
||||
return (me.ToUniversalTime().Ticks - 621355968000000000) / 10000;
|
||||
}
|
||||
|
||||
|
||||
// ReSharper disable once InconsistentNaming
|
||||
/// <summary>
|
||||
/// yyyy_MM
|
||||
/// </summary>
|
||||
public static string yyyy_MM(this DateTime me)
|
||||
{
|
||||
return me.ToString("yyyy-MM");
|
||||
return me.ToString("yyyy-MM", CultureInfo.InvariantCulture);
|
||||
}
|
||||
|
||||
// ReSharper disable once InconsistentNaming
|
||||
/// <summary>
|
||||
/// yyyy_MM_dd
|
||||
/// </summary>
|
||||
public static string yyyy_MM_dd(this DateTime me)
|
||||
{
|
||||
return me.ToString("yyyy-MM-dd");
|
||||
return me.ToString("yyyy-MM-dd", CultureInfo.InvariantCulture);
|
||||
}
|
||||
|
||||
// ReSharper disable once InconsistentNaming
|
||||
/// <summary>
|
||||
/// yyyy_MM_dd_HH_mm
|
||||
/// </summary>
|
||||
public static string yyyy_MM_dd_HH_mm(this DateTime me)
|
||||
{
|
||||
return me.ToString("yyyy-MM-dd HH:mm");
|
||||
return me.ToString("yyyy-MM-dd HH:mm", CultureInfo.InvariantCulture);
|
||||
}
|
||||
|
||||
|
||||
// ReSharper disable once InconsistentNaming
|
||||
/// <summary>
|
||||
/// yyyy_MM_dd_HH_mm_ss
|
||||
/// </summary>
|
||||
public static string yyyy_MM_dd_HH_mm_ss(this DateTime me)
|
||||
{
|
||||
return me.ToString("yyyy-MM-dd HH:mm:ss");
|
||||
return me.ToString("yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture);
|
||||
}
|
||||
|
||||
// ReSharper disable once InconsistentNaming
|
||||
/// <summary>
|
||||
/// yyyy_MM_dd_HH_mm_ss_fff
|
||||
/// </summary>
|
||||
public static string yyyy_MM_dd_HH_mm_ss_fff(this DateTime me)
|
||||
{
|
||||
return me.ToString("yyyy-MM-dd HH:mm:ss.fff");
|
||||
return me.ToString("yyyy-MM-dd HH:mm:ss.fff", CultureInfo.InvariantCulture);
|
||||
}
|
||||
|
||||
|
||||
// ReSharper disable once InconsistentNaming
|
||||
/// <summary>
|
||||
/// yyyyMM
|
||||
/// </summary>
|
||||
public static string yyyyMM(this DateTime me)
|
||||
{
|
||||
return me.ToString("yyyyMM");
|
||||
return me.ToString("yyyyMM", CultureInfo.InvariantCulture);
|
||||
}
|
||||
|
||||
// ReSharper disable once InconsistentNaming
|
||||
/// <summary>
|
||||
/// yyyyMMdd
|
||||
/// </summary>
|
||||
public static string yyyyMMdd(this DateTime me)
|
||||
{
|
||||
return me.ToString("yyyyMMdd");
|
||||
return me.ToString("yyyyMMdd", CultureInfo.InvariantCulture);
|
||||
}
|
||||
}
|
@ -1,28 +1,34 @@
|
||||
namespace NSExt.Extensions;
|
||||
|
||||
/// <summary>
|
||||
/// DbCommandExtensions
|
||||
/// </summary>
|
||||
public static class DbCommandExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// 格式化参数拼接成完整的SQL语句
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static string ParameterFormat(this DbCommand me)
|
||||
{
|
||||
//var aa = pars.ToDictionary(it => it.ParameterName, it => it.Value);
|
||||
var sql = me.CommandText;
|
||||
|
||||
//应逆向替换,否则由于 多个表的过滤器问题导致替换不完整 如 @TenantId1 @TenantId10
|
||||
for (var i = me.Parameters.Count - 1; i >= 0; i--)
|
||||
for (var i = me.Parameters.Count - 1; i >= 0; i--) {
|
||||
#pragma warning disable IDE0072
|
||||
sql = me.Parameters[i].DbType switch {
|
||||
#pragma warning restore IDE0072
|
||||
DbType.String or DbType.DateTime or DbType.Date or DbType.Time or DbType.DateTime2
|
||||
or DbType.DateTimeOffset or DbType.Guid or DbType.VarNumeric or DbType.AnsiStringFixedLength
|
||||
or DbType.AnsiString
|
||||
or DbType.StringFixedLength => sql.Replace(me.Parameters[i].ParameterName,
|
||||
"'" + me.Parameters[i].Value + "'"),
|
||||
DbType.Boolean => sql.Replace(me.Parameters[i].ParameterName,
|
||||
Convert.ToBoolean(me.Parameters[i].Value) ? "1" : "0"),
|
||||
_ => sql.Replace(me.Parameters[i].ParameterName, me.Parameters[i].Value?.ToString())
|
||||
or DbType.StringFixedLength =>
|
||||
sql.Replace(me.Parameters[i].ParameterName, "'" + me.Parameters[i].Value + "'")
|
||||
, DbType.Boolean => sql.Replace(//
|
||||
me.Parameters[i].ParameterName
|
||||
, Convert.ToBoolean(me.Parameters[i].Value, CultureInfo.InvariantCulture) ? "1" : "0")
|
||||
, _ => sql.Replace(me.Parameters[i].ParameterName, me.Parameters[i].Value?.ToString())
|
||||
};
|
||||
}
|
||||
|
||||
return sql;
|
||||
}
|
@ -1,5 +1,8 @@
|
||||
namespace NSExt.Extensions;
|
||||
|
||||
/// <summary>
|
||||
/// DecimalExtensions
|
||||
/// </summary>
|
||||
public static class DecimalExtensions
|
||||
{
|
||||
/// <summary>
|
29
src/Extensions/EnumExtensions.cs
Normal file
29
src/Extensions/EnumExtensions.cs
Normal file
@ -0,0 +1,29 @@
|
||||
using System.Reflection;
|
||||
using NSExt.Attributes;
|
||||
|
||||
namespace NSExt.Extensions;
|
||||
|
||||
/// <summary>
|
||||
/// EnumExtensions
|
||||
/// </summary>
|
||||
public static class EnumExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取枚举的description属性
|
||||
/// </summary>
|
||||
/// <param name="e">枚举对象</param>
|
||||
/// <returns>description属性</returns>
|
||||
public static string Desc(this Enum e)
|
||||
{
|
||||
var t = e.GetType();
|
||||
var fi = t.GetField(Enum.GetName(t, e)!);
|
||||
var descAttr = fi!.GetCustomAttribute<DescriptionAttribute>(true);
|
||||
if (descAttr is null) {
|
||||
return Enum.GetName(t, e);
|
||||
}
|
||||
|
||||
var str = descAttr.Description;
|
||||
var locAttr = fi!.GetCustomAttribute<LocalizationAttribute>(true);
|
||||
return locAttr is null ? str : locAttr.ResourceClass.GetProperty(str)?.GetValue(default) as string ?? str;
|
||||
}
|
||||
}
|
@ -1,13 +1,13 @@
|
||||
namespace NSExt.Extensions;
|
||||
|
||||
/// <summary>
|
||||
/// EnumerableExtensions
|
||||
/// </summary>
|
||||
public static class EnumerableExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// 将列表转成分隔符分隔的字符串
|
||||
/// </summary>
|
||||
/// <param name="me"></param>
|
||||
/// <param name="separator"></param>
|
||||
/// <returns></returns>
|
||||
public static string Join(this IEnumerable<object> me, string separator)
|
||||
{
|
||||
return string.Join(separator, me);
|
41
src/Extensions/GenericExtensions.cs
Normal file
41
src/Extensions/GenericExtensions.cs
Normal file
@ -0,0 +1,41 @@
|
||||
namespace NSExt.Extensions;
|
||||
|
||||
/// <summary>
|
||||
/// GenericExtensions
|
||||
/// </summary>
|
||||
public static class GenericExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// 从指定的对象拷贝属性
|
||||
/// </summary>
|
||||
/// <typeparam name="T">对象类型</typeparam>
|
||||
/// <param name="me">拷贝目标</param>
|
||||
/// <param name="copyObj">拷贝来源</param>
|
||||
/// <param name="propNameList">需要处理的属性名</param>
|
||||
/// <param name="isIncludeOrExclude">True包含,false排除</param>
|
||||
public static void CopyFrom<T>(this T me, T copyObj, IList<string> propNameList = null
|
||||
, bool isIncludeOrExclude = false)
|
||||
{
|
||||
foreach (var p in me.GetType().GetProperties()) {
|
||||
if (!p.CanWrite) {
|
||||
continue;
|
||||
}
|
||||
|
||||
var isSet = isIncludeOrExclude
|
||||
? propNameList?.Contains(p.Name) ?? false
|
||||
: !propNameList?.Contains(p.Name) ?? true;
|
||||
if (isSet) {
|
||||
p.SetValue(me, copyObj.GetType().GetProperty(p.Name)?.GetValue(copyObj, null), null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 判断是否与某对象相等
|
||||
/// </summary>
|
||||
public static T Is<T>(this T me, T compare, T ret)
|
||||
where T : struct
|
||||
{
|
||||
return me.Equals(compare) ? ret : me;
|
||||
}
|
||||
}
|
@ -1,15 +1,15 @@
|
||||
namespace NSExt.Extensions;
|
||||
|
||||
/// <summary>
|
||||
/// IntExtensions
|
||||
/// </summary>
|
||||
public static class IntExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// 判断枚举是否包含某个位
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="me"></param>
|
||||
/// <param name="flag"></param>
|
||||
/// <returns></returns>
|
||||
public static bool HasFlag<T>(this int me, T flag) where T : Enum
|
||||
public static bool HasFlag<T>(this int me, T flag)
|
||||
where T : Enum
|
||||
{
|
||||
return ((long)me).HasFlag(flag);
|
||||
}
|
||||
@ -18,7 +18,6 @@ public static class IntExtensions
|
||||
/// 生成随机数
|
||||
/// </summary>
|
||||
/// <param name="me">大于等于[0],小于[1]</param>
|
||||
/// <returns></returns>
|
||||
public static int Rand(this int[] me)
|
||||
{
|
||||
return new Random(Guid.NewGuid().GetHashCode()).Next(me[0], me[1]);
|
||||
@ -27,8 +26,6 @@ public static class IntExtensions
|
||||
/// <summary>
|
||||
/// 转换成ipv4
|
||||
/// </summary>
|
||||
/// <param name="me"></param>
|
||||
/// <returns></returns>
|
||||
public static string ToIpV4(this int me)
|
||||
{
|
||||
return string.Join(".", BitConverter.GetBytes(me).Reverse());
|
27
src/Extensions/JsonSerializerOptionsExtensions.cs
Normal file
27
src/Extensions/JsonSerializerOptionsExtensions.cs
Normal file
@ -0,0 +1,27 @@
|
||||
using System.Text.Encodings.Web;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace NSExt.Extensions;
|
||||
|
||||
/// <summary>
|
||||
/// JsonSerializerOptionsExtensions
|
||||
/// </summary>
|
||||
public static class JsonSerializerOptionsExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// NewJsonSerializerOptions
|
||||
/// </summary>
|
||||
public static JsonSerializerOptions NewJsonSerializerOptions(this JsonSerializerOptions _)
|
||||
{
|
||||
return new JsonSerializerOptions {
|
||||
ReadCommentHandling = JsonCommentHandling.Skip
|
||||
, AllowTrailingCommas = true
|
||||
, DictionaryKeyPolicy = JsonNamingPolicy.CamelCase
|
||||
, PropertyNamingPolicy = JsonNamingPolicy.CamelCase
|
||||
, Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping
|
||||
, NumberHandling = JsonNumberHandling.AllowReadingFromString
|
||||
, PropertyNameCaseInsensitive = true
|
||||
};
|
||||
}
|
||||
}
|
88
src/Extensions/LoggerExtensions.cs
Normal file
88
src/Extensions/LoggerExtensions.cs
Normal file
@ -0,0 +1,88 @@
|
||||
// ReSharper disable TemplateIsNotCompileTimeConstantProblem
|
||||
|
||||
namespace NSExt.Extensions;
|
||||
|
||||
/// <summary>
|
||||
/// LoggerExtensions
|
||||
/// </summary>
|
||||
public static class LoggerExtensions
|
||||
{
|
||||
private const string _MESSAGE_S_THREADID_CALLERNAME_CALLERFILEPATH_CALLERLINENUMBER
|
||||
= "{Message} <s:{ThreadId}#{CallerName}@{CallerFilePath}:{CallerLineNumber}>";
|
||||
|
||||
private static readonly Action<ILogger, string, string, string, string, string, Exception> _logDebug
|
||||
= LoggerMessage.Define<string, string, string, string, string>(LogLevel.Debug, default
|
||||
, _MESSAGE_S_THREADID_CALLERNAME_CALLERFILEPATH_CALLERLINENUMBER);
|
||||
|
||||
private static readonly Action<ILogger, string, string, string, string, string, Exception> _logError
|
||||
= LoggerMessage.Define<string, string, string, string, string>(LogLevel.Error, default
|
||||
, _MESSAGE_S_THREADID_CALLERNAME_CALLERFILEPATH_CALLERLINENUMBER);
|
||||
|
||||
private static readonly Action<ILogger, string, string, string, string, string, Exception> _logFatal
|
||||
= LoggerMessage.Define<string, string, string, string, string>(LogLevel.Critical, default
|
||||
, _MESSAGE_S_THREADID_CALLERNAME_CALLERFILEPATH_CALLERLINENUMBER);
|
||||
|
||||
private static readonly Action<ILogger, string, string, string, string, string, Exception> _logInfo
|
||||
= LoggerMessage.Define<string, string, string, string, string>(LogLevel.Information, default
|
||||
, _MESSAGE_S_THREADID_CALLERNAME_CALLERFILEPATH_CALLERLINENUMBER);
|
||||
|
||||
private static readonly Action<ILogger, string, string, string, string, string, Exception> _logWarn
|
||||
= LoggerMessage.Define<string, string, string, string, string>(LogLevel.Warning, default
|
||||
, _MESSAGE_S_THREADID_CALLERNAME_CALLERFILEPATH_CALLERLINENUMBER);
|
||||
|
||||
/// <summary>
|
||||
/// Debug
|
||||
/// </summary>
|
||||
public static void Debug(this ILogger me, object message, [CallerMemberName] string callerName = null
|
||||
, [CallerFilePath] string callerFilePath = null, [CallerLineNumber] int callerLineNumber = 0)
|
||||
{
|
||||
_logDebug(me, message.ToString(), Environment.CurrentManagedThreadId.ToString(CultureInfo.InvariantCulture)
|
||||
, callerName, Path.GetFileName(callerFilePath), callerLineNumber.ToString(CultureInfo.InvariantCulture)
|
||||
, null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Error
|
||||
/// </summary>
|
||||
public static void Error(this ILogger me, object message, [CallerMemberName] string callerName = null
|
||||
, [CallerFilePath] string callerFilePath = null, [CallerLineNumber] int callerLineNumber = 0)
|
||||
{
|
||||
_logError(me, message.ToString(), Environment.CurrentManagedThreadId.ToString(CultureInfo.InvariantCulture)
|
||||
, callerName, Path.GetFileName(callerFilePath), callerLineNumber.ToString(CultureInfo.InvariantCulture)
|
||||
, null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fatal
|
||||
/// </summary>
|
||||
public static void Fatal(this ILogger me, object message, Exception ex = null
|
||||
, [CallerMemberName] string callerName = null, [CallerFilePath] string callerFilePath = null
|
||||
, [CallerLineNumber] int callerLineNumber = 0)
|
||||
{
|
||||
_logFatal(me, message.ToString(), Environment.CurrentManagedThreadId.ToString(CultureInfo.InvariantCulture)
|
||||
, callerName, Path.GetFileName(callerFilePath), callerLineNumber.ToString(CultureInfo.InvariantCulture)
|
||||
, ex);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Info
|
||||
/// </summary>
|
||||
public static void Info(this ILogger me, object message, [CallerMemberName] string callerName = null
|
||||
, [CallerFilePath] string callerFilePath = null, [CallerLineNumber] int callerLineNumber = 0)
|
||||
{
|
||||
_logInfo(me, message.ToString(), Environment.CurrentManagedThreadId.ToString(CultureInfo.InvariantCulture)
|
||||
, callerName, Path.GetFileName(callerFilePath), callerLineNumber.ToString(CultureInfo.InvariantCulture)
|
||||
, null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Warn
|
||||
/// </summary>
|
||||
public static void Warn(this ILogger me, object message, [CallerMemberName] string callerName = null
|
||||
, [CallerFilePath] string callerFilePath = null, [CallerLineNumber] int callerLineNumber = 0)
|
||||
{
|
||||
_logWarn(me, message.ToString(), Environment.CurrentManagedThreadId.ToString(CultureInfo.InvariantCulture)
|
||||
, callerName, Path.GetFileName(callerFilePath), callerLineNumber.ToString(CultureInfo.InvariantCulture)
|
||||
, null);
|
||||
}
|
||||
}
|
@ -1,15 +1,15 @@
|
||||
namespace NSExt.Extensions;
|
||||
|
||||
/// <summary>
|
||||
/// LongExtensions
|
||||
/// </summary>
|
||||
public static class LongExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// 判断枚举是否包含某个位
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="me"></param>
|
||||
/// <param name="flag"></param>
|
||||
/// <returns></returns>
|
||||
public static bool HasFlag<T>(this long me, T flag) where T : Enum
|
||||
public static bool HasFlag<T>(this long me, T flag)
|
||||
where T : Enum
|
||||
{
|
||||
var val = (long)(object)flag;
|
||||
return (me & val) == val;
|
||||
@ -18,8 +18,6 @@ public static class LongExtensions
|
||||
/// <summary>
|
||||
/// 1970毫秒数转换成日期对象
|
||||
/// </summary>
|
||||
/// <param name="msFrom1970"></param>
|
||||
/// <returns></returns>
|
||||
public static DateTime Time(this long msFrom1970)
|
||||
{
|
||||
return new DateTime(1970, 1, 1).AddMilliseconds(msFrom1970).ToLocalTime();
|
33
src/Extensions/ObjectExtensions.cs
Normal file
33
src/Extensions/ObjectExtensions.cs
Normal file
@ -0,0 +1,33 @@
|
||||
using System.Text.Json;
|
||||
|
||||
namespace NSExt.Extensions;
|
||||
|
||||
/// <summary>
|
||||
/// ObjectExtensions
|
||||
/// </summary>
|
||||
public static class ObjectExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// 将一个对象序列化成json文本
|
||||
/// </summary>
|
||||
/// <param name="me">指定对象</param>
|
||||
/// <param name="format">是否格式化</param>
|
||||
/// <returns>json文本</returns>
|
||||
public static string Json(this object me, bool format = false)
|
||||
{
|
||||
var defaultOptions = default(JsonSerializerOptions).NewJsonSerializerOptions();
|
||||
defaultOptions.WriteIndented = format;
|
||||
return Json(me, defaultOptions);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将一个对象序列化成json文本
|
||||
/// </summary>
|
||||
/// <param name="me">指定对象</param>
|
||||
/// <param name="options">序列化选项</param>
|
||||
/// <returns>json文本</returns>
|
||||
public static string Json(this object me, JsonSerializerOptions options)
|
||||
{
|
||||
return JsonSerializer.Serialize(me, options);
|
||||
}
|
||||
}
|
30
src/Extensions/StreamExtensions.cs
Normal file
30
src/Extensions/StreamExtensions.cs
Normal file
@ -0,0 +1,30 @@
|
||||
namespace NSExt.Extensions;
|
||||
|
||||
/// <summary>
|
||||
/// StreamExtensions
|
||||
/// </summary>
|
||||
public static class StreamExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// FirstByteIndex
|
||||
/// </summary>
|
||||
public static long FirstByteIndex(this Stream me, byte[] findBytes)
|
||||
{
|
||||
int data;
|
||||
while ((data = me.ReadByte()) != -1) {
|
||||
if (findBytes.Contains((byte)data)) {
|
||||
return me.Position;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// IsTextStream
|
||||
/// </summary>
|
||||
public static bool IsTextStream(this Stream me)
|
||||
{
|
||||
return me.FirstByteIndex(new byte[] { 0x00, 0xff }) < 0;
|
||||
}
|
||||
}
|
@ -1,43 +1,27 @@
|
||||
// ReSharper disable UnusedMember.Global
|
||||
// ReSharper disable MemberCanBePrivate.Global
|
||||
|
||||
|
||||
#pragma warning disable CA1720
|
||||
using System.Security.Cryptography;
|
||||
using System.Text.Json;
|
||||
using NSExt.Constant;
|
||||
|
||||
namespace NSExt.Extensions;
|
||||
|
||||
/// <summary>
|
||||
/// StringExtensions
|
||||
/// </summary>
|
||||
public static class StringExtensions
|
||||
{
|
||||
private static readonly JsonSerializerOptions _defaultJsonSerializerOptions =
|
||||
default(JsonSerializerOptions).NewJsonSerializerOptions();
|
||||
|
||||
/// <summary>
|
||||
/// MD5 hmac编码
|
||||
/// </summary>
|
||||
/// <param name="me">字符串</param>
|
||||
/// <param name="key">密钥</param>
|
||||
/// <param name="e">字符串使用的编码</param>
|
||||
/// <returns>hash摘要的16进制文本形式(无连字符小写)</returns>
|
||||
private static string Md5Hmac(this string me, string key, Encoding e)
|
||||
{
|
||||
using var md5Hmac = new HMACMD5(e.GetBytes(key));
|
||||
return BitConverter.ToString(md5Hmac.ComputeHash(e.GetBytes(me)))
|
||||
.Replace("-", string.Empty)
|
||||
.ToLower(CultureInfo.CurrentCulture);
|
||||
}
|
||||
private static readonly JsonSerializerOptions _defaultJsonSerializerOptions
|
||||
= default(JsonSerializerOptions).NewJsonSerializerOptions();
|
||||
|
||||
/// <summary>
|
||||
/// aes加密
|
||||
/// </summary>
|
||||
/// <param name="me">要加密的串</param>
|
||||
/// <param name="key">密钥</param>
|
||||
/// <param name="cipherMode">指定要用于加密的块密码模式。</param>
|
||||
/// <param name="paddingMode">指定在消息数据块短于加密操作所需的完整字节数时要应用的填充类型。</param>
|
||||
/// <returns></returns>
|
||||
public static string Aes(this string me,
|
||||
string key,
|
||||
CipherMode cipherMode = CipherMode.ECB,
|
||||
PaddingMode paddingMode = PaddingMode.PKCS7)
|
||||
public static string Aes(this string me, string key)
|
||||
{
|
||||
using var aes = System.Security.Cryptography.Aes.Create();
|
||||
aes.Padding = PaddingMode.PKCS7;
|
||||
@ -49,19 +33,12 @@ public static class StringExtensions
|
||||
return decrypted.Base64();
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// aes解密
|
||||
/// </summary>
|
||||
/// <param name="me">要加密的串</param>
|
||||
/// <param name="key">密钥</param>
|
||||
/// <param name="cipherMode">指定要用于加密的块密码模式。</param>
|
||||
/// <param name="paddingMode">指定在消息数据块短于加密操作所需的完整字节数时要应用的填充类型。</param>
|
||||
/// <returns></returns>
|
||||
public static string AesDe(this string me,
|
||||
string key,
|
||||
CipherMode cipherMode = CipherMode.ECB,
|
||||
PaddingMode paddingMode = PaddingMode.PKCS7)
|
||||
public static string AesDe(this string me, string key)
|
||||
{
|
||||
using var aes = System.Security.Cryptography.Aes.Create();
|
||||
aes.Padding = PaddingMode.PKCS7;
|
||||
@ -102,13 +79,12 @@ public static class StringExtensions
|
||||
/// <returns>解码后的原始字符串</returns>
|
||||
public static string Base64De(this string me, Encoding e)
|
||||
{
|
||||
return e.GetString(Base64De(me));
|
||||
return e.GetString(me.Base64De());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将易于web传输的base64web字符串转换为原生base64
|
||||
/// </summary>
|
||||
/// <param name="me"></param>
|
||||
/// <returns>原生base64</returns>
|
||||
public static string Base64Sys(this string me)
|
||||
{
|
||||
@ -118,7 +94,6 @@ public static class StringExtensions
|
||||
/// <summary>
|
||||
/// 将原生base64字符串转换成易于web传输的字符串
|
||||
/// </summary>
|
||||
/// <param name="me"></param>
|
||||
/// <returns>易于web传输的字符串</returns>
|
||||
public static string Base64Web(this string me)
|
||||
{
|
||||
@ -160,7 +135,6 @@ public static class StringExtensions
|
||||
: ret;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 将字符串转换成日期对象
|
||||
/// </summary>
|
||||
@ -182,7 +156,6 @@ public static class StringExtensions
|
||||
return decimal.Parse(me, CultureInfo.CurrentCulture);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 尝试将字符串转为decimal
|
||||
/// </summary>
|
||||
@ -194,7 +167,6 @@ public static class StringExtensions
|
||||
return !decimal.TryParse(me, out var ret) ? def : ret;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// string to double
|
||||
/// </summary>
|
||||
@ -208,23 +180,17 @@ public static class StringExtensions
|
||||
/// <summary>
|
||||
/// 将字符串转换成枚举对象
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="name"></param>
|
||||
/// <returns></returns>
|
||||
public static T Enum<T>(this string name) where T : Enum
|
||||
public static T Enum<T>(this string name)
|
||||
where T : Enum
|
||||
{
|
||||
return (T)System.Enum.Parse(typeof(T), name, true);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 将字符串转换成枚举对象
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="name"></param>
|
||||
/// <param name="def"></param>
|
||||
/// <returns></returns>
|
||||
public static T EnumTry<T>(this string name, T def) where T : Enum
|
||||
public static T EnumTry<T>(this string name, T def)
|
||||
where T : Enum
|
||||
{
|
||||
return !System.Enum.TryParse(typeof(T), name, out var ret) ? def : (T)ret;
|
||||
}
|
||||
@ -239,12 +205,10 @@ public static class StringExtensions
|
||||
return float.Parse(me, CultureInfo.CurrentCulture);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 将字符串转为guid
|
||||
/// </summary>
|
||||
/// <param name="me">字符串</param>
|
||||
/// <returns></returns>
|
||||
public static Guid Guid(this string me)
|
||||
{
|
||||
return System.Guid.Parse(me);
|
||||
@ -255,13 +219,11 @@ public static class StringExtensions
|
||||
/// </summary>
|
||||
/// <param name="me">字符串</param>
|
||||
/// <param name="def">转换失败的返回值</param>
|
||||
/// <returns></returns>
|
||||
public static Guid Guid(this string me, Guid def)
|
||||
{
|
||||
return System.Guid.TryParse(me, out var ret) ? ret : def;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 将字符串转换成字节数组形式
|
||||
/// </summary>
|
||||
@ -283,11 +245,10 @@ public static class StringExtensions
|
||||
return me.Hex(Encoding.UTF8);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 对一个字符串进行sha1 hash运算
|
||||
/// </summary>
|
||||
/// <param name="me">对一个字符串进行sha1 hash运算</param>
|
||||
/// <param name="me">me</param>
|
||||
/// <param name="secret">密钥</param>
|
||||
/// <param name="e">使用的编码</param>
|
||||
/// <returns>hash摘要的16进制文本形式(无连字符小写)</returns>
|
||||
@ -303,8 +264,6 @@ public static class StringExtensions
|
||||
/// <summary>
|
||||
/// html编码
|
||||
/// </summary>
|
||||
/// <param name="me"></param>
|
||||
/// <returns></returns>
|
||||
public static string Html(this string me)
|
||||
{
|
||||
return HttpUtility.HtmlEncode(me);
|
||||
@ -341,7 +300,6 @@ public static class StringExtensions
|
||||
return !int.TryParse(me, out var ret) ? def : ret;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// string to Int64
|
||||
/// </summary>
|
||||
@ -366,43 +324,43 @@ public static class StringExtensions
|
||||
/// <summary>
|
||||
/// ipv4格式转int32格式
|
||||
/// </summary>
|
||||
/// <param name="me"></param>
|
||||
/// <returns></returns>
|
||||
public static int IpV4ToInt32(this string me)
|
||||
{
|
||||
return BitConverter.ToInt32(me.Split('.').Select(byte.Parse).Reverse().ToArray(), 0);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 是否base64字符串
|
||||
/// </summary>
|
||||
/// <param name="me">字符串</param>
|
||||
/// <returns></returns>
|
||||
public static bool IsBase64String(this string me)
|
||||
{
|
||||
// 一个合法的Base64,有着以下特征:
|
||||
// 字符串的长度为4的整数倍。
|
||||
// 字符串的符号取值只能在A -Z, a -z, 0 -9, +, /, =共计65个字符中,且 = 如果出现就必须在结尾出现。
|
||||
if (!me.All(x => x.IsBase64Character())) return false;
|
||||
if (me.Length % 4 != 0) return false;
|
||||
if (!me.All(x => x.IsBase64Character())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (me.Length % 4 != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var firstEqualSignPos = me.IndexOf('=');
|
||||
if (firstEqualSignPos < 0) return true;
|
||||
if (firstEqualSignPos < 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
var lastEqualSignPos = me.LastIndexOf('=');
|
||||
return lastEqualSignPos == me.Length - 1 && me[firstEqualSignPos..lastEqualSignPos].All(x => x == '=');
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 中文姓名打马赛克
|
||||
/// </summary>
|
||||
/// <param name="me"></param>
|
||||
/// <returns></returns>
|
||||
public static string MaskChineseName(this string me)
|
||||
{
|
||||
if (me.Length == 2) return "*" + me[1..];
|
||||
|
||||
return me[..1] + "*" + me[^1..];
|
||||
return me.Length == 2 ? "*" + me[1..] : me[..1] + "*" + me[^1..];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -412,10 +370,9 @@ public static class StringExtensions
|
||||
/// <returns>掩码后的手机号</returns>
|
||||
public static string MaskMobile(this string me)
|
||||
{
|
||||
return new Regex(@"^(\d{3})\d{4}(\d{4})$").Replace(me, "$1****$2");
|
||||
return Regexes.RegexMobile.Replace(me, "$1****$2");
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 对一个字符串进行md5hash运算
|
||||
/// </summary>
|
||||
@ -424,8 +381,7 @@ public static class StringExtensions
|
||||
/// <returns>hash摘要的16进制文本形式(无连字符小写)</returns>
|
||||
public static string Md5(this string me, Encoding e)
|
||||
{
|
||||
using var md5 = MD5.Create();
|
||||
return BitConverter.ToString(md5.ComputeHash(e.GetBytes(me)))
|
||||
return BitConverter.ToString(MD5.HashData(e.GetBytes(me)))
|
||||
.Replace("-", string.Empty)
|
||||
.ToLower(CultureInfo.CurrentCulture);
|
||||
}
|
||||
@ -441,12 +397,9 @@ public static class StringExtensions
|
||||
return me.AsEnumerable().NullOrEmpty() ? defVal : me;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// null或空白字符
|
||||
/// </summary>
|
||||
/// <param name="me"></param>
|
||||
/// <returns></returns>
|
||||
public static bool NullOrWhiteSpace(this string me)
|
||||
{
|
||||
return string.IsNullOrWhiteSpace(me);
|
||||
@ -463,7 +416,6 @@ public static class StringExtensions
|
||||
return JsonSerializer.Deserialize<T>(me, options ?? _defaultJsonSerializerOptions);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 反序列化一个文件获得指定类型的数据对象
|
||||
/// </summary>
|
||||
@ -476,7 +428,6 @@ public static class StringExtensions
|
||||
return JsonSerializer.Deserialize(me, type, options ?? _defaultJsonSerializerOptions);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 生成密码
|
||||
/// </summary>
|
||||
@ -494,20 +445,17 @@ public static class StringExtensions
|
||||
/// <returns>处理之后的字符串</returns>
|
||||
public static string RemoveHtmlTag(this string me)
|
||||
{
|
||||
return new Regex(@"<[^>]*>").Replace(me, "");
|
||||
return Regexes.RegexHtmlTag.Replace(me, string.Empty);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 删除换行符
|
||||
/// </summary>
|
||||
/// <param name="me"></param>
|
||||
/// <returns></returns>
|
||||
public static string RemoveWrapped(this string me)
|
||||
{
|
||||
return me.Replace("\r", "").Replace("\n", "");
|
||||
return me.Replace("\r", string.Empty).Replace("\n", string.Empty);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 对一个字符串进行sha1 hash运算
|
||||
/// </summary>
|
||||
@ -516,49 +464,59 @@ public static class StringExtensions
|
||||
/// <returns>hash摘要的16进制文本形式(无连字符小写)</returns>
|
||||
public static string Sha1(this string me, Encoding e)
|
||||
{
|
||||
using var sha1 = SHA1.Create();
|
||||
return BitConverter.ToString(sha1.ComputeHash(e.GetBytes(me)))
|
||||
return BitConverter.ToString(SHA1.HashData(e.GetBytes(me)))
|
||||
.Replace("-", string.Empty)
|
||||
.ToLower(CultureInfo.CurrentCulture);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 蛇形命名
|
||||
/// </summary>
|
||||
/// <param name="me"></param>
|
||||
/// <returns></returns>
|
||||
public static string Snakecase(this string me)
|
||||
{
|
||||
return Regex.Replace(me, "([A-Z])", "-$1").ToLower().TrimStart('-');
|
||||
return Regexes.RegexUpLetter.Replace(me, "-$1").ToLower(CultureInfo.InvariantCulture).TrimStart('-');
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 截取指定长度的字符串,代替substring
|
||||
/// </summary>
|
||||
/// <param name="me"></param>
|
||||
/// <param name="startIndex"></param>
|
||||
/// <param name="length"></param>
|
||||
/// <returns></returns>
|
||||
public static string Sub(this string me, int startIndex, int length)
|
||||
{
|
||||
if (startIndex + length > me.Length) length = me.Length - startIndex;
|
||||
if (startIndex + length > me.Length) {
|
||||
length = me.Length - startIndex;
|
||||
}
|
||||
|
||||
return me.Substring(startIndex, length);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 纯文本字符串转html
|
||||
/// </summary>
|
||||
public static string Text2Html(this string me)
|
||||
{
|
||||
return $"<pre>{me}</pre>";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将连续多个空格替换成一个空格
|
||||
/// </summary>
|
||||
/// <param name="me"></param>
|
||||
/// <returns></returns>
|
||||
public static string TrimSpaces(this string me)
|
||||
{
|
||||
var ret = me.Replace(" ", " ");
|
||||
|
||||
// ReSharper disable once TailRecursiveCall
|
||||
return ret == me ? ret : TrimSpaces(ret);
|
||||
return ret == me ? ret : ret.TrimSpaces();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将\ux0000 、 %u0000 、 &#x0000; 编码转换成可读字符串
|
||||
/// </summary>
|
||||
public static string UnicodeDe(this string me)
|
||||
{
|
||||
const string replacement = "&#x$1;";
|
||||
return me.Contains(@"\u") ? Regexes.RegexBacksLantUnicode.Replace(me, replacement).HtmlDe() :
|
||||
me.Contains(@"%u") ? Regexes.RegexPercentUnicode.Replace(me, replacement).HtmlDe() : me.HtmlDe();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// url编码
|
||||
@ -579,4 +537,19 @@ public static class StringExtensions
|
||||
{
|
||||
return Uri.UnescapeDataString(me);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// MD5 hmac编码
|
||||
/// </summary>
|
||||
/// <param name="me">字符串</param>
|
||||
/// <param name="key">密钥</param>
|
||||
/// <param name="e">字符串使用的编码</param>
|
||||
/// <returns>hash摘要的16进制文本形式(无连字符小写)</returns>
|
||||
private static string Md5Hmac(this string me, string key, Encoding e)
|
||||
{
|
||||
using var md5Hmac = new HMACMD5(e.GetBytes(key));
|
||||
return BitConverter.ToString(md5Hmac.ComputeHash(e.GetBytes(me)))
|
||||
.Replace("-", string.Empty)
|
||||
.ToLower(CultureInfo.CurrentCulture);
|
||||
}
|
||||
}
|
@ -1,13 +1,13 @@
|
||||
namespace NSExt.Extensions;
|
||||
|
||||
/// <summary>
|
||||
/// TypeExtensions
|
||||
/// </summary>
|
||||
public static class TypeExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// 搜索此成员的继承链以查找自定义属性,接口也会被搜索。
|
||||
/// </summary>
|
||||
/// <param name="me"></param>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <returns></returns>
|
||||
public static IEnumerable<T> GetCustomAttributesIncludingBaseInterfaces<T>(this Type me)
|
||||
{
|
||||
var attributeType = typeof(T);
|
@ -1,12 +1,13 @@
|
||||
namespace NSExt.Extensions;
|
||||
|
||||
/// <summary>
|
||||
/// UriExtensions
|
||||
/// </summary>
|
||||
public static class UriExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// 移除url的Scheme
|
||||
/// </summary>
|
||||
/// <param name="me"></param>
|
||||
/// <returns></returns>
|
||||
public static string RemoveScheme(this Uri me)
|
||||
{
|
||||
return "//" + me.Authority + me.PathAndQuery;
|
@ -1,9 +1,9 @@
|
||||
global using System.ComponentModel;
|
||||
global using System.Data;
|
||||
global using System.Data.Common;
|
||||
global using System.Runtime.CompilerServices;
|
||||
global using Microsoft.Extensions.Logging;
|
||||
global using System.Globalization;
|
||||
global using System.Runtime.CompilerServices;
|
||||
global using System.Text;
|
||||
global using System.Text.RegularExpressions;
|
||||
global using System.Web;
|
||||
global using System.ComponentModel;
|
||||
global using Microsoft.Extensions.Logging;
|
17
src/NSExt.csproj
Normal file
17
src/NSExt.csproj
Normal file
@ -0,0 +1,17 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Extensions.Logging" Version="7.0.0" />
|
||||
<PackageReference Include="MinVer" Version="4.3.0-beta.1">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
|
||||
<Import Project="../CodeQuality.props" />
|
||||
</Project>
|
@ -1,16 +0,0 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NSExt", "NSExt\NSExt.csproj", "{54814D1B-C587-4D90-A7BE-4BE1E170D5FC}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{54814D1B-C587-4D90-A7BE-4BE1E170D5FC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{54814D1B-C587-4D90-A7BE-4BE1E170D5FC}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{54814D1B-C587-4D90-A7BE-4BE1E170D5FC}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{54814D1B-C587-4D90-A7BE-4BE1E170D5FC}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
EndGlobal
|
@ -1,17 +0,0 @@
|
||||
namespace NSExt.Extensions;
|
||||
|
||||
public static class EnumExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取枚举的description属性
|
||||
/// </summary>
|
||||
/// <param name="e">枚举对象</param>
|
||||
/// <returns>description属性</returns>
|
||||
public static string Desc(this Enum e)
|
||||
{
|
||||
var t = e.GetType();
|
||||
var fi = t.GetField(Enum.GetName(t, e)!);
|
||||
var attrs = (DescriptionAttribute[])fi!.GetCustomAttributes(typeof(DescriptionAttribute), false);
|
||||
return (attrs.Length != 0 ? attrs[0].Description : Enum.GetName(t, e)) ?? "";
|
||||
}
|
||||
}
|
@ -1,43 +0,0 @@
|
||||
namespace NSExt.Extensions;
|
||||
|
||||
public static class GenericExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// 从指定的对象拷贝属性
|
||||
/// </summary>
|
||||
/// <typeparam name="T">对象类型</typeparam>
|
||||
/// <param name="me">拷贝目标</param>
|
||||
/// <param name="copyObj">拷贝来源</param>
|
||||
/// <param name="propNameList">需要处理的属性名</param>
|
||||
/// <param name="isIncludeOrExclude">True包含,false排除</param>
|
||||
public static void CopyFrom<T>(this T me,
|
||||
T copyObj,
|
||||
IList<string> propNameList = null,
|
||||
bool isIncludeOrExclude = false)
|
||||
{
|
||||
foreach (var p in me.GetType().GetProperties()) {
|
||||
if (!p.CanWrite) continue;
|
||||
bool isSet;
|
||||
if (isIncludeOrExclude)
|
||||
isSet = propNameList?.Contains(p.Name) ?? false;
|
||||
else
|
||||
isSet = !propNameList?.Contains(p.Name) ?? true;
|
||||
|
||||
if (isSet) p.SetValue(me, copyObj.GetType().GetProperty(p.Name)?.GetValue(copyObj, null), null);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 判断是否与某对象相等
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="me"></param>
|
||||
/// <param name="compare"></param>
|
||||
/// <param name="ret"></param>
|
||||
/// <returns></returns>
|
||||
public static T Is<T>(this T me, T compare, T ret) where T : struct
|
||||
{
|
||||
return me.Equals(compare) ? ret : me;
|
||||
}
|
||||
}
|
@ -1,21 +0,0 @@
|
||||
using System.Text.Encodings.Web;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace NSExt.Extensions;
|
||||
|
||||
public static class JsonSerializerOptionsExtensions
|
||||
{
|
||||
public static JsonSerializerOptions NewJsonSerializerOptions(this JsonSerializerOptions me)
|
||||
{
|
||||
return new JsonSerializerOptions {
|
||||
ReadCommentHandling = JsonCommentHandling.Skip,
|
||||
AllowTrailingCommas = true,
|
||||
DictionaryKeyPolicy = JsonNamingPolicy.CamelCase,
|
||||
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
|
||||
Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping,
|
||||
NumberHandling = JsonNumberHandling.AllowReadingFromString | JsonNumberHandling.WriteAsString,
|
||||
PropertyNameCaseInsensitive = true
|
||||
};
|
||||
}
|
||||
}
|
@ -1,66 +0,0 @@
|
||||
// ReSharper disable TemplateIsNotCompileTimeConstantProblem
|
||||
|
||||
namespace NSExt.Extensions;
|
||||
|
||||
public static class LoggerExtensions
|
||||
{
|
||||
private static string CallerInfoMessage(object message,
|
||||
string callerName,
|
||||
string callerFilePath,
|
||||
int callerLineNumber)
|
||||
{
|
||||
return
|
||||
$"{message} <s:{Environment.CurrentManagedThreadId}#{callerName}@{Path.GetFileName(callerFilePath)}:{callerLineNumber}>";
|
||||
}
|
||||
|
||||
public static void Debug(this ILogger me,
|
||||
object message,
|
||||
[CallerMemberName] string callerName = null,
|
||||
[CallerFilePath] string callerFilePath = null,
|
||||
[CallerLineNumber] int callerLineNumber = 0)
|
||||
{
|
||||
me.LogDebug(CallerInfoMessage(message, callerName, callerFilePath, callerLineNumber));
|
||||
}
|
||||
|
||||
|
||||
public static void Error(this ILogger me,
|
||||
object message,
|
||||
[CallerMemberName] string callerName = null,
|
||||
[CallerFilePath] string callerFilePath = null,
|
||||
[CallerLineNumber] int callerLineNumber = 0)
|
||||
{
|
||||
me.LogError(CallerInfoMessage(message, callerName, callerFilePath, callerLineNumber));
|
||||
}
|
||||
|
||||
public static void Fatal(this ILogger me,
|
||||
object message,
|
||||
Exception ex = null,
|
||||
[CallerMemberName] string callerName = null,
|
||||
[CallerFilePath] string callerFilePath = null,
|
||||
[CallerLineNumber] int callerLineNumber = 0)
|
||||
{
|
||||
if (ex is null)
|
||||
me.LogCritical(CallerInfoMessage(message, callerName, callerFilePath, callerLineNumber));
|
||||
else
|
||||
me.LogCritical(CallerInfoMessage(message, callerName, callerFilePath, callerLineNumber), ex);
|
||||
}
|
||||
|
||||
|
||||
public static void Info(this ILogger me,
|
||||
object message,
|
||||
[CallerMemberName] string callerName = null,
|
||||
[CallerFilePath] string callerFilePath = null,
|
||||
[CallerLineNumber] int callerLineNumber = 0)
|
||||
{
|
||||
me.LogInformation(CallerInfoMessage(message, callerName, callerFilePath, callerLineNumber));
|
||||
}
|
||||
|
||||
public static void Warn(this ILogger me,
|
||||
object message,
|
||||
[CallerMemberName] string callerName = null,
|
||||
[CallerFilePath] string callerFilePath = null,
|
||||
[CallerLineNumber] int callerLineNumber = 0)
|
||||
{
|
||||
me.LogWarning(CallerInfoMessage(message, callerName, callerFilePath, callerLineNumber));
|
||||
}
|
||||
}
|
@ -1,21 +0,0 @@
|
||||
using System.Text.Json;
|
||||
|
||||
namespace NSExt.Extensions;
|
||||
|
||||
public static class ObjectExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// 将一个对象序列化成json文本
|
||||
/// </summary>
|
||||
/// <param name="me">指定对象</param>
|
||||
/// <param name="format">是否格式化</param>
|
||||
/// <returns>json文本</returns>
|
||||
public static string Json(this object me, bool format = false)
|
||||
{
|
||||
return JsonSerializer.Serialize(me,
|
||||
new JsonSerializerOptions {
|
||||
WriteIndented = format,
|
||||
PropertyNamingPolicy = JsonNamingPolicy.CamelCase
|
||||
});
|
||||
}
|
||||
}
|
@ -1,22 +0,0 @@
|
||||
namespace NSExt.Extensions;
|
||||
|
||||
public static class StreamExtensions
|
||||
{
|
||||
public static long FirstByteIndex(this Stream me, byte[] findBytes)
|
||||
{
|
||||
int data;
|
||||
while ((data = me.ReadByte()) != -1)
|
||||
if (findBytes.Contains((byte)data))
|
||||
return me.Position;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
public static bool IsTextStream(this Stream me)
|
||||
{
|
||||
return me.FirstByteIndex(new byte[] {
|
||||
0x00,
|
||||
0xff
|
||||
}) < 0;
|
||||
}
|
||||
}
|
@ -1,14 +0,0 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>net6.0;net7.0</TargetFrameworks>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Version>1.0.6</Version>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Extensions.Logging" Version="7.0.0"/>
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
</Project>
|
9
stylecop.json
Normal file
9
stylecop.json
Normal file
@ -0,0 +1,9 @@
|
||||
{
|
||||
"$schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json",
|
||||
"settings": {
|
||||
"indentation": {
|
||||
"useTabs": false,
|
||||
"indentationSize": 4
|
||||
}
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user