12 Commits

Author SHA1 Message Date
tk
f2444b3048 feat: enum、string 2023-02-27 11:03:19 +08:00
d1978d9d9e <chore> 2023-02-08 22:20:16 +08:00
1f17375915 feat: * 泛型特性本地化资源描述 * 添加测试项目 2023-02-08 22:15:56 +08:00
f846b7bdbf 调整一下日志格式 2023-01-29 20:32:58 +08:00
9384bc0692 <chore> 2023-01-19 20:35:34 +08:00
05ca80acda <fix> 将一个对象序列化成json文本 2023-01-14 23:40:34 +08:00
cc761e4939 <feat> 从资源文件读取Description-可继承 2023-01-10 11:14:15 +08:00
d23092e8fc <feat> 从资源文件读取Description 2023-01-08 20:01:03 +08:00
13f8ae51c2 Merge branch 'dev' of https://github.com/nsnail/ns-ext into dev 2023-01-04 18:21:12 +08:00
52b3170e10 bugfix 2023-01-04 18:12:44 +08:00
f3d0f98970 <fix> 2022-12-27 16:14:38 +08:00
485e7a0ead <revert> 2022-12-16 23:20:37 +08:00
43 changed files with 591 additions and 470 deletions

View File

@ -13,15 +13,20 @@ trim_trailing_whitespace = true
[*.cs]
dotnet_analyzer_diagnostic.severity = warning
dotnet_diagnostic.CA1707.severity = none
dotnet_diagnostic.CA1720.severity = none
dotnet_diagnostic.CA1716.severity = none
dotnet_diagnostic.CA1848.severity = none
dotnet_diagnostic.CA2254.severity = none
dotnet_diagnostic.CA5350.severity = none
dotnet_diagnostic.CA5351.severity = none
dotnet_diagnostic.IDE0005.severity = none
dotnet_diagnostic.IDE0008.severity = none
dotnet_diagnostic.IDE0010.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
dotnet_diagnostic.SYSLIB1045.severity = none
# ReSharper properties

4
.gitignore vendored
View File

@ -29,7 +29,7 @@ x86/
bld/
[Bb]in/
[Oo]bj/
[Ll]og/
# [Ll]og/
[Ll]ogs/
# Visual Studio 2015/2017 cache/options directory
@ -399,6 +399,6 @@ FodyWeavers.xsd
.idea/
# User Define
build/
dist/
nuget.config
*.[Dd]esigner.cs

View File

@ -1,16 +1,27 @@
#r "nuget: Newtonsoft.Json, 13.0.0"
using System.Xml;
using System.IO;
using Newtonsoft.Json.Linq;
var path = Directory.GetFiles(@".idea", "workspace.xml", SearchOption.AllDirectories).First();
const string findStr = """
&quot;keyToString&quot;: {
""";
const string replaceStr = """
&quot;keyToString&quot;: {
&quot;rider.code.cleanup.on.save&quot;: &quot;true&quot;,
""";
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);
XmlDocument xdoc = new XmlDocument();
using(var fs = File.Open(path, FileMode.Open)){
xdoc.Load(fs);
fs.Seek(0, SeekOrigin.Begin);
var propertiesComponent = xdoc.SelectSingleNode("""//component[@name="PropertiesComponent"]""");
var jsonStr = propertiesComponent.InnerText;
var jsonObj = JObject.Parse(jsonStr);
var keyToStringObj = jsonObj["keyToString"] as JObject;
if (keyToStringObj.ContainsKey("rider.code.cleanup.on.save")) return;
keyToStringObj.Add(new JProperty("rider.code.cleanup.on.save", "true"));
var newNode = xdoc.CreateCDataSection(jsonObj.ToString());
propertiesComponent.InnerText=string.Empty;
propertiesComponent.AppendChild(newNode);
var settings = new XmlWriterSettings { Indent = true };
using(var writer = XmlWriter.Create(fs, settings)){
xdoc.WriteTo(writer);
}
}

View File

@ -1,6 +1,6 @@
<Project>
<PropertyGroup>
<CodeAnalysisRuleSet>../StyleCopAnalyzers.ruleset</CodeAnalysisRuleSet>
<CodeAnalysisRuleSet>../../StyleCopAnalyzers.ruleset</CodeAnalysisRuleSet>
<CodeAnalysisTreatWarningsAsErrors>true</CodeAnalysisTreatWarningsAsErrors>
<EnforceCodeStyleInBuild>true</EnforceCodeStyleInBuild>
<MSBuildTreatWarningsAsErrors>true</MSBuildTreatWarningsAsErrors>
@ -13,5 +13,9 @@
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="NSCodeAnalysis" Version="1.0.1-alpha.0.2">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>
</Project>

View File

