<refactor>

This commit is contained in:
nsnail 2022-12-15 14:12:34 +08:00
parent 9ae1046dca
commit 3095dc783e
33 changed files with 644 additions and 259 deletions

View File

@ -1,12 +1,28 @@
root = true
[*]
indent_style = space
indent_size = 4
end_of_line = lf
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
@ -23,23 +39,27 @@ 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_foreach_stmt = 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

17
CodeQuality.props Normal file
View 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>

View File

@ -1,9 +1,11 @@
<Project>
<PropertyGroup>
<ImplicitUsings>enable</ImplicitUsings>
<BaseOutputPath>../build/$(MSBuildProjectName)/bin</BaseOutputPath>
<BaseIntermediateOutputPath>../build/$(MSBuildProjectName)/obj</BaseIntermediateOutputPath>
<MSBuildProjectExtensionsPath>$(BaseIntermediateOutputPath)</MSBuildProjectExtensionsPath>
<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>

45
ImageOptimize.csx Normal file
View 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}");
});

View File

@ -11,17 +11,22 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "meta", "meta", "{85E669CB-F
.gitattributes = .gitattributes
.gitignore = .gitignore
.tgitconfig = .tgitconfig
add-meta-files-to-sln.csx = add-meta-files-to-sln.csx
code-cleanup-on-save.csx = code-cleanup-on-save.csx
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.ps1 = git-clean.ps1
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

View File

@ -1,6 +1,18 @@
<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">
<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">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="AA_BB" /&gt;</s:String>
<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;
@ -8,43 +20,38 @@
&lt;Entry.SortBy&gt;
&lt;Kind&gt;
&lt;Kind.Order&gt;
&lt;DeclarationKind&gt;Interface&lt;/DeclarationKind&gt;
&lt;DeclarationKind&gt;Class&lt;/DeclarationKind&gt;
&lt;DeclarationKind&gt;Record&lt;/DeclarationKind&gt;
&lt;DeclarationKind&gt;Enum&lt;/DeclarationKind&gt;
&lt;DeclarationKind&gt;Struct&lt;/DeclarationKind&gt;
&lt;DeclarationKind&gt;Delegate&lt;/DeclarationKind&gt;
&lt;DeclarationKind&gt;Event&lt;/DeclarationKind&gt;
&lt;DeclarationKind&gt;Constant&lt;/DeclarationKind&gt;
&lt;DeclarationKind&gt;Field&lt;/DeclarationKind&gt;
&lt;DeclarationKind&gt;Property&lt;/DeclarationKind&gt;
&lt;DeclarationKind&gt;Constructor&lt;/DeclarationKind&gt;
&lt;DeclarationKind&gt;Destructor&lt;/DeclarationKind&gt;
&lt;DeclarationKind&gt;Delegate&lt;/DeclarationKind&gt;
&lt;DeclarationKind&gt;Event&lt;/DeclarationKind&gt;
&lt;DeclarationKind&gt;Enum&lt;/DeclarationKind&gt;
&lt;DeclarationKind&gt;Interface&lt;/DeclarationKind&gt;
&lt;DeclarationKind&gt;Property&lt;/DeclarationKind&gt;
&lt;DeclarationKind&gt;Indexer&lt;/DeclarationKind&gt;
&lt;DeclarationKind&gt;Method&lt;/DeclarationKind&gt;
&lt;DeclarationKind&gt;Struct&lt;/DeclarationKind&gt;
&lt;DeclarationKind&gt;Record&lt;/DeclarationKind&gt;
&lt;DeclarationKind&gt;Class&lt;/DeclarationKind&gt;
&lt;/Kind.Order&gt;
&lt;/Kind&gt;
&lt;Access&gt;
&lt;Access.Order&gt;
&lt;AccessModifier&gt;Private&lt;/AccessModifier&gt;
&lt;AccessModifier&gt;PrivateProtected&lt;/AccessModifier&gt;
&lt;AccessModifier&gt;Protected&lt;/AccessModifier&gt;
&lt;AccessModifier&gt;ProtectedInternal&lt;/AccessModifier&gt;
&lt;AccessModifier&gt;Internal&lt;/AccessModifier&gt;
&lt;AccessModifier&gt;Public&lt;/AccessModifier&gt;
&lt;AccessModifier&gt;Internal&lt;/AccessModifier&gt;
&lt;AccessModifier&gt;ProtectedInternal&lt;/AccessModifier&gt;
&lt;AccessModifier&gt;Protected&lt;/AccessModifier&gt;
&lt;AccessModifier&gt;PrivateProtected&lt;/AccessModifier&gt;
&lt;AccessModifier&gt;Private&lt;/AccessModifier&gt;
&lt;/Access.Order&gt;
&lt;/Access&gt;
&lt;Static /&gt;
&lt;Readonly /&gt;
&lt;Name /&gt;
&lt;/Entry.SortBy&gt;
&lt;/Entry&gt;
&lt;/TypePattern&gt;
&lt;/Patterns&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=Constants/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="AA_BB" /&gt;</s:String>
<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: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>

