mirror of
https://github.com/nsnail/ns-ext.git
synced 2025-06-21 01:48:15 +08:00
Tk (#1)
* <chore> * 1.0.7 * <adjust> * <chore> * <chore> * <refactor> * <doc> * <doc> * <feat> + Unicode,UnicodeDe * <revert> * <fix> * bugfix * <feat> 从资源文件读取Description * <feat> 从资源文件读取Description-可继承 * <fix> 将一个对象序列化成json文本 * <chore> * 调整一下日志格式 * feat: * 泛型特性本地化资源描述 * 添加测试项目 * <chore> * feat: enum、string * feat: long 类型增加rand方法 * feat: ToInvString * fix: ToInvString * fix: ToInvString * fix: ParameterFormat bug * [BLD] [SKIP CI]
This commit is contained in:
@ -1,89 +0,0 @@
|
||||
[*.{appxmanifest,asax,ascx,aspx,axaml,axml,build,config,cs,cshtml,csproj,css,dbml,discomap,dtd,htm,html,js,json,jsproj,jsx,lsproj,master,njsproj,nuspec,paml,proj,props,proto,razor,resjson,resw,resx,skin,StyleCop,targets,tasks,ts,tsx,vb,vbproj,xaml,xamlx,xml,xoml,xsd}]
|
||||
indent_style = space
|
||||
indent_size = space
|
||||
tab_width = 4
|
||||
|
||||
[*]
|
||||
|
||||
# Microsoft .NET properties
|
||||
csharp_indent_braces = false
|
||||
csharp_new_line_before_members_in_object_initializers = true
|
||||
csharp_new_line_before_open_brace = local_functions, methods, types
|
||||
csharp_preferred_modifier_order = public, private, protected, internal, new, abstract, virtual, sealed, override, static, readonly, extern, unsafe, volatile, async:suggestion
|
||||
csharp_style_var_elsewhere = true:suggestion
|
||||
csharp_style_var_for_built_in_types = true:suggestion
|
||||
csharp_style_var_when_type_is_apparent = true:suggestion
|
||||
dotnet_style_parentheses_in_arithmetic_binary_operators = never_if_unnecessary:none
|
||||
dotnet_style_parentheses_in_other_binary_operators = never_if_unnecessary:none
|
||||
dotnet_style_parentheses_in_relational_binary_operators = never_if_unnecessary:none
|
||||
dotnet_style_predefined_type_for_locals_parameters_members = true:suggestion
|
||||
dotnet_style_predefined_type_for_member_access = true:suggestion
|
||||
dotnet_style_qualification_for_event = false:suggestion
|
||||
dotnet_style_qualification_for_field = false:suggestion
|
||||
dotnet_style_qualification_for_method = false:suggestion
|
||||
dotnet_style_qualification_for_property = false:suggestion
|
||||
dotnet_style_require_accessibility_modifiers = for_non_interface_members:suggestion
|
||||
|
||||
# ReSharper inspection severities
|
||||
resharper_arrange_redundant_parentheses_highlighting = hint
|
||||
resharper_arrange_this_qualifier_highlighting = hint
|
||||
resharper_arrange_type_member_modifiers_highlighting = hint
|
||||
resharper_arrange_type_modifiers_highlighting = hint
|
||||
resharper_built_in_type_reference_style_for_member_access_highlighting = hint
|
||||
resharper_built_in_type_reference_style_highlighting = hint
|
||||
resharper_redundant_base_qualifier_highlighting = warning
|
||||
resharper_suggest_var_or_type_built_in_types_highlighting = hint
|
||||
resharper_suggest_var_or_type_elsewhere_highlighting = hint
|
||||
resharper_suggest_var_or_type_simple_types_highlighting = hint
|
||||
|
||||
# ReSharper properties
|
||||
resharper_align_first_arg_by_paren = true
|
||||
resharper_align_linq_query = true
|
||||
resharper_align_multiline_argument = true
|
||||
resharper_align_multiline_array_and_object_initializer = false
|
||||
resharper_align_multiline_calls_chain = true
|
||||
resharper_align_multiline_expression = true
|
||||
resharper_align_multiline_extends_list = true
|
||||
resharper_align_multiline_for_stmt = true
|
||||
resharper_align_multiline_property_pattern = true
|
||||
resharper_align_multiline_switch_expression = true
|
||||
resharper_align_multline_type_parameter_constrains = true
|
||||
resharper_align_multline_type_parameter_list = true
|
||||
resharper_align_tuple_components = true
|
||||
resharper_csharp_align_multiline_parameter = true
|
||||
resharper_csharp_align_multiple_declaration = true
|
||||
resharper_csharp_empty_block_style = together
|
||||
resharper_csharp_indent_size = 4
|
||||
resharper_csharp_indent_style = space
|
||||
resharper_csharp_insert_final_newline = true
|
||||
resharper_csharp_max_line_length = 120
|
||||
resharper_csharp_stick_comment = false
|
||||
resharper_csharp_tab_width = 4
|
||||
resharper_csharp_wrap_arguments_style = chop_if_long
|
||||
resharper_csharp_wrap_before_comma = false
|
||||
resharper_csharp_wrap_chained_method_calls = chop_if_long
|
||||
resharper_csharp_wrap_extends_list_style = chop_if_long
|
||||
resharper_csharp_wrap_parameters_style = chop_if_long
|
||||
resharper_indent_anonymous_method_block = true
|
||||
resharper_indent_nested_fixed_stmt = true
|
||||
resharper_indent_nested_foreach_stmt = true
|
||||
resharper_indent_nested_for_stmt = true
|
||||
resharper_indent_nested_lock_stmt = true
|
||||
resharper_indent_nested_usings_stmt = true
|
||||
resharper_indent_nested_while_stmt = true
|
||||
resharper_indent_preprocessor_if = usual_indent
|
||||
resharper_indent_preprocessor_other = usual_indent
|
||||
resharper_int_align = true
|
||||
resharper_keep_existing_arrangement = false
|
||||
resharper_keep_existing_linebreaks = false
|
||||
resharper_max_initializer_elements_on_line = 1
|
||||
resharper_outdent_commas = true
|
||||
resharper_outdent_dots = true
|
||||
resharper_wrap_array_initializer_style = chop_always
|
||||
resharper_wrap_before_comma = false
|
||||
resharper_wrap_object_and_collection_initializer_style = chop_always
|
||||
|
||||
[*.cs]
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
tab_width = 4
|
@ -1,18 +0,0 @@
|
||||
<Project>
|
||||
<PropertyGroup>
|
||||
<Authors>nsnail</Authors>
|
||||
<Product>NSExt</Product>
|
||||
<Copyright>© 2006-2022 nsnail</Copyright>
|
||||
<RepositoryUrl>https://github.com/nsnail/ns-ext.git</RepositoryUrl>
|
||||
<PublishRepositoryUrl>true</PublishRepositoryUrl>
|
||||
<EmbedUntrackedSource>true</EmbedUntrackedSource>
|
||||
<EmbedAllSources>true</EmbedAllSources>
|
||||
<RepositoryType>Git</RepositoryType>
|
||||
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
|
||||
<IncludeSymbols>true</IncludeSymbols>
|
||||
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
|
||||
<PackageLicenseExpression>MIT</PackageLicenseExpression>
|
||||
<PackageProjectUrl>https://github.com/nsnail/ns-ext.git</PackageProjectUrl>
|
||||
<PackageOutputPath>../../build/nupkgs</PackageOutputPath>
|
||||
</PropertyGroup>
|
||||
</Project>
|
9
src/NSExt.Tests/NSExt.Tests.csproj
Normal file
9
src/NSExt.Tests/NSExt.Tests.csproj
Normal file
@ -0,0 +1,9 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0-preview-23424-02"/>
|
||||
<PackageReference Include="xunit" Version="2.5.2-pre.2"/>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\NSExt\NSExt.csproj"/>
|
||||
</ItemGroup>
|
||||
</Project>
|
36
src/NSExt.Tests/TestCase.cs
Normal file
36
src/NSExt.Tests/TestCase.cs
Normal file
@ -0,0 +1,36 @@
|
||||
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);
|
||||
// }
|
||||
}
|
@ -1,16 +0,0 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NSExt", "NSExt\NSExt.csproj", "{54814D1B-C587-4D90-A7BE-4BE1E170D5FC}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{54814D1B-C587-4D90-A7BE-4BE1E170D5FC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{54814D1B-C587-4D90-A7BE-4BE1E170D5FC}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{54814D1B-C587-4D90-A7BE-4BE1E170D5FC}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{54814D1B-C587-4D90-A7BE-4BE1E170D5FC}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
EndGlobal
|
@ -1,45 +0,0 @@
|
||||
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
|
||||
<s:String x:Key="/Default/CodeStyle/CSharpFileLayoutPatterns/Pattern/@EntryValue"><?xml version="1.0" encoding="utf-16"?>
|
||||
<Patterns xmlns="urn:schemas-jetbrains-com:member-reordering-patterns">
|
||||
<TypePattern>
|
||||
<Entry>
|
||||
<Entry.SortBy>
|
||||
<Kind>
|
||||
<Kind.Order>
|
||||
<DeclarationKind>Interface</DeclarationKind>
|
||||
<DeclarationKind>Class</DeclarationKind>
|
||||
<DeclarationKind>Enum</DeclarationKind>
|
||||
<DeclarationKind>Struct</DeclarationKind>
|
||||
<DeclarationKind>Delegate</DeclarationKind>
|
||||
<DeclarationKind>Event</DeclarationKind>
|
||||
<DeclarationKind>Constant</DeclarationKind>
|
||||
<DeclarationKind>Field</DeclarationKind>
|
||||
<DeclarationKind>Property</DeclarationKind>
|
||||
<DeclarationKind>Constructor</DeclarationKind>
|
||||
<DeclarationKind>Destructor</DeclarationKind>
|
||||
<DeclarationKind>Indexer</DeclarationKind>
|
||||
<DeclarationKind>Method</DeclarationKind>
|
||||
</Kind.Order>
|
||||
</Kind>
|
||||
<Access>
|
||||
<Access.Order>
|
||||
<AccessModifier>Private</AccessModifier>
|
||||
<AccessModifier>PrivateProtected</AccessModifier>
|
||||
<AccessModifier>Protected</AccessModifier>
|
||||
<AccessModifier>ProtectedInternal</AccessModifier>
|
||||
<AccessModifier>Internal</AccessModifier>
|
||||
<AccessModifier>Public</AccessModifier>
|
||||
</Access.Order>
|
||||
</Access>
|
||||
<Name />
|
||||
</Entry.SortBy>
|
||||
</Entry>
|
||||
</TypePattern>
|
||||
</Patterns></s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=Constants/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="AA_BB" /></s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateConstants/@EntryIndexedValue"><Policy Inspect="True" Prefix="_" Suffix="" Style="AA_BB" /></s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateStaticReadonly/@EntryIndexedValue"><Policy Inspect="True" Prefix="_" Suffix="" Style="aaBb" /></s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=StaticReadonly/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /></s:String>
|
||||
<s:Boolean x:Key="/Default/ReSpeller/ReSpellerEnabled/@EntryValue">False</s:Boolean>
|
||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=TooWideLocalVariableScope/@EntryIndexedValue">HINT</s:String>
|
||||
</wpf:ResourceDictionary>
|
24
src/NSExt/Attributes/LocalizationAttribute.cs
Normal file
24
src/NSExt/Attributes/LocalizationAttribute.cs
Normal file
@ -0,0 +1,24 @@
|
||||
namespace NSExt.Attributes;
|
||||
|
||||
/// <summary>
|
||||
/// 指定本地化资源类型
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Class | AttributeTargets.Field)]
|
||||
public sealed 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; }
|
||||
}
|
26
src/NSExt/Attributes/ResourceDescriptionAttribute.cs
Normal file
26
src/NSExt/Attributes/ResourceDescriptionAttribute.cs
Normal file
@ -0,0 +1,26 @@
|
||||
namespace NSExt.Attributes;
|
||||
|
||||
/// <summary>
|
||||
/// 本地化资源描述特性
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Class | AttributeTargets.Field)]
|
||||
public sealed 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; }
|
||||
}
|
21
src/NSExt/Constant/Regexes.cs
Normal file
21
src/NSExt/Constant/Regexes.cs
Normal file
@ -0,0 +1,21 @@
|
||||
namespace NSExt.Constant;
|
||||
#pragma warning disable SYSLIB1045
|
||||
|
||||
/// <summary>
|
||||
/// 使用 RegexGenerator 新特性会生成重复key值的xmlComment导致出错
|
||||
/// </summary>
|
||||
internal static class Regexes
|
||||
{
|
||||
public static readonly Regex RegexBacksLantUnicode
|
||||
= new(@"\\u([a-fA-F0-9]{4})", RegexOptions.Compiled | RegexOptions.IgnoreCase);
|
||||
|
||||
public static readonly Regex RegexHtmlTag = new("<[^>]*>", RegexOptions.Compiled | RegexOptions.IgnoreCase);
|
||||
|
||||
public static readonly Regex RegexMobile
|
||||
= new(@"^(\d{3})\d{4}(\d{4})$", RegexOptions.Compiled | RegexOptions.IgnoreCase);
|
||||
|
||||
public static readonly Regex RegexPercentUnicode
|
||||
= new(@"\\u([a-fA-F0-9]{4})", RegexOptions.Compiled | RegexOptions.IgnoreCase);
|
||||
|
||||
public static readonly Regex RegexUpLetter = new("([A-Z])", RegexOptions.Compiled | RegexOptions.IgnoreCase);
|
||||
}
|
@ -1,22 +1,24 @@
|
||||
namespace NSExt.Extensions;
|
||||
|
||||
/// <summary>
|
||||
/// ByteExtensions
|
||||
/// </summary>
|
||||
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)
|
||||
{
|
||||
return Convert.ToBase64String(me);
|
||||
}
|
||||
|
||||
|
||||
/// <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)
|
||||
@ -24,11 +26,10 @@ public static class ByteExtensions
|
||||
return e.GetString(me);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 将字节数组解码成字符串
|
||||
/// </summary>
|
||||
/// <param name="me">字节数组</param>
|
||||
/// <param name="me">me</param>
|
||||
/// <returns>解码后的原始字符串</returns>
|
||||
public static string HexDe(this byte[] me)
|
||||
{
|
||||
@ -38,15 +39,23 @@ public static class ByteExtensions
|
||||
/// <summary>
|
||||
/// 将字节数组转换成16进制字符串
|
||||
/// </summary>
|
||||
/// <param name="me"></param>
|
||||
/// <param name="me">me</param>
|
||||
/// <param name="upperCase">是否大写</param>
|
||||
/// <param name="splitShar">字节间分隔符</param>
|
||||
/// <returns></returns>
|
||||
public static string String(this byte[] me, bool upperCase = true, string splitShar = null)
|
||||
/// <param name="splitInterval">分隔符跳跃字节数</param>
|
||||
public static string Str(this IEnumerable<byte> me, bool upperCase = true, string splitShar = ""
|
||||
, int splitInterval = 1)
|
||||
{
|
||||
var ret = BitConverter.ToString(me);
|
||||
if (!upperCase) ret = ret.ToLower();
|
||||
if (splitShar != "-") ret = ret.Replace("-", splitShar ?? string.Empty);
|
||||
return ret;
|
||||
var sb = new StringBuilder();
|
||||
var i = 0;
|
||||
foreach (var c in me.Select(x => x.ToString(upperCase ? "X2" : "x2", CultureInfo.InvariantCulture))) {
|
||||
if (i++ % splitInterval == 0) {
|
||||
_ = sb.Append(splitShar);
|
||||
}
|
||||
|
||||
_ = sb.Append(c);
|
||||
}
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
}
|
@ -1,12 +1,13 @@
|
||||
namespace NSExt.Extensions;
|
||||
|
||||
/// <summary>
|
||||
/// CharExtensions
|
||||
/// </summary>
|
||||
public static class CharExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// 是否数字或大小写字母
|
||||
/// </summary>
|
||||
/// <param name="me"></param>
|
||||
/// <returns></returns>
|
||||
public static bool IsAsciiLetterOrDigit(this char me)
|
||||
{
|
||||
return (((uint)me - 'A') & ~0x20) < 26 || (uint)me - '0' < 10;
|
||||
@ -15,8 +16,6 @@ public static class CharExtensions
|
||||
/// <summary>
|
||||
/// 是否base64字符
|
||||
/// </summary>
|
||||
/// <param name="me"></param>
|
||||
/// <returns></returns>
|
||||
public static bool IsBase64Character(this char me)
|
||||
{
|
||||
return IsAsciiLetterOrDigit(me) || me is '+' or '/' or '=';
|
||||
|
@ -1,31 +1,18 @@
|
||||
// ReSharper disable InconsistentNaming
|
||||
// ReSharper disable UnusedMember.Global
|
||||
|
||||
#pragma warning disable SA1300, IDE1006
|
||||
namespace NSExt.Extensions;
|
||||
|
||||
/// <summary>
|
||||
/// DateTimeExtensions
|
||||
/// </summary>
|
||||
public static class DateTimeExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// 将一个过去时间对象与当前时间相减转换成“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 + "秒前";
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 指定时间的世界协调时的unix时间戳形式
|
||||
/// </summary>
|
||||
/// <param name="me">指定时间</param>
|
||||
/// <param name="me">me</param>
|
||||
/// <returns>unix时间戳</returns>
|
||||
public static long TimeUnixUtc(this DateTime me)
|
||||
{
|
||||
@ -35,55 +22,89 @@ 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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// ToString 的 Invariant 版本
|
||||
/// </summary>
|
||||
public static string ToInvString(this DateTime me)
|
||||
{
|
||||
return me.ToString(CultureInfo.InvariantCulture);
|
||||
}
|
||||
|
||||
// ReSharper disable once InconsistentNaming
|
||||
/// <summary>
|
||||
/// 将一个过去时间对象与当前时间相减转换成“xx以前”的字符串, 如2秒以前, 3天以前
|
||||
/// </summary>
|
||||
/// <param name="me">me</param>
|
||||
/// <returns>字符串</returns>
|
||||
public static string UtcTimeAgo(this DateTime me)
|
||||
{
|
||||
var ts = DateTime.UtcNow - me;
|
||||
return ts.Days switch {
|
||||
> 0 => ts.Days + "天前"
|
||||
, _ => ts.Hours switch {
|
||||
> 0 => ts.Hours + "小时前"
|
||||
, _ => ts.Minutes switch { > 0 => ts.Minutes + "分钟前", _ => ts.Seconds + "秒前" }
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// yyyy_MM
|
||||
/// </summary>
|
||||
public static string yyyy_MM(this DateTime me)
|
||||
{
|
||||
return me.ToString("yyyy-MM");
|
||||
return me.ToString("yyyy-MM", CultureInfo.InvariantCulture);
|
||||
}
|
||||
|
||||
// ReSharper disable once InconsistentNaming
|
||||
/// <summary>
|
||||
/// yyyy_MM_dd
|
||||
/// </summary>
|
||||
public static string yyyy_MM_dd(this DateTime me)
|
||||
{
|
||||
return me.ToString("yyyy-MM-dd");
|
||||
return me.ToString("yyyy-MM-dd", CultureInfo.InvariantCulture);
|
||||
}
|
||||
|
||||
// ReSharper disable once InconsistentNaming
|
||||
/// <summary>
|
||||
/// yyyy_MM_dd_HH_mm
|
||||
/// </summary>
|
||||
public static string yyyy_MM_dd_HH_mm(this DateTime me)
|
||||
{
|
||||
return me.ToString("yyyy-MM-dd HH:mm");
|
||||
return me.ToString("yyyy-MM-dd HH:mm", CultureInfo.InvariantCulture);
|
||||
}
|
||||
|
||||
|
||||
// ReSharper disable once InconsistentNaming
|
||||
/// <summary>
|
||||
/// yyyy_MM_dd_HH_mm_ss
|
||||
/// </summary>
|
||||
public static string yyyy_MM_dd_HH_mm_ss(this DateTime me)
|
||||
{
|
||||
return me.ToString("yyyy-MM-dd HH:mm:ss");
|
||||
return me.ToString("yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture);
|
||||
}
|
||||
|
||||
// ReSharper disable once InconsistentNaming
|
||||
/// <summary>
|
||||
/// yyyy_MM_dd_HH_mm_ss_fff
|
||||
/// </summary>
|
||||
public static string yyyy_MM_dd_HH_mm_ss_fff(this DateTime me)
|
||||
{
|
||||
return me.ToString("yyyy-MM-dd HH:mm:ss.fff");
|
||||
return me.ToString("yyyy-MM-dd HH:mm:ss.fff", CultureInfo.InvariantCulture);
|
||||
}
|
||||
|
||||
|
||||
// ReSharper disable once InconsistentNaming
|
||||
/// <summary>
|
||||
/// yyyyMM
|
||||
/// </summary>
|
||||
public static string yyyyMM(this DateTime me)
|
||||
{
|
||||
return me.ToString("yyyyMM");
|
||||
return me.ToString("yyyyMM", CultureInfo.InvariantCulture);
|
||||
}
|
||||
|
||||
// ReSharper disable once InconsistentNaming
|
||||
/// <summary>
|
||||
/// yyyyMMdd
|
||||
/// </summary>
|
||||
public static string yyyyMMdd(this DateTime me)
|
||||
{
|
||||
return me.ToString("yyyyMMdd");
|
||||
return me.ToString("yyyyMMdd", CultureInfo.InvariantCulture);
|
||||
}
|
||||
}
|
@ -1,28 +1,35 @@
|
||||
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--)
|
||||
// 应逆向替换,否则由于 多个表的过滤器问题导致替换不完整 如 @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) ? "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
|
||||
, me.Parameters[i].Value != DBNull.Value &&
|
||||
Convert.ToBoolean(me.Parameters[i].Value, CultureInfo.InvariantCulture)
|
||||
? "1"
|
||||
: "0")
|
||||
, _ => sql.Replace(me.Parameters[i].ParameterName, me.Parameters[i].Value?.ToString())
|
||||
};
|
||||
}
|
||||
|
||||
return sql;
|
||||
}
|
||||
|
@ -1,16 +1,26 @@
|
||||
namespace NSExt.Extensions;
|
||||
|
||||
/// <summary>
|
||||
/// DecimalExtensions
|
||||
/// </summary>
|
||||
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)
|
||||
{
|
||||
var dec = Math.Round(me, place);
|
||||
return dec;
|
||||
return Math.Round(me, place);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// ToString 的 Invariant 版本
|
||||
/// </summary>
|
||||
public static string ToInvString(this decimal me)
|
||||
{
|
||||
return me.ToString(CultureInfo.InvariantCulture);
|
||||
}
|
||||
}
|
@ -1,17 +1,41 @@
|
||||
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>
|
||||
public static string Desc(this Enum e)
|
||||
public static DisplayAttribute GetDisplay(this Enum me)
|
||||
{
|
||||
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 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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 通过类泛型类型获取特性
|
||||
/// </summary>
|
||||
private static T GetAttributeOfType<T>(this Enum me)
|
||||
where T : Attribute
|
||||
{
|
||||
return me.GetType().GetMember(me.ToString())[0].GetCustomAttributes<T>(false).FirstOrDefault();
|
||||
}
|
||||
}
|
@ -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);
|
||||
@ -17,10 +17,10 @@ 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)
|
||||
{
|
||||
return me is null || !me.Any();
|
||||
return me?.Any() != true;
|
||||
}
|
||||
}
|
@ -1,42 +1,40 @@
|
||||
namespace NSExt.Extensions;
|
||||
|
||||
/// <summary>
|
||||
/// GenericExtensions
|
||||
/// </summary>
|
||||
public static class GenericExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// 从指定的对象拷贝属性
|
||||
/// </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>
|
||||
public static void CopyFrom<T>(this T me,
|
||||
T copyObj,
|
||||
IList<string> propNameList = null,
|
||||
bool isIncludeOrExclude = false)
|
||||
public static void CopyFrom<T>(this T me, T copyObj, IList<string> propNameList = null
|
||||
, bool isIncludeOrExclude = false)
|
||||
{
|
||||
foreach (var p in me.GetType().GetProperties()) {
|
||||
if (!p.CanWrite) continue;
|
||||
bool isSet;
|
||||
if (isIncludeOrExclude)
|
||||
isSet = propNameList?.Contains(p.Name) ?? false;
|
||||
else
|
||||
isSet = !propNameList?.Contains(p.Name) ?? true;
|
||||
if (!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;
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
@ -17,18 +17,23 @@ public static class IntExtensions
|
||||
/// <summary>
|
||||
/// 生成随机数
|
||||
/// </summary>
|
||||
/// <param name="me">大于等于[0],小于[1]</param>
|
||||
/// <returns></returns>
|
||||
/// <param name="me">me</param>
|
||||
public static int Rand(this int[] me)
|
||||
{
|
||||
return new Random(Guid.NewGuid().GetHashCode()).Next(me[0], me[1]);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// ToString 的 Invariant 版本
|
||||
/// </summary>
|
||||
public static string ToInvString(this int me)
|
||||
{
|
||||
return me.ToString(CultureInfo.InvariantCulture);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 转换成ipv4
|
||||
/// </summary>
|
||||
/// <param name="me"></param>
|
||||
/// <returns></returns>
|
||||
public static string ToIpV4(this int me)
|
||||
{
|
||||
return string.Join(".", BitConverter.GetBytes(me).Reverse());
|
||||
|
@ -1,21 +0,0 @@
|
||||
using System.Text.Encodings.Web;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace NSExt.Extensions;
|
||||
|
||||
public static class JsonSerializerOptionsExtensions
|
||||
{
|
||||
public static JsonSerializerOptions NewJsonSerializerOptions(this JsonSerializerOptions me)
|
||||
{
|
||||
return new JsonSerializerOptions {
|
||||
ReadCommentHandling = JsonCommentHandling.Skip,
|
||||
AllowTrailingCommas = true,
|
||||
DictionaryKeyPolicy = JsonNamingPolicy.CamelCase,
|
||||
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
|
||||
Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping,
|
||||
NumberHandling = JsonNumberHandling.AllowReadingFromString | JsonNumberHandling.WriteAsString,
|
||||
PropertyNameCaseInsensitive = true
|
||||
};
|
||||
}
|
||||
}
|
@ -2,65 +2,82 @@
|
||||
|
||||
namespace NSExt.Extensions;
|
||||
|
||||
/// <summary>
|
||||
/// LoggerExtensions
|
||||
/// </summary>
|
||||
public static class LoggerExtensions
|
||||
{
|
||||
private static string CallerInfoMessage(object message,
|
||||
string callerName,
|
||||
string callerFilePath,
|
||||
int callerLineNumber)
|
||||
private const string _MESSAGE_S_THREAD_ID_CALLER_NAME_CALLER_FILE_PATH_CALLER_LINE_NUMBER
|
||||
= "{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_THREAD_ID_CALLER_NAME_CALLER_FILE_PATH_CALLER_LINE_NUMBER);
|
||||
|
||||
private static readonly Action<ILogger, string, string, string, string, Exception> _logError
|
||||
= LoggerMessage.Define<string, string, string, string>(LogLevel.Error, default
|
||||
, _MESSAGE_S_THREAD_ID_CALLER_NAME_CALLER_FILE_PATH_CALLER_LINE_NUMBER);
|
||||
|
||||
private static readonly Action<ILogger, string, string, string, string, Exception> _logFatal
|
||||
= LoggerMessage.Define<string, string, string, string>(LogLevel.Critical, default
|
||||
, _MESSAGE_S_THREAD_ID_CALLER_NAME_CALLER_FILE_PATH_CALLER_LINE_NUMBER);
|
||||
|
||||
private static readonly Action<ILogger, string, string, string, string, Exception> _logInfo
|
||||
= LoggerMessage.Define<string, string, string, string>(LogLevel.Information, default
|
||||
, _MESSAGE_S_THREAD_ID_CALLER_NAME_CALLER_FILE_PATH_CALLER_LINE_NUMBER);
|
||||
|
||||
private static readonly Action<ILogger, string, string, string, string, Exception> _logWarn
|
||||
= LoggerMessage.Define<string, string, string, string>(LogLevel.Warning, default
|
||||
, _MESSAGE_S_THREAD_ID_CALLER_NAME_CALLER_FILE_PATH_CALLER_LINE_NUMBER);
|
||||
|
||||
/// <summary>
|
||||
/// Debug
|
||||
/// </summary>
|
||||
public static void Debug(this ILogger me, object message, [CallerMemberName] string callerName = null
|
||||
, [CallerFilePath] string callerFilePath = null, [CallerLineNumber] int callerLineNumber = 0)
|
||||
{
|
||||
return
|
||||
$"{message} <s:{Environment.CurrentManagedThreadId}#{callerName}@{Path.GetFileName(callerFilePath)}:{callerLineNumber}>";
|
||||
_logDebug(me, message.ToString(), callerName, Path.GetFileName(callerFilePath)
|
||||
, callerLineNumber.ToString(CultureInfo.InvariantCulture), null);
|
||||
}
|
||||
|
||||
public static void Debug(this ILogger me,
|
||||
object message,
|
||||
[CallerMemberName] string callerName = null,
|
||||
[CallerFilePath] string callerFilePath = null,
|
||||
[CallerLineNumber] int callerLineNumber = 0)
|
||||
/// <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.LogDebug(CallerInfoMessage(message, callerName, callerFilePath, callerLineNumber));
|
||||
_logError(me, message.ToString(), callerName, Path.GetFileName(callerFilePath)
|
||||
, callerLineNumber.ToString(CultureInfo.InvariantCulture), null);
|
||||
}
|
||||
|
||||
|
||||
public static void Error(this ILogger me,
|
||||
object message,
|
||||
[CallerMemberName] string callerName = null,
|
||||
[CallerFilePath] string callerFilePath = null,
|
||||
[CallerLineNumber] int callerLineNumber = 0)
|
||||
/// <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)
|
||||
{
|
||||
me.LogError(CallerInfoMessage(message, callerName, callerFilePath, callerLineNumber));
|
||||
_logFatal(me, message.ToString(), callerName, Path.GetFileName(callerFilePath)
|
||||
, callerLineNumber.ToString(CultureInfo.InvariantCulture), ex);
|
||||
}
|
||||
|
||||
public static void Fatal(this ILogger me,
|
||||
object message,
|
||||
Exception ex = null,
|
||||
[CallerMemberName] string callerName = null,
|
||||
[CallerFilePath] string callerFilePath = null,
|
||||
[CallerLineNumber] int callerLineNumber = 0)
|
||||
/// <summary>
|
||||
/// Info
|
||||
/// </summary>
|
||||
public static void Info(this ILogger me, object message, [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);
|
||||
_logInfo(me, message.ToString(), callerName, Path.GetFileName(callerFilePath)
|
||||
, callerLineNumber.ToString(CultureInfo.InvariantCulture), null);
|
||||
}
|
||||
|
||||
|
||||
public static void Info(this ILogger me,
|
||||
object message,
|
||||
[CallerMemberName] string callerName = null,
|
||||
[CallerFilePath] string callerFilePath = null,
|
||||
[CallerLineNumber] int callerLineNumber = 0)
|
||||
/// <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.LogInformation(CallerInfoMessage(message, callerName, callerFilePath, callerLineNumber));
|
||||
}
|
||||
|
||||
public static void Warn(this ILogger me,
|
||||
object message,
|
||||
[CallerMemberName] string callerName = null,
|
||||
[CallerFilePath] string callerFilePath = null,
|
||||
[CallerLineNumber] int callerLineNumber = 0)
|
||||
{
|
||||
me.LogWarning(CallerInfoMessage(message, callerName, callerFilePath, callerLineNumber));
|
||||
_logWarn(me, message.ToString(), callerName, Path.GetFileName(callerFilePath)
|
||||
, callerLineNumber.ToString(CultureInfo.InvariantCulture), null);
|
||||
}
|
||||
}
|
@ -1,27 +1,42 @@
|
||||
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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 生成随机数
|
||||
/// </summary>
|
||||
/// <param name="me">me</param>
|
||||
public static long Rand(this long[] me)
|
||||
{
|
||||
return new Random(Guid.NewGuid().GetHashCode()).NextInt64(me[0], me[1]);
|
||||
}
|
||||
|
||||
/// <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();
|
||||
return DateTime.UnixEpoch.AddMilliseconds(msFrom1970).ToLocalTime();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// ToString 的 Invariant 版本
|
||||
/// </summary>
|
||||
public static string ToInvString(this long me)
|
||||
{
|
||||
return me.ToString(CultureInfo.InvariantCulture);
|
||||
}
|
||||
}
|
@ -2,20 +2,29 @@ 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>
|
||||
/// <param name="me">me</param>
|
||||
/// <returns>json文本</returns>
|
||||
public static string Json(this object me, bool format = false)
|
||||
public static string Json(this object me)
|
||||
{
|
||||
return JsonSerializer.Serialize(me,
|
||||
new JsonSerializerOptions {
|
||||
WriteIndented = format,
|
||||
PropertyNamingPolicy = JsonNamingPolicy.CamelCase
|
||||
});
|
||||
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);
|
||||
}
|
||||
}
|
@ -1,22 +1,30 @@
|
||||
namespace NSExt.Extensions;
|
||||
|
||||
/// <summary>
|
||||
/// StreamExtensions
|
||||
/// </summary>
|
||||
public static class StreamExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// FirstByteIndex
|
||||
/// </summary>
|
||||
public static long FirstByteIndex(this Stream me, byte[] findBytes)
|
||||
{
|
||||
int data;
|
||||
while ((data = me.ReadByte()) != -1)
|
||||
if (findBytes.Contains((byte)data))
|
||||
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;
|
||||
return me.FirstByteIndex(new byte[] { 0x00, 0xff }) < 0;
|
||||
}
|
||||
}
|
@ -1,43 +1,25 @@
|
||||
// ReSharper disable UnusedMember.Global
|
||||
// ReSharper disable MemberCanBePrivate.Global
|
||||
|
||||
|
||||
#pragma warning disable CA1720
|
||||
using System.Security.Cryptography;
|
||||
using System.Text.Json;
|
||||
using NSExt.Constant;
|
||||
|
||||
namespace NSExt.Extensions;
|
||||
|
||||
/// <summary>
|
||||
/// StringExtensions
|
||||
/// </summary>
|
||||
#pragma warning disable CodeLinesAnalyzer
|
||||
public static class StringExtensions
|
||||
{
|
||||
private static readonly JsonSerializerOptions _defaultJsonSerializerOptions =
|
||||
default(JsonSerializerOptions).NewJsonSerializerOptions();
|
||||
|
||||
/// <summary>
|
||||
/// MD5 hmac编码
|
||||
/// </summary>
|
||||
/// <param name="me">字符串</param>
|
||||
/// <param name="key">密钥</param>
|
||||
/// <param name="e">字符串使用的编码</param>
|
||||
/// <returns>hash摘要的16进制文本形式(无连字符小写)</returns>
|
||||
private static string Md5Hmac(this string me, string key, Encoding e)
|
||||
{
|
||||
using var md5Hmac = new HMACMD5(e.GetBytes(key));
|
||||
return BitConverter.ToString(md5Hmac.ComputeHash(e.GetBytes(me)))
|
||||
.Replace("-", string.Empty)
|
||||
.ToLower(CultureInfo.CurrentCulture);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// aes加密
|
||||
/// </summary>
|
||||
/// <param name="me">要加密的串</param>
|
||||
/// <param name="me">me</param>
|
||||
/// <param name="key">密钥</param>
|
||||
/// <param name="cipherMode">指定要用于加密的块密码模式。</param>
|
||||
/// <param name="paddingMode">指定在消息数据块短于加密操作所需的完整字节数时要应用的填充类型。</param>
|
||||
/// <returns></returns>
|
||||
public static string Aes(this string me,
|
||||
string key,
|
||||
CipherMode cipherMode = CipherMode.ECB,
|
||||
PaddingMode paddingMode = PaddingMode.PKCS7)
|
||||
public static string Aes(this string me, string key)
|
||||
{
|
||||
using var aes = System.Security.Cryptography.Aes.Create();
|
||||
aes.Padding = PaddingMode.PKCS7;
|
||||
@ -49,19 +31,12 @@ public static class StringExtensions
|
||||
return decrypted.Base64();
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// aes解密
|
||||
/// </summary>
|
||||
/// <param name="me">要加密的串</param>
|
||||
/// <param name="me">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;
|
||||
@ -76,7 +51,7 @@ public static 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)
|
||||
@ -87,7 +62,7 @@ public static class StringExtensions
|
||||
/// <summary>
|
||||
/// base64解码
|
||||
/// </summary>
|
||||
/// <param name="me">待解码的字符串</param>
|
||||
/// <param name="me">me</param>
|
||||
/// <returns>解码后的原始字节数组</returns>
|
||||
public static byte[] Base64De(this string me)
|
||||
{
|
||||
@ -97,18 +72,17 @@ public static 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)
|
||||
{
|
||||
return e.GetString(Base64De(me));
|
||||
return e.GetString(me.Base64De());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将易于web传输的base64web字符串转换为原生base64
|
||||
/// </summary>
|
||||
/// <param name="me"></param>
|
||||
/// <returns>原生base64</returns>
|
||||
public static string Base64Sys(this string me)
|
||||
{
|
||||
@ -118,7 +92,6 @@ public static class StringExtensions
|
||||
/// <summary>
|
||||
/// 将原生base64字符串转换成易于web传输的字符串
|
||||
/// </summary>
|
||||
/// <param name="me"></param>
|
||||
/// <returns>易于web传输的字符串</returns>
|
||||
public static string Base64Web(this string me)
|
||||
{
|
||||
@ -128,7 +101,7 @@ public static class StringExtensions
|
||||
/// <summary>
|
||||
/// 将字符串转换成日期对象
|
||||
/// </summary>
|
||||
/// <param name="me">待转换字符串</param>
|
||||
/// <param name="me">me</param>
|
||||
/// <returns>转换后的日期对象</returns>
|
||||
public static DateTime DateTime(this string me)
|
||||
{
|
||||
@ -138,7 +111,7 @@ public static 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)
|
||||
@ -149,44 +122,42 @@ public static class StringExtensions
|
||||
/// <summary>
|
||||
/// 将字符串转换成日期对象
|
||||
/// </summary>
|
||||
/// <param name="me">待转换字符串</param>
|
||||
/// <param name="me">me</param>
|
||||
/// <param name="format">日期格式</param>
|
||||
/// <param name="def">转换失败时返回的日期对象</param>
|
||||
/// <returns>转换后的日期对象</returns>
|
||||
public static DateTime DateTimeExactTry(this string me, string format, DateTime def)
|
||||
{
|
||||
return !System.DateTime.TryParseExact(me, format, CultureInfo.CurrentCulture, DateTimeStyles.None, out var ret)
|
||||
? def
|
||||
: ret;
|
||||
? def
|
||||
: ret;
|
||||
}
|
||||
|
||||
|
||||
/// <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)
|
||||
{
|
||||
return !System.DateTime.TryParse(me, out var ret) ? def : ret;
|
||||
return !System.DateTime.TryParse(me, CultureInfo.InvariantCulture, out var ret) ? def : ret;
|
||||
}
|
||||
|
||||
/// <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)
|
||||
{
|
||||
return decimal.Parse(me, CultureInfo.CurrentCulture);
|
||||
}
|
||||
|
||||
|
||||
/// <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)
|
||||
@ -194,11 +165,10 @@ public static class StringExtensions
|
||||
return !decimal.TryParse(me, out var ret) ? def : ret;
|
||||
}
|
||||
|
||||
|
||||
/// <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)
|
||||
{
|
||||
@ -208,23 +178,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;
|
||||
}
|
||||
@ -232,19 +196,17 @@ public static 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)
|
||||
{
|
||||
return float.Parse(me, CultureInfo.CurrentCulture);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 将字符串转为guid
|
||||
/// </summary>
|
||||
/// <param name="me">字符串</param>
|
||||
/// <returns></returns>
|
||||
/// <param name="me">me</param>
|
||||
public static Guid Guid(this string me)
|
||||
{
|
||||
return System.Guid.Parse(me);
|
||||
@ -253,19 +215,17 @@ public static class StringExtensions
|
||||
/// <summary>
|
||||
/// 将字符串转换成guid
|
||||
/// </summary>
|
||||
/// <param name="me">字符串</param>
|
||||
/// <param name="me">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>
|
||||
/// <param name="me">字符串</param>
|
||||
/// <param name="me">me</param>
|
||||
/// <param name="e">字符串使用的编码</param>
|
||||
/// <returns>字节数组</returns>
|
||||
public static byte[] Hex(this string me, Encoding e)
|
||||
@ -276,24 +236,25 @@ public static class StringExtensions
|
||||
/// <summary>
|
||||
/// 将字符串转换成字节数组形式
|
||||
/// </summary>
|
||||
/// <param name="me">字符串</param>
|
||||
/// <param name="me">me</param>
|
||||
/// <returns>字节数组</returns>
|
||||
public static byte[] Hex(this string me)
|
||||
{
|
||||
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>
|
||||
public static string HmacSha1(this string me, string secret, Encoding e)
|
||||
{
|
||||
#pragma warning disable CA5350
|
||||
using var hmacSha1 = new HMACSHA1(e.GetBytes(secret));
|
||||
#pragma warning restore CA5350
|
||||
|
||||
return BitConverter.ToString(hmacSha1.ComputeHash(e.GetBytes(me)))
|
||||
.Replace("-", string.Empty)
|
||||
@ -303,8 +264,6 @@ public static class StringExtensions
|
||||
/// <summary>
|
||||
/// html编码
|
||||
/// </summary>
|
||||
/// <param name="me"></param>
|
||||
/// <returns></returns>
|
||||
public static string Html(this string me)
|
||||
{
|
||||
return HttpUtility.HtmlEncode(me);
|
||||
@ -313,7 +272,7 @@ public static class StringExtensions
|
||||
/// <summary>
|
||||
/// 解码html编码
|
||||
/// </summary>
|
||||
/// <param name="me">html编码后的字符串</param>
|
||||
/// <param name="me">me</param>
|
||||
/// <returns>解码后的原始字符串</returns>
|
||||
public static string HtmlDe(this string me)
|
||||
{
|
||||
@ -323,7 +282,7 @@ public static 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)
|
||||
{
|
||||
@ -333,7 +292,7 @@ public static 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)
|
||||
@ -341,11 +300,10 @@ public static class StringExtensions
|
||||
return !int.TryParse(me, out var ret) ? def : ret;
|
||||
}
|
||||
|
||||
|
||||
/// <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)
|
||||
{
|
||||
@ -355,7 +313,7 @@ public static 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)
|
||||
@ -366,66 +324,66 @@ 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>
|
||||
/// <param name="me">me</param>
|
||||
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>
|
||||
/// 对一个手机号进行掩码处理
|
||||
/// </summary>
|
||||
/// <param name="me">手机号</param>
|
||||
/// <param name="me">me</param>
|
||||
/// <returns>掩码后的手机号</returns>
|
||||
public static string MaskMobile(this string me)
|
||||
{
|
||||
return new Regex(@"^(\d{3})\d{4}(\d{4})$").Replace(me, "$1****$2");
|
||||
return Regexes.RegexMobile.Replace(me, "$1****$2");
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 对一个字符串进行md5hash运算
|
||||
/// </summary>
|
||||
/// <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)
|
||||
{
|
||||
using var md5 = MD5.Create();
|
||||
return BitConverter.ToString(md5.ComputeHash(e.GetBytes(me)))
|
||||
#pragma warning disable CA5351
|
||||
return BitConverter.ToString(MD5.HashData(e.GetBytes(me)))
|
||||
#pragma warning restore CA5351
|
||||
.Replace("-", string.Empty)
|
||||
.ToLower(CultureInfo.CurrentCulture);
|
||||
}
|
||||
@ -433,7 +391,7 @@ public static 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)
|
||||
@ -441,12 +399,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);
|
||||
@ -455,32 +410,30 @@ public static 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)
|
||||
{
|
||||
@ -490,80 +443,118 @@ public static class StringExtensions
|
||||
/// <summary>
|
||||
/// 移除字符串中的html标签
|
||||
/// </summary>
|
||||
/// <param name="me">字符串</param>
|
||||
/// <param name="me">me</param>
|
||||
/// <returns>处理之后的字符串</returns>
|
||||
public static string RemoveHtmlTag(this string me)
|
||||
{
|
||||
return new Regex(@"<[^>]*>").Replace(me, "");
|
||||
return Regexes.RegexHtmlTag.Replace(me, string.Empty);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 删除换行符
|
||||
/// </summary>
|
||||
/// <param name="me"></param>
|
||||
/// <returns></returns>
|
||||
public static string RemoveWrapped(this string me)
|
||||
{
|
||||
return me.Replace("\r", "").Replace("\n", "");
|
||||
return me.Replace("\r", string.Empty).Replace("\n", string.Empty);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 对一个字符串进行sha1 hash运算
|
||||
/// </summary>
|
||||
/// <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)
|
||||
{
|
||||
using var sha1 = SHA1.Create();
|
||||
return BitConverter.ToString(sha1.ComputeHash(e.GetBytes(me)))
|
||||
#pragma warning disable CA5350
|
||||
return BitConverter.ToString(SHA1.HashData(e.GetBytes(me)))
|
||||
#pragma warning restore CA5350
|
||||
.Replace("-", string.Empty)
|
||||
.ToLower(CultureInfo.CurrentCulture);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 蛇形命名
|
||||
/// </summary>
|
||||
/// <param name="me"></param>
|
||||
/// <returns></returns>
|
||||
public static string Snakecase(this string me)
|
||||
public static string SnakeCase(this string me)
|
||||
{
|
||||
return Regex.Replace(me, "([A-Z])", "-$1").ToLower().TrimStart('-');
|
||||
return Regexes.RegexUpLetter.Replace(me, "-$1").ToLower(CultureInfo.InvariantCulture).TrimStart('-');
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 截取指定长度的字符串,代替substring
|
||||
/// </summary>
|
||||
/// <param name="me"></param>
|
||||
/// <param name="startIndex"></param>
|
||||
/// <param name="length"></param>
|
||||
/// <returns></returns>
|
||||
public static string Sub(this string me, int startIndex, int length)
|
||||
{
|
||||
if (startIndex + length > me.Length) length = me.Length - startIndex;
|
||||
if (startIndex + length > me.Length) {
|
||||
length = me.Length - startIndex;
|
||||
}
|
||||
|
||||
return me.Substring(startIndex, length);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 纯文本字符串转html
|
||||
/// </summary>
|
||||
public static string Text2Html(this string me)
|
||||
{
|
||||
return $"<pre>{me}</pre>";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 首字母小写
|
||||
/// </summary>
|
||||
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>
|
||||
/// <param name="me"></param>
|
||||
/// <returns></returns>
|
||||
public static string TrimSpaces(this string me)
|
||||
{
|
||||
var ret = me.Replace(" ", " ");
|
||||
|
||||
// ReSharper disable once TailRecursiveCall
|
||||
return ret == me ? ret : TrimSpaces(ret);
|
||||
return ret == me ? ret : ret.TrimSpaces();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将\ux0000 、 %u0000 、 &#x0000; 编码转换成可读字符串
|
||||
/// </summary>
|
||||
public static string UnicodeDe(this string me)
|
||||
{
|
||||
const string replacement = "&#x$1;";
|
||||
if (me.Contains(@"\u")) {
|
||||
return Regexes.RegexBacksLantUnicode.Replace(me, replacement).HtmlDe();
|
||||
}
|
||||
|
||||
// ReSharper disable once ConvertIfStatementToReturnStatement
|
||||
#pragma warning disable IDE0046
|
||||
if (me.Contains("%u")) {
|
||||
#pragma warning restore IDE0046
|
||||
return Regexes.RegexPercentUnicode.Replace(me, replacement).HtmlDe();
|
||||
}
|
||||
|
||||
return me.HtmlDe();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// url编码
|
||||
/// </summary>
|
||||
/// <param name="me">字符串</param>
|
||||
/// <param name="me">me</param>
|
||||
/// <returns>url编码后的字符串</returns>
|
||||
public static string Url(this string me)
|
||||
{
|
||||
@ -573,10 +564,28 @@ public static class StringExtensions
|
||||
/// <summary>
|
||||
/// 解码url编码
|
||||
/// </summary>
|
||||
/// <param name="me">url编码后的字符串</param>
|
||||
/// <param name="me">me</param>
|
||||
/// <returns>解码后的原始字符串</returns>
|
||||
public static string UrlDe(this string me)
|
||||
{
|
||||
return Uri.UnescapeDataString(me);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// MD5 hmac编码
|
||||
/// </summary>
|
||||
/// <param name="me">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)
|
||||
{
|
||||
#pragma warning disable CA5351
|
||||
using var md5Hmac = new HMACMD5(e.GetBytes(key));
|
||||
#pragma warning restore CA5351
|
||||
return BitConverter.ToString(md5Hmac.ComputeHash(e.GetBytes(me)))
|
||||
.Replace("-", string.Empty)
|
||||
.ToLower(CultureInfo.CurrentCulture);
|
||||
}
|
||||
}
|
||||
#pragma warning restore CodeLinesAnalyzer
|
@ -1,13 +1,13 @@
|
||||
namespace NSExt.Extensions;
|
||||
|
||||
/// <summary>
|
||||
/// TypeExtensions
|
||||
/// </summary>
|
||||
public static class TypeExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// 搜索此成员的继承链以查找自定义属性,接口也会被搜索。
|
||||
/// </summary>
|
||||
/// <param name="me"></param>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <returns></returns>
|
||||
public static IEnumerable<T> GetCustomAttributesIncludingBaseInterfaces<T>(this Type me)
|
||||
{
|
||||
var attributeType = typeof(T);
|
||||
|
@ -1,12 +1,13 @@
|
||||
namespace NSExt.Extensions;
|
||||
|
||||
/// <summary>
|
||||
/// UriExtensions
|
||||
/// </summary>
|
||||
public static class UriExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// 移除url的Scheme
|
||||
/// </summary>
|
||||
/// <param name="me"></param>
|
||||
/// <returns></returns>
|
||||
public static string RemoveScheme(this Uri me)
|
||||
{
|
||||
return "//" + me.Authority + me.PathAndQuery;
|
||||
|
@ -1,9 +1,8 @@
|
||||
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;
|
@ -1,14 +1,10 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>net6.0;net7.0</TargetFrameworks>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Version>1.0.6</Version>
|
||||
</PropertyGroup>
|
||||
|
||||
<Import Project="../../code.quality.props"/>
|
||||
<Import Project="../../packable.props"/>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Extensions.Logging" Version="7.0.0"/>
|
||||
<PackageReference Include="Microsoft.Extensions.Logging" Version="8.0.0-rc.1.23419.4"/>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="../../logo.png" Pack="true" PackagePath=""/>
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
</Project>
|
Reference in New Issue
Block a user