@ -1,22 +1,13 @@
<Project>
<PropertyGroup>
<ImplicitUsings>enable</ImplicitUsings>
<BaseOutputPath>../dist</BaseOutputPath>
<BaseIntermediateOutputPath>../dist</BaseIntermediateOutputPath>
<OutputPath>$(BaseOutputPath)/$(MSBuildProjectName)/bin</OutputPath>
<IntermediateOutputPath>$(BaseIntermediateOutputPath)/$(MSBuildProjectName)/obj</IntermediateOutputPath>
<MSBuildProjectExtensionsPath>$(BaseIntermediateOutputPath)/$(MSBuildProjectName)/obj</MSBuildProjectExtensionsPath>
<!-- $(XXX) 定义有顺序 排序请注意-->
<SolutionDir>$(MSBuildThisFileDirectory)</SolutionDir>
<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>
<BaseIntermediateOutputPath>$(SolutionDir)/dist/$(MSBuildProjectName)/obj</BaseIntermediateOutputPath>
<BaseOutputPath>$(SolutionDir)/dist/$(MSBuildProjectName)/bin</BaseOutputPath>
<Copyright>© 2006-2023 nsnail</Copyright>
<EnableBaseIntermediateOutputPathMismatchWarning>false</EnableBaseIntermediateOutputPathMismatchWarning>
<ImplicitUsings>enable</ImplicitUsings>
<TargetFramework>net7.0</TargetFramework>
</PropertyGroup>
</Project>

View File

@ -3,8 +3,6 @@ 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
@ -17,18 +15,23 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "meta", "meta", "{85E669CB-F
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
NSExt.sln.DotSettings = NSExt.sln.DotSettings
NSExt.sln.DotSettings.user = NSExt.sln.DotSettings.user
README.md = README.md
README.zh-CN.md = README.zh-CN.md
stylecop.json = stylecop.json
StyleCopAnalyzers.ruleset = StyleCopAnalyzers.ruleset
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NSExt.Tests", "src\NSExt.Tests\NSExt.Tests.csproj", "{557FBEF6-E6D5-4531-86DF-D772A10E2261}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NSExt", "src\NSExt\NSExt.csproj", "{BA0982BE-6E57-4AAF-9778-F9B2EB46F505}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -38,9 +41,13 @@ Global
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
{557FBEF6-E6D5-4531-86DF-D772A10E2261}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{557FBEF6-E6D5-4531-86DF-D772A10E2261}.Debug|Any CPU.Build.0 = Debug|Any CPU
{557FBEF6-E6D5-4531-86DF-D772A10E2261}.Release|Any CPU.ActiveCfg = Release|Any CPU
{557FBEF6-E6D5-4531-86DF-D772A10E2261}.Release|Any CPU.Build.0 = Release|Any CPU
{BA0982BE-6E57-4AAF-9778-F9B2EB46F505}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{BA0982BE-6E57-4AAF-9778-F9B2EB46F505}.Debug|Any CPU.Build.0 = Debug|Any CPU
{BA0982BE-6E57-4AAF-9778-F9B2EB46F505}.Release|Any CPU.ActiveCfg = Release|Any CPU
{BA0982BE-6E57-4AAF-9778-F9B2EB46F505}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
EndGlobal

View File

@ -1,8 +1,7 @@
<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/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpKeepExistingMigration/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpPlaceEmbeddedOnSameLineMigration/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpUseContinuousIndentInsideBracesMigration/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EMigrateBlankLinesAroundFieldToBlankLinesAroundProperty/@EntryIndexedValue">True</s:Boolean>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=UnusedAutoPropertyAccessor_002EGlobal/@EntryIndexedValue">DO_NOT_SHOW</s:String>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=UnusedAutoPropertyAccessor_002ELocal/@EntryIndexedValue">DO_NOT_SHOW</s:String>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_FIELD_ATTRIBUTE_ON_SAME_LINE_EX/@EntryValue">NEVER</s:String>
<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>
@ -16,7 +15,6 @@
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateConstants/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="_" Suffix="" Style="AA_BB" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateStaticReadonly/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="_" Suffix="" Style="aaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=StaticReadonly/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/CSharpFileLayoutPatterns/Pattern/@EntryValue">&lt;?xml version="1.0" encoding="utf-16"?&gt;
&lt;Patterns xmlns="urn:schemas-jetbrains-com:member-reordering-patterns"&gt;
&lt;TypePattern&gt;

View File

@ -13,7 +13,7 @@
<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="SA1005" Action="Warning"/> <!-- 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 -->
@ -73,7 +73,7 @@
<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="SA1134" Action="Warning"/> <!-- 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 -->
@ -115,7 +115,7 @@
<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="SA1313" Action="Warning"/> <!-- 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 -->
@ -125,12 +125,12 @@
<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="SA1402" Action="None"/> <!-- 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="SA1407" Action="Warning"/> <!-- 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 -->
@ -143,7 +143,7 @@
<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="SA1503" Action="Warning"/> <!-- 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 -->
@ -173,7 +173,7 @@
<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="SA1609" Action="None"/> <!-- 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 -->
@ -187,13 +187,13 @@
<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="SA1623" Action="None"/> <!-- 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="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 -->

View File