221
StyleCopAnalyzers.ruleset Normal file
View 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>

View File

@ -1,6 +1,6 @@
var target = Argument("target", "Default");
var configuration = Argument("configuration", "Release");
var pkgOutPath = $"./build/NSExt/pkg/{configuration}";
var pkgOutPath = $"./dist/NSExt/pkg/{configuration}";
////////////////////////////////////////////////////////////////
// Tasks
@ -13,7 +13,7 @@ Task("Clean")
Task("Build")
.IsDependentOn("Clean")
.Does(context =>
.Does(context =>
{
DotNetBuild("./NSExt.sln", new DotNetBuildSettings {
Configuration = configuration,
@ -26,7 +26,7 @@ Task("Build")
Task("Test")
.IsDependentOn("Build")
.Does(context =>
.Does(context =>
{
DotNetTest("./test/Spectre.Console.Tests/Spectre.Console.Tests.csproj", new DotNetTestSettings {
Configuration = configuration,
@ -49,7 +49,7 @@ Task("Test")
Task("Package")
.IsDependentOn("Build")
.Does(context =>
.Does(context =>
{
context.DotNetPack("./NSExt.sln", new DotNetPackSettings {
Configuration = configuration,
@ -64,7 +64,7 @@ Task("Package")
Task("Publish-GitHub")
.WithCriteria(ctx => BuildSystem.IsRunningOnGitHubActions, "Not running on GitHub Actions")
.IsDependentOn("Package")
.Does(context =>
.Does(context =>
{
var apiKey = Argument<string>("github-key", null);
if(string.IsNullOrWhiteSpace(apiKey)) {
@ -73,10 +73,10 @@ Task("Publish-GitHub")
// Publish to GitHub Packages
var exitCode = 0;
foreach(var file in context.GetFiles("./.artifacts/*.nupkg"))
foreach(var file in context.GetFiles("./.artifacts/*.nupkg"))
{
context.Information("Publishing {0}...", file.GetFilename().FullPath);
exitCode += StartProcess("dotnet",
exitCode += StartProcess("dotnet",
new ProcessSettings {
Arguments = new ProcessArgumentBuilder()
.Append("gpr")
@ -87,7 +87,7 @@ Task("Publish-GitHub")
);
}
if(exitCode != 0)
if(exitCode != 0)
{
throw new CakeException("Could not push GitHub packages.");
}
@ -96,7 +96,7 @@ Task("Publish-GitHub")
Task("Publish-NuGet")
// .WithCriteria(ctx => BuildSystem.IsRunningOnGitHubActions, "Not running on GitHub Actions")
.IsDependentOn("Package")
.Does(context =>
.Does(context =>
{
var apiKey = Argument<string>("nuget-key", null);
if(string.IsNullOrWhiteSpace(apiKey)) {
@ -104,7 +104,7 @@ Task("Publish-NuGet")
}
// Publish to GitHub Packages
foreach(var file in context.GetFiles($"{pkgOutPath}/*.*nupkg"))
foreach(var file in context.GetFiles($"{pkgOutPath}/*.*nupkg"))
{
context.Information("Publishing {0}...", file.GetFilename().FullPath);
DotNetNuGetPush(file.FullPath, new DotNetNuGetPushSettings

View File

@ -2,6 +2,5 @@
"version": 1,
"isRoot": true,
"tools": {
}
}

View File

@ -1,5 +1,5 @@
Param(
# Nuget APIKey
# Nuget APIKey
[string] $apikey
)
@ -12,13 +12,13 @@ if ($apikey -eq $null -or $apikey -eq "")
rm -r ./build/nupkgs
dotnet build -c Release
$files = Get-ChildItem -Path ./build/nupkgs/ -Filter *.nupkg
foreach($file in $files)
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)
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,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,20 @@ 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)
{
var ret = BitConverter.ToString(me);
if (!upperCase) ret = ret.ToLower();
if (splitShar != "-") ret = ret.Replace("-", splitShar ?? string.Empty);
var ret = BitConverter.ToString(me);
if (!upperCase) {
ret = ret.ToLower(CultureInfo.InvariantCulture);
}
if (splitShar != "-") {
ret = ret.Replace("-", splitShar ?? string.Empty);
}
return ret;
}
}

View File

@ -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 '=';

View File

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

View File

@ -1,28 +1,46 @@
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--) {
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) ? "1" : "0")
, _ => sql.Replace(me.Parameters[i].ParameterName, me.Parameters[i].Value?.ToString())
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,5 +1,8 @@
namespace NSExt.Extensions;
/// <summary>
/// DecimalExtensions
/// </summary>
public static class DecimalExtensions
{
/// <summary>

View File

@ -1,5 +1,8 @@
namespace NSExt.Extensions;
/// <summary>
/// EnumExtensions
/// </summary>
public static class EnumExtensions
{
/// <summary>
@ -12,6 +15,6 @@ public static class EnumExtensions
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)) ?? "";
return (attrs.Length != 0 ? attrs[0].Description : Enum.GetName(t, e)) ?? string.Empty;
}
}

View File

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

View File

@ -1,5 +1,8 @@
namespace NSExt.Extensions;
/// <summary>
/// GenericExtensions
/// </summary>
public static class GenericExtensions
{
/// <summary>
@ -14,27 +17,24 @@ public static class GenericExtensions
, 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 (!p.CanWrite) {
continue;
}
if (isSet) p.SetValue(me, copyObj.GetType().GetProperty(p.Name)?.GetValue(copyObj, null), null);
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>
/// <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
public static T Is<T>(this T me, T compare, T ret)
where T : struct
{
return me.Equals(compare) ? ret : me;
}

View File

@ -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());

View File

@ -4,9 +4,15 @@ using System.Text.Json.Serialization;
namespace NSExt.Extensions;
/// <summary>
/// JsonSerializerOptionsExtensions
/// </summary>
public static class JsonSerializerOptionsExtensions
{
public static JsonSerializerOptions NewJsonSerializerOptions(this JsonSerializerOptions me)
/// <summary>
/// NewJsonSerializerOptions
/// </summary>
public static JsonSerializerOptions NewJsonSerializerOptions(this JsonSerializerOptions _)
{
return new JsonSerializerOptions {
ReadCommentHandling = JsonCommentHandling.Skip

View File

@ -2,48 +2,87 @@
namespace NSExt.Extensions;
/// <summary>
/// LoggerExtensions
/// </summary>
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}>";
}
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)
{
me.LogDebug(CallerInfoMessage(message, callerName, callerFilePath, callerLineNumber));
_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)
{
me.LogError(CallerInfoMessage(message, callerName, callerFilePath, callerLineNumber));
_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)
{
if (ex is null)
me.LogCritical(CallerInfoMessage(message, callerName, callerFilePath, callerLineNumber));
else
me.LogCritical(CallerInfoMessage(message, callerName, callerFilePath, callerLineNumber), ex);
_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)
{
me.LogInformation(CallerInfoMessage(message, callerName, callerFilePath, callerLineNumber));
_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)
{
me.LogWarning(CallerInfoMessage(message, callerName, callerFilePath, callerLineNumber));
_logWarn(me, message.ToString(), Environment.CurrentManagedThreadId.ToString(CultureInfo.InvariantCulture)
, callerName, Path.GetFileName(callerFilePath), callerLineNumber.ToString(CultureInfo.InvariantCulture)
, null);
}
}

View File

@ -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();

View File

@ -2,6 +2,9 @@ using System.Text.Json;
namespace NSExt.Extensions;
/// <summary>
/// ObjectExtensions
/// </summary>
public static class ObjectExtensions
{
/// <summary>

View File

@ -1,17 +1,28 @@
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))
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;

View File

@ -1,41 +1,26 @@
// ReSharper disable UnusedMember.Global
// ReSharper disable MemberCanBePrivate.Global
#pragma warning disable CA1720
using System.Security.Cryptography;
using System.Text.Json;
namespace NSExt.Extensions;
public static class StringExtensions
/// <summary>
/// StringExtensions
/// </summary>
public static partial 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);
}
/// <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;
@ -47,17 +32,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;
@ -98,13 +78,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)
{
@ -114,7 +93,6 @@ public static class StringExtensions
/// <summary>
/// 将原生base64字符串转换成易于web传输的字符串
/// </summary>
/// <param name="me"></param>
/// <returns>易于web传输的字符串</returns>
public static string Base64Web(this string me)
{
@ -156,7 +134,6 @@ public static class StringExtensions
: ret;
}
/// <summary>
/// 将字符串转换成日期对象
/// </summary>
@ -178,7 +155,6 @@ public static class StringExtensions
return decimal.Parse(me, CultureInfo.CurrentCulture);
}
/// <summary>
/// 尝试将字符串转为decimal
/// </summary>
@ -190,7 +166,6 @@ public static class StringExtensions
return !decimal.TryParse(me, out var ret) ? def : ret;
}
/// <summary>
/// string to double
/// </summary>
@ -204,23 +179,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;
}
@ -235,12 +204,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);
@ -251,13 +218,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>
@ -279,11 +244,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>
@ -299,8 +263,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);
@ -337,7 +299,6 @@ public static class StringExtensions
return !int.TryParse(me, out var ret) ? def : ret;
}
/// <summary>
/// string to Int64
/// </summary>
@ -362,43 +323,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>
@ -408,10 +369,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 MyRegex().Replace(me, "$1****$2");
}
/// <summary>
/// 对一个字符串进行md5hash运算
/// </summary>
@ -420,8 +380,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);
}
@ -437,12 +396,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);
@ -459,7 +415,6 @@ public static class StringExtensions
return JsonSerializer.Deserialize<T>(me, options ?? _defaultJsonSerializerOptions);
}
/// <summary>
/// 反序列化一个文件获得指定类型的数据对象
/// </summary>
@ -472,7 +427,6 @@ public static class StringExtensions
return JsonSerializer.Deserialize(me, type, options ?? _defaultJsonSerializerOptions);
}
/// <summary>
/// 生成密码
/// </summary>
@ -490,20 +444,17 @@ public static class StringExtensions
/// <returns>处理之后的字符串</returns>
public static string RemoveHtmlTag(this string me)
{
return new Regex(@"<[^>]*>").Replace(me, "");
return MyRegex1().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>
@ -512,42 +463,34 @@ 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 MyRegex2().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>
/// <param name="me"></param>
/// <returns></returns>
public static string Text2Html(this string me)
{
return $"<pre>{me}</pre>";
@ -556,15 +499,13 @@ public static class StringExtensions
/// <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);
}
// ReSharper disable once TailRecursiveCall
return ret == me ? ret : ret.TrimSpaces();
}
/// <summary>
/// url编码
@ -585,4 +526,28 @@ 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);
}
[GeneratedRegex("^(\\d{3})\\d{4}(\\d{4})$")]
private static partial Regex MyRegex();
[GeneratedRegex("<[^>]*>")]
private static partial Regex MyRegex1();
[GeneratedRegex("([A-Z])")]
private static partial Regex MyRegex2();
}

View File

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

View File

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

View File

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

View File

@ -1,16 +1,17 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net6.0;net7.0</TargetFrameworks>
<TargetFrameworks>net7.0</TargetFrameworks>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Logging" Version="7.0.0" />
<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>
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>
<Import Project="../CodeQuality.props"/>
</Project>

9
stylecop.json Normal file
View 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
}
}
}