@ -1,6 +1,6 @@
var target = Argument("target", "Default");
var configuration = Argument("configuration", "Release");
var pkgOutPath = $"./dist/NSExt/pkg/{configuration}";
var framework = Argument("framework", "net7.0");
////////////////////////////////////////////////////////////////
// Tasks
@ -8,123 +8,108 @@ var pkgOutPath = $"./dist/NSExt/pkg/{configuration}";
Task("Clean")
.Does(context =>
{
context.CleanDirectory(pkgOutPath);
context.CleanDirectory("./dist");
});
Task("Build")
.IsDependentOn("Clean")
.Does(context =>
{
DotNetBuild("./NSExt.sln", new DotNetBuildSettings {
DotNetPublish("./src/NSExt/NSExt.csproj", new DotNetPublishSettings {
Configuration = configuration,
NoIncremental = context.HasArgument("rebuild"),
MSBuildSettings = new DotNetMSBuildSettings()
.TreatAllWarningsAs(MSBuildTreatAllWarningsAs.Error)
Framework = framework,
});
});
Task("Test")
.IsDependentOn("Build")
.Does(context =>
{
DotNetTest("./test/Spectre.Console.Tests/Spectre.Console.Tests.csproj", new DotNetTestSettings {
Configuration = configuration,
NoRestore = true,
NoBuild = true,
});
// 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,
// });
// });
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-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 =>
//.WithCriteria(ctx => BuildSystem.IsRunningOnGitHubActions, "Not running on GitHub Actions")
.IsDependentOn("Build")
.Does(context =>
{
var apiKey = Argument<string>("nuget-key", null);
if(string.IsNullOrWhiteSpace(apiKey)) {
throw new CakeException("No NuGet API key was provided.");
}
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
});
}
// Publish to GitHub Packages
foreach(var file in context.GetFiles("./dist/NSExt/bin/Release/*.*"))
{
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-GitHub")
.IsDependentOn("Publish-NuGet");
Task("Default")
.IsDependentOn("Package");
.IsDependentOn("Build");
////////////////////////////////////////////////////////////////
// Execution

View File

@ -1 +1,2 @@
git reset --hard | git clean -d -fx .
git reset --hard
git clean -d -fx .

BIN
key.snk Normal file

Binary file not shown.

BIN
logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

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

View File

@ -1,47 +0,0 @@
namespace NSExt.Extensions;
/// <summary>
/// DbCommandExtensions
/// </summary>
public static class DbCommandExtensions
{
/// <summary>
/// 格式化参数拼接成完整的SQL语句
/// </summary>
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--) {
sql = me.Parameters[i].DbType switch {
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, CultureInfo.InvariantCulture) ? "1" : "0")
, DbType.Binary => throw new NotImplementedException()
, DbType.Byte => throw new NotImplementedException()
, DbType.Currency => throw new NotImplementedException()
, DbType.Decimal => throw new NotImplementedException()
, DbType.Double => throw new NotImplementedException()
, DbType.Int16 => throw new NotImplementedException()
, DbType.Int32 => throw new NotImplementedException()
, DbType.Int64 => throw new NotImplementedException()
, DbType.Object => throw new NotImplementedException()
, DbType.SByte => throw new NotImplementedException()
, DbType.Single => throw new NotImplementedException()
, DbType.UInt16 => throw new NotImplementedException()
, DbType.UInt32 => throw new NotImplementedException()
, DbType.UInt64 => throw new NotImplementedException()
, DbType.Xml => throw new NotImplementedException()
, _ => sql.Replace(me.Parameters[i].ParameterName, me.Parameters[i].Value?.ToString())
};
}
return sql;
}
}

View File

@ -1,20 +0,0 @@
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 attrs = (DescriptionAttribute[])fi!.GetCustomAttributes(typeof(DescriptionAttribute), false);
return (attrs.Length != 0 ? attrs[0].Description : Enum.GetName(t, e)) ?? string.Empty;
}
}

View File

@ -1,29 +0,0 @@
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 |
JsonNumberHandling.WriteAsString
, PropertyNameCaseInsensitive = true
};
}
}

View File

@ -1,88 +0,0 @@
// 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);
}
}

View File

@ -1,21 +0,0 @@
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)
{
return JsonSerializer.Serialize(
me, new JsonSerializerOptions { WriteIndented = format, PropertyNamingPolicy = JsonNamingPolicy.CamelCase });
}
}

View File

@ -0,0 +1,9 @@
<Project Sdk="Microsoft.NET.Sdk">
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.5.0" />
<PackageReference Include="xunit" Version="2.4.2" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\NSExt\NSExt.csproj" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,41 @@
using NSExt.Attributes;
using NSExt.Extensions;
using Xunit;
using Xunit.Abstractions;
namespace NSExt.Tests;
/// <summary>
/// 测试用例
/// </summary>
public class TestCase
{
private readonly ITestOutputHelper _testOutputHelper;
public TestCase(ITestOutputHelper testOutputHelper)
{
_testOutputHelper = testOutputHelper;
}
public enum MyEnum1
{
[ResourceDescription<TestCase>(nameof(Description))]
Online = 1
, Offline = 2
}
public static string Description { get; set; } = "123";
/// <summary>
/// Case1
/// </summary>
[Fact]
public void Case1()
{
var test = MyEnum1.Online.ResDesc<TestCase>();
_testOutputHelper.WriteLine(test);
Assert.True(test is not null);
}
}

View File

@ -1,17 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net7.0</TargetFrameworks>
<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>

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

View File

@ -0,0 +1,26 @@
namespace NSExt.Attributes;
/// <summary>
/// 本地化资源描述特性
/// </summary>
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Class | AttributeTargets.Field)]
public class ResourceDescriptionAttribute<T> : Attribute
{
/// <summary>
/// Initializes a new instance of the <see cref="ResourceDescriptionAttribute{T}" /> class.
/// </summary>
public ResourceDescriptionAttribute(string resourceName)
{
ResourceName = resourceName;
}
/// <summary>
/// 资源名称
/// </summary>
public string ResourceName { get; set; }
/// <summary>
/// 资源对象
/// </summary>
public T ResourceObject { get; set; }
}

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

View File

@ -8,7 +8,7 @@ public static class ByteExtensions
/// <summary>
/// base64编码
/// </summary>
/// <param name="me">待编码的字节数组</param>
/// <param name="me">me</param>
/// <returns>编码后的base64字符串</returns>
public static string Base64(this byte[] me)
{
@ -18,7 +18,7 @@ public static class ByteExtensions
/// <summary>
/// 将字节数组解码成字符串
/// </summary>
/// <param name="me">字节数组</param>
/// <param name="me">me</param>
/// <param name="e">字符串使用的编码方式</param>
/// <returns>解码后的原始字符串</returns>
public static string HexDe(this byte[] me, Encoding e)
@ -29,7 +29,7 @@ public static class ByteExtensions
/// <summary>
/// 将字节数组解码成字符串
/// </summary>
/// <param name="me">字节数组</param>
/// <param name="me">me</param>
/// <returns>解码后的原始字符串</returns>
public static string HexDe(this byte[] me)
{
@ -43,8 +43,8 @@ public static class ByteExtensions
/// <param name="upperCase">是否大写</param>
/// <param name="splitShar">字节间分隔符</param>
/// <param name="splitInterval">分隔符跳跃字节数</param>
public static string String(this IEnumerable<byte> me, bool upperCase = true, string splitShar = ""
, int splitInterval = 1)
public static string Str(this IEnumerable<byte> me, bool upperCase = true, string splitShar = ""
, int splitInterval = 1)
{
var sb = new StringBuilder();
var i = 0;

View File

@ -13,7 +13,7 @@ public static class DateTimeExtensions
/// <summary>
/// 将一个过去时间对象与当前时间相减转换成“xx以前”的字符串, 如2秒以前, 3天以前
/// </summary>
/// <param name="me">时间对象</param>
/// <param name="me">me</param>
/// <returns>字符串</returns>
public static string TimeAgo(this DateTime me)
{
@ -26,7 +26,7 @@ public static class DateTimeExtensions
/// <summary>
/// 指定时间的世界协调时的unix时间戳形式
/// </summary>
/// <param name="me">指定时间</param>
/// <param name="me">me</param>
/// <returns>unix时间戳</returns>
public static long TimeUnixUtc(this DateTime me)
{

View File

@ -0,0 +1,34 @@
namespace NSExt.Extensions;
/// <summary>
/// DbCommandExtensions
/// </summary>
public static class DbCommandExtensions
{
/// <summary>
/// 格式化参数拼接成完整的SQL语句
/// </summary>
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--) {
#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, CultureInfo.InvariantCulture) ? "1" : "0")
, _ => sql.Replace(me.Parameters[i].ParameterName, me.Parameters[i].Value?.ToString())
};
}
return sql;
}
}

View File

@ -8,7 +8,7 @@ public static class DecimalExtensions
/// <summary>
/// 四舍五入后的近似值
/// </summary>
/// <param name="me">数字</param>
/// <param name="me">me</param>
/// <param name="place">小数点位数</param>
/// <returns>处理后的值</returns>
public static decimal Round(this decimal me, int place)

View File

@ -0,0 +1,61 @@
using System.ComponentModel.DataAnnotations;
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>
[Obsolete(nameof(ResDesc))]
public static string Desc(this Enum e)
{
var typeOfEnum = e.GetType();
var typeOfField = typeOfEnum.GetField(Enum.GetName(typeOfEnum, e)!);
var descAttr = typeOfField!.GetCustomAttribute<DescriptionAttribute>(true);
if (descAttr is null) {
return Enum.GetName(typeOfEnum, e);
}
var str = descAttr.Description;
var locAttr = typeOfField!.GetCustomAttribute<LocalizationAttribute>(true);
return locAttr is null ? str : locAttr.ResourceClass.GetProperty(str)?.GetValue(default) as string ?? str;
}
/// <summary>
/// 通过类泛型类型获取特性
/// </summary>
public static T GetAttributeOfType<T>(this Enum me)
where T : Attribute
{
return me.GetType().GetMember(me.ToString()).First().GetCustomAttributes<T>(false).FirstOrDefault();
}
/// <summary>
/// 获取显示特性
/// </summary>
public static DisplayAttribute GetDisplay(this Enum me)
{
return me.GetAttributeOfType<DisplayAttribute>();
}
/// <summary>
/// 获取枚举的本地化资源描述
/// </summary>
public static string ResDesc<T>(this Enum e)
{
var typeOfEnum = e.GetType();
var typeOfField = typeOfEnum.GetField(Enum.GetName(typeOfEnum, e)!);
var resDescAttr = typeOfField!.GetCustomAttribute<ResourceDescriptionAttribute<T>>(true);
return resDescAttr is null
? Enum.GetName(typeOfEnum, e)
: typeof(T).GetProperty(resDescAttr.ResourceName)?.GetValue(default) as string;
}
}

View File

@ -17,7 +17,7 @@ public static class EnumerableExtensions
/// 判断对象是否为null或不存在子元素如果为集合对象
/// </summary>
/// <typeparam name="T">对象类型</typeparam>
/// <param name="me">指定对象</param>
/// <param name="me">me</param>
/// <returns>空则返回true</returns>
public static bool NullOrEmpty<T>(this IEnumerable<T> me)
{

View File

@ -9,7 +9,7 @@ public static class GenericExtensions
/// 从指定的对象拷贝属性
/// </summary>
/// <typeparam name="T">对象类型</typeparam>
/// <param name="me">拷贝目标</param>
/// <param name="me">me</param>
/// <param name="copyObj">拷贝来源</param>
/// <param name="propNameList">需要处理的属性名</param>
/// <param name="isIncludeOrExclude">True包含false排除</param>

View File

@ -17,7 +17,7 @@ public static class IntExtensions
/// <summary>
/// 生成随机数
/// </summary>
/// <param name="me">大于等于[0],小于[1]</param>
/// <param name="me">me</param>
public static int Rand(this int[] me)
{
return new Random(Guid.NewGuid().GetHashCode()).Next(me[0], me[1]);

View File

@ -0,0 +1,83 @@
// ReSharper disable TemplateIsNotCompileTimeConstantProblem
namespace NSExt.Extensions;
/// <summary>
/// LoggerExtensions
/// </summary>
public static class LoggerExtensions
{
private const string _MESSAGE_S_THREADID_CALLERNAME_CALLERFILEPATH_CALLERLINENUMBER
= "{Message} <s:{CallerName}@{CallerFilePath}:{CallerLineNumber}>";
private static readonly Action<ILogger, string, string, string, string, Exception> _logDebug
= LoggerMessage.Define<string, string, string, string>(LogLevel.Debug, default
, _MESSAGE_S_THREADID_CALLERNAME_CALLERFILEPATH_CALLERLINENUMBER);
private static readonly Action<ILogger, string, string, string, string, Exception> _logError
= LoggerMessage.Define<string, string, string, string>(LogLevel.Error, default
, _MESSAGE_S_THREADID_CALLERNAME_CALLERFILEPATH_CALLERLINENUMBER);
private static readonly Action<ILogger, string, string, string, string, Exception> _logFatal
= LoggerMessage.Define<string, string, string, string>(LogLevel.Critical, default
, _MESSAGE_S_THREADID_CALLERNAME_CALLERFILEPATH_CALLERLINENUMBER);
private static readonly Action<ILogger, string, string, string, string, Exception> _logInfo
= LoggerMessage.Define<string, string, string, string>(LogLevel.Information, default
, _MESSAGE_S_THREADID_CALLERNAME_CALLERFILEPATH_CALLERLINENUMBER);
private static readonly Action<ILogger, string, string, string, string, Exception> _logWarn
= LoggerMessage.Define<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(), 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(), 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(), 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(), 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(), callerName, Path.GetFileName(callerFilePath)
, callerLineNumber.ToString(CultureInfo.InvariantCulture), null);
}
}

View File

@ -0,0 +1,30 @@
using System.Text.Json;
namespace NSExt.Extensions;
/// <summary>
/// ObjectExtensions
/// </summary>
public static class ObjectExtensions
{
/// <summary>
/// 将一个对象序列化成json文本
/// </summary>
/// <param name="me">me</param>
/// <returns>json文本</returns>
public static string Json(this object me)
{
return JsonSerializer.Serialize(me);
}
/// <summary>
/// 将一个对象序列化成json文本
/// </summary>
/// <param name="me">me</param>
/// <param name="options">序列化选项</param>
/// <returns>json文本</returns>
public static string Json(this object me, JsonSerializerOptions options)
{
return JsonSerializer.Serialize(me, options);
}
}

View File

@ -4,21 +4,20 @@
#pragma warning disable CA1720
using System.Security.Cryptography;
using System.Text.Json;
using NSExt.Constant;
namespace NSExt.Extensions;
/// <summary>
/// StringExtensions
/// </summary>
public static partial class StringExtensions
#pragma warning disable CodeLinesAnalyzer
public static class StringExtensions
{
private static readonly JsonSerializerOptions _defaultJsonSerializerOptions
= default(JsonSerializerOptions).NewJsonSerializerOptions();
/// <summary>
/// aes加密
/// </summary>
/// <param name="me">要加密的串</param>
/// <param name="me">me</param>
/// <param name="key">密钥</param>
public static string Aes(this string me, string key)
{
@ -35,7 +34,7 @@ public static partial class StringExtensions
/// <summary>
/// aes解密
/// </summary>
/// <param name="me">要加密的串</param>
/// <param name="me">me</param>
/// <param name="key">密钥</param>
public static string AesDe(this string me, string key)
{
@ -52,7 +51,7 @@ public static partial class StringExtensions
/// <summary>
/// base64编码
/// </summary>
/// <param name="me">待base64编码的字符串</param>
/// <param name="me">me</param>
/// <param name="e">字符串的编码方式</param>
/// <returns>编码后的base64字符串</returns>
public static string Base64(this string me, Encoding e)
@ -63,7 +62,7 @@ public static partial class StringExtensions
/// <summary>
/// base64解码
/// </summary>
/// <param name="me">待解码的字符串</param>
/// <param name="me">me</param>
/// <returns>解码后的原始字节数组</returns>
public static byte[] Base64De(this string me)
{
@ -73,7 +72,7 @@ public static partial class StringExtensions
/// <summary>
/// base64解码
/// </summary>
/// <param name="me">待解码的字符串</param>
/// <param name="me">me</param>
/// <param name="e">字符串的编码方式</param>
/// <returns>解码后的原始字符串</returns>
public static string Base64De(this string me, Encoding e)
@ -102,7 +101,7 @@ public static partial class StringExtensions
/// <summary>
/// 将字符串转换成日期对象
/// </summary>
/// <param name="me">待转换字符串</param>
/// <param name="me">me</param>
/// <returns>转换后的日期对象</returns>
public static DateTime DateTime(this string me)
{
@ -112,7 +111,7 @@ public static partial class StringExtensions
/// <summary>
/// 将字符串转换成日期对象
/// </summary>
/// <param name="me">待转换字符串</param>
/// <param name="me">me</param>
/// <param name="format">日期格式</param>
/// <returns>转换后的日期对象</returns>
public static DateTime DateTimeExact(this string me, string format)
@ -123,7 +122,7 @@ public static partial class StringExtensions
/// <summary>
/// 将字符串转换成日期对象
/// </summary>
/// <param name="me">待转换字符串</param>
/// <param name="me">me</param>
/// <param name="format">日期格式</param>
/// <param name="def">转换失败时返回的日期对象</param>
/// <returns>转换后的日期对象</returns>
@ -137,7 +136,7 @@ public static partial class StringExtensions
/// <summary>
/// 将字符串转换成日期对象
/// </summary>
/// <param name="me">待转换字符串</param>
/// <param name="me">me</param>
/// <param name="def">转换失败时返回的日期对象</param>
/// <returns>转换后的日期对象</returns>
public static DateTime DateTimeTry(this string me, DateTime def)
@ -148,7 +147,7 @@ public static partial class StringExtensions
/// <summary>
/// string to decimal
/// </summary>
/// <param name="me">string</param>
/// <param name="me">me</param>
/// <returns>decimal</returns>
public static decimal Dec(this string me)
{
@ -158,7 +157,7 @@ public static partial class StringExtensions
/// <summary>
/// 尝试将字符串转为decimal
/// </summary>
/// <param name="me">字符串</param>
/// <param name="me">me</param>
/// <param name="def">转换失败后返回的默认值</param>
/// <returns>转换后的decimal</returns>
public static decimal DecTry(this string me, decimal def)
@ -169,7 +168,7 @@ public static partial class StringExtensions
/// <summary>
/// string to double
/// </summary>
/// <param name="me">string</param>
/// <param name="me">me</param>
/// <returns>Int32</returns>
public static double Double(this string me)
{
@ -197,7 +196,7 @@ public static partial class StringExtensions
/// <summary>
/// string to float
/// </summary>
/// <param name="me">string</param>
/// <param name="me">me</param>
/// <returns>Int32</returns>
public static float Float(this string me)
{
@ -207,7 +206,7 @@ public static partial class StringExtensions
/// <summary>
/// 将字符串转为guid
/// </summary>
/// <param name="me">字符串</param>
/// <param name="me">me</param>
public static Guid Guid(this string me)
{
return System.Guid.Parse(me);
@ -216,7 +215,7 @@ public static partial class StringExtensions
/// <summary>
/// 将字符串转换成guid
/// </summary>
/// <param name="me">字符串</param>
/// <param name="me">me</param>
/// <param name="def">转换失败的返回值</param>
public static Guid Guid(this string me, Guid def)
{
@ -226,7 +225,7 @@ public static partial class StringExtensions
/// <summary>
/// 将字符串转换成字节数组形式
/// </summary>
/// <param name="me">字符串</param>
/// <param name="me">me</param>
/// <param name="e">字符串使用的编码</param>
/// <returns>字节数组</returns>
public static byte[] Hex(this string me, Encoding e)
@ -237,7 +236,7 @@ public static partial class StringExtensions
/// <summary>
/// 将字符串转换成字节数组形式
/// </summary>
/// <param name="me">字符串</param>
/// <param name="me">me</param>
/// <returns>字节数组</returns>
public static byte[] Hex(this string me)
{
@ -271,7 +270,7 @@ public static partial class StringExtensions
/// <summary>
/// 解码html编码
/// </summary>
/// <param name="me">html编码后的字符串</param>
/// <param name="me">me</param>
/// <returns>解码后的原始字符串</returns>
public static string HtmlDe(this string me)
{
@ -281,7 +280,7 @@ public static partial class StringExtensions
/// <summary>
/// string to Int32
/// </summary>
/// <param name="me">string</param>
/// <param name="me">me</param>
/// <returns>Int32</returns>
public static int Int32(this string me)
{
@ -291,7 +290,7 @@ public static partial class StringExtensions
/// <summary>
/// 尝试将字符串转为int32
/// </summary>
/// <param name="me">字符串</param>
/// <param name="me">me</param>
/// <param name="def">转换失败后返回的默认值</param>
/// <returns>转换后的int32</returns>
public static int Int32Try(this string me, int def)
@ -302,7 +301,7 @@ public static partial class StringExtensions
/// <summary>
/// string to Int64
/// </summary>
/// <param name="me">string</param>
/// <param name="me">me</param>
/// <returns>Int64</returns>
public static long Int64(this string me)
{
@ -312,7 +311,7 @@ public static partial class StringExtensions
/// <summary>
/// 尝试将字符串转为int64
/// </summary>
/// <param name="me">字符串</param>
/// <param name="me">me</param>
/// <param name="def">转换失败后返回的默认值</param>
/// <returns>转换后的int64</returns>
public static long Int64Try(this string me, long def)
@ -331,7 +330,7 @@ public static partial class StringExtensions
/// <summary>
/// 是否base64字符串
/// </summary>
/// <param name="me">字符串</param>
/// <param name="me">me</param>
public static bool IsBase64String(this string me)
{
// 一个合法的Base64有着以下特征
@ -365,17 +364,17 @@ public static partial class StringExtensions
/// <summary>
/// 对一个手机号进行掩码处理
/// </summary>
/// <param name="me">手机号</param>
/// <param name="me">me</param>
/// <returns>掩码后的手机号</returns>
public static string MaskMobile(this string me)
{
return RegexMobile().Replace(me, "$1****$2");
return Regexes.RegexMobile.Replace(me, "$1****$2");
}
/// <summary>
/// 对一个字符串进行md5hash运算
/// </summary>
/// <param name="me">字符串</param>
/// <param name="me">me</param>
/// <param name="e">字符串使用的编码</param>
/// <returns>hash摘要的16进制文本形式无连字符小写</returns>
public static string Md5(this string me, Encoding e)
@ -388,7 +387,7 @@ public static partial class StringExtensions
/// <summary>
/// 判断字符串是否为null或不存在子元素如果为集合对象如果为空返回指定的默认值否则返回字符串本身
/// </summary>
/// <param name="me">指定字符串</param>
/// <param name="me">me</param>
/// <param name="defVal">指定的默认值</param>
/// <returns>如果为空,返回指定的默认值,否则返回字符串本身</returns>
public static string NullOrEmpty(this string me, string defVal)
@ -407,30 +406,30 @@ public static partial class StringExtensions
/// <summary>
/// 反序列化一个文件获得指定类型的数据对象
/// </summary>
/// <param name="me">等待反序列化的json文本</param>
/// <param name="me">me</param>
/// <param name="options">序列化选项</param>
/// <returns>反序列化后生成的对象</returns>
public static T Object<T>(this string me, JsonSerializerOptions options = null)
{
return JsonSerializer.Deserialize<T>(me, options ?? _defaultJsonSerializerOptions);
return JsonSerializer.Deserialize<T>(me, options);
}
/// <summary>
/// 反序列化一个文件获得指定类型的数据对象
/// </summary>
/// <param name="me">等待反序列化的json文本</param>
/// <param name="me">me</param>
/// <param name="type">实际类型</param>
/// <param name="options">序列化选项</param>
/// <returns>反序列化后生成的对象</returns>
public static object Object(this string me, Type type, JsonSerializerOptions options = null)
{
return JsonSerializer.Deserialize(me, type, options ?? _defaultJsonSerializerOptions);
return JsonSerializer.Deserialize(me, type, options);
}
/// <summary>
/// 生成密码
/// </summary>
/// <param name="me">密码原文</param>
/// <param name="me">me</param>
/// <returns>密文</returns>
public static string Pwd(this string me)
{
@ -440,11 +439,11 @@ public static partial class StringExtensions
/// <summary>
/// 移除字符串中的html标签
/// </summary>
/// <param name="me">字符串</param>
/// <param name="me">me</param>
/// <returns>处理之后的字符串</returns>
public static string RemoveHtmlTag(this string me)
{
return RegexHtmlTag().Replace(me, string.Empty);
return Regexes.RegexHtmlTag.Replace(me, string.Empty);
}
/// <summary>
@ -458,7 +457,7 @@ public static partial class StringExtensions
/// <summary>
/// 对一个字符串进行sha1 hash运算
/// </summary>
/// <param name="me">字符串</param>
/// <param name="me">me</param>
/// <param name="e">字符串使用的编码</param>
/// <returns>hash摘要的16进制文本形式无连字符小写</returns>
public static string Sha1(this string me, Encoding e)
@ -473,7 +472,7 @@ public static partial class StringExtensions
/// </summary>
public static string Snakecase(this string me)
{
return RegexUpperCaseLetter().Replace(me, "-$1").ToLower(CultureInfo.InvariantCulture).TrimStart('-');
return Regexes.RegexUpLetter.Replace(me, "-$1").ToLower(CultureInfo.InvariantCulture).TrimStart('-');
}
/// <summary>
@ -496,6 +495,25 @@ public static partial class StringExtensions
return $"<pre>{me}</pre>";
}
/// <summary>
/// 首字母小写
/// </summary>
public static string ToLowerCamelCase(this string me)
{
return string.IsNullOrWhiteSpace(me)
? me
: string.Concat( //
me[0].ToString(CultureInfo.InvariantCulture).ToLowerInvariant(), me.AsSpan(1));
}
/// <summary>
/// 首字母大写
/// </summary>
public static string ToUpperCamelCase(this string me)
{
return string.IsNullOrWhiteSpace(me) ? me : string.Concat(me[0].ToString().ToUpperInvariant(), me.AsSpan(1));
}
/// <summary>
/// 将连续多个空格替换成一个空格
/// </summary>
@ -513,14 +531,14 @@ public static partial class StringExtensions
public static string UnicodeDe(this string me)
{
const string replacement = "&#x$1;";
return me.Contains(@"\u") ? RegexBacksLantUnicode().Replace(me, replacement).HtmlDe() :
me.Contains(@"%u") ? RegexPercentUnicode().Replace(me, replacement).HtmlDe() : me.HtmlDe();
return me.Contains(@"\u") ? Regexes.RegexBacksLantUnicode.Replace(me, replacement).HtmlDe() :
me.Contains(@"%u") ? Regexes.RegexPercentUnicode.Replace(me, replacement).HtmlDe() : me.HtmlDe();
}
/// <summary>
/// url编码
/// </summary>
/// <param name="me">字符串</param>
/// <param name="me">me</param>
/// <returns>url编码后的字符串</returns>
public static string Url(this string me)
{
@ -530,7 +548,7 @@ public static partial class StringExtensions
/// <summary>
/// 解码url编码
/// </summary>
/// <param name="me">url编码后的字符串</param>
/// <param name="me">me</param>
/// <returns>解码后的原始字符串</returns>
public static string UrlDe(this string me)
{
@ -540,7 +558,7 @@ public static partial class StringExtensions
/// <summary>
/// MD5 hmac编码
/// </summary>
/// <param name="me">字符串</param>
/// <param name="me">me</param>
/// <param name="key">密钥</param>
/// <param name="e">字符串使用的编码</param>
/// <returns>hash摘要的16进制文本形式无连字符小写</returns>
@ -551,19 +569,5 @@ public static partial class StringExtensions
.Replace("-", string.Empty)
.ToLower(CultureInfo.CurrentCulture);
}
[GeneratedRegex("\\\\u([a-fA-F0-9]{4})")]
private static partial Regex RegexBacksLantUnicode();
[GeneratedRegex("<[^>]*>")]
private static partial Regex RegexHtmlTag();
[GeneratedRegex("^(\\d{3})\\d{4}(\\d{4})$")]
private static partial Regex RegexMobile();
[GeneratedRegex("\\\\u([a-fA-F0-9]{4})")]
private static partial Regex RegexPercentUnicode();
[GeneratedRegex("([A-Z])")]
private static partial Regex RegexUpperCaseLetter();
}
}
#pragma warning restore CodeLinesAnalyzer

35
src/NSExt/NSExt.csproj Normal file
View File

@ -0,0 +1,35 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="../../CodeQuality.props" />
<PropertyGroup>
<AssemblyOriginatorKeyFile>../../key.snk</AssemblyOriginatorKeyFile>
<DelaySign>false</DelaySign>
<Description>A .NET extension function library</Description>
<EmbedAllSources>true</EmbedAllSources>
<EmbedUntrackedSource>true</EmbedUntrackedSource>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<IncludeSymbols>true</IncludeSymbols>
<IsPackable>true</IsPackable>
<PackageIcon>logo.png</PackageIcon>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
<PackageProjectUrl>https://github.com/nsnail/ns-ext.git</PackageProjectUrl>
<PackageTags>extensions</PackageTags>
<Product>NSExt</Product>
<PublishRepositoryUrl>true</PublishRepositoryUrl>
<RepositoryType>git</RepositoryType>
<RepositoryUrl>https://github.com/nsnail/ns-ext.git</RepositoryUrl>
<SignAssembly>true</SignAssembly>
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
<Title>$(AssemblyName)</Title>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Logging" Version="7.0.0" />
<PackageReference Include="MinVer" Version="4.3.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>
<ItemGroup>
<None Include="../../logo.png" Pack="true" PackagePath="" />
</ItemGroup>
</Project>