Merge branch 'dev' of https://github.com/nsnail/ns-ext into dev

This commit is contained in:
2022-12-16 23:18:57 +08:00
35 changed files with 735 additions and 221 deletions

View File

@@ -1,5 +1,8 @@
namespace NSExt.Extensions;
/// <summary>
/// ByteExtensions
/// </summary>
public static class ByteExtensions
{
/// <summary>
@@ -36,17 +39,16 @@ public static class ByteExtensions
/// <summary>
/// 将字节数组转换成16进制字符串
/// </summary>
/// <param name="me"></param>
/// <param name="me">me</param>
/// <param name="upperCase">是否大写</param>
/// <param name="splitShar">字节间分隔符</param>
/// <param name="splitInterval">分隔符跳跃字节数</param>
/// <returns></returns>
public static string String(this IEnumerable<byte> me, bool upperCase = true, string splitShar = ""
, int splitInterval = 1)
{
var sb = new StringBuilder();
var i = 0;
foreach (var c in me.Select(x => x.ToString(upperCase ? "X2" : "x2"))) {
foreach (var c in me.Select(x => x.ToString(upperCase ? "X2" : "x2", CultureInfo.InvariantCulture))) {
if (i++ % splitInterval == 0) {
sb.Append(splitShar);
}

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,10 +1,15 @@
// ReSharper disable UnusedMember.Global
// ReSharper disable MemberCanBePrivate.Global
#pragma warning disable CA1720
using System.Security.Cryptography;
using System.Text.Json;
namespace NSExt.Extensions;
/// <summary>
/// StringExtensions
/// </summary>
public static partial class StringExtensions
{
private static readonly JsonSerializerOptions _defaultJsonSerializerOptions
@@ -15,11 +20,7 @@ public static partial class StringExtensions
/// </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;
@@ -36,11 +37,7 @@ public static partial class StringExtensions
/// </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;
@@ -87,7 +84,6 @@ public static partial class StringExtensions
/// <summary>
/// 将易于web传输的base64web字符串转换为原生base64
/// </summary>
/// <param name="me"></param>
/// <returns>原生base64</returns>
public static string Base64Sys(this string me)
{
@@ -97,7 +93,6 @@ public static partial class StringExtensions
/// <summary>
/// 将原生base64字符串转换成易于web传输的字符串
/// </summary>
/// <param name="me"></param>
/// <returns>易于web传输的字符串</returns>
public static string Base64Web(this string me)
{
@@ -184,10 +179,8 @@ public static partial 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);
}
@@ -195,11 +188,8 @@ public static partial class StringExtensions
/// <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;
}
@@ -218,7 +208,6 @@ public static partial class StringExtensions
/// 将字符串转为guid
/// </summary>
/// <param name="me">字符串</param>
/// <returns></returns>
public static Guid Guid(this string me)
{
return System.Guid.Parse(me);
@@ -229,7 +218,6 @@ public static partial 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;
@@ -245,7 +233,6 @@ public static partial class StringExtensions
{
return e.GetBytes(me);
}
//public static byte[] TextHex(this string me,)
/// <summary>
/// 将字符串转换成字节数组形式
@@ -260,7 +247,7 @@ public static partial class StringExtensions
/// <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>
@@ -276,8 +263,6 @@ public static partial class StringExtensions
/// <summary>
/// html编码
/// </summary>
/// <param name="me"></param>
/// <returns></returns>
public static string Html(this string me)
{
return HttpUtility.HtmlEncode(me);
@@ -338,8 +323,6 @@ public static partial 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);
@@ -349,7 +332,6 @@ public static partial class StringExtensions
/// 是否base64字符串
/// </summary>
/// <param name="me">字符串</param>
/// <returns></returns>
public static bool IsBase64String(this string me)
{
// 一个合法的Base64有着以下特征
@@ -375,15 +357,9 @@ public static partial class StringExtensions
/// <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>
@@ -393,7 +369,7 @@ public static partial 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 RegexMobile().Replace(me, "$1****$2");
}
/// <summary>
@@ -404,8 +380,7 @@ public static partial 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);
}
@@ -424,8 +399,6 @@ public static partial class StringExtensions
/// <summary>
/// null或空白字符
/// </summary>
/// <param name="me"></param>
/// <returns></returns>
public static bool NullOrWhiteSpace(this string me)
{
return string.IsNullOrWhiteSpace(me);
@@ -471,17 +444,15 @@ public static partial class StringExtensions
/// <returns>处理之后的字符串</returns>
public static string RemoveHtmlTag(this string me)
{
return new Regex(@"<[^>]*>").Replace(me, "");
return 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>
@@ -492,8 +463,7 @@ public static partial 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);
}
@@ -501,20 +471,14 @@ public static partial class StringExtensions
/// <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 RegexUpperCaseLetter().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) {
@@ -527,8 +491,6 @@ public static partial class StringExtensions
/// <summary>
/// 纯文本字符串转html
/// </summary>
/// <param name="me"></param>
/// <returns></returns>
public static string Text2Html(this string me)
{
return $"<pre>{me}</pre>";
@@ -537,28 +499,22 @@ public static partial 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 : ret.TrimSpaces();
}
/// <summary>
/// 将\ux0000 、 %u0000 、 &#x0000; 编码转换成可读字符串
/// 将\ux0000 、 %u0000 、 &amp;#x0000; 编码转换成可读字符串
/// </summary>
/// <param name="me"></param>
/// <returns></returns>
public static string UnicodeDe(this string me)
{
const string replacement = "&#x$1;";
if (me.Contains(@"\u")) {
return RegexBacksLantUnicode().Replace(me, replacement).HtmlDe();
}
return me.Contains(@"%u") ? RegexPercentUnicode().Replace(me, replacement).HtmlDe() : me.HtmlDe();
return me.Contains(@"\u") ? RegexBacksLantUnicode().Replace(me, replacement).HtmlDe() :
me.Contains(@"%u") ? RegexPercentUnicode().Replace(me, replacement).HtmlDe() : me.HtmlDe();
}
/// <summary>
@@ -599,6 +555,15 @@ public static partial class StringExtensions
[GeneratedRegex("\\\\u([a-fA-F0-9]{4})")]
private static partial Regex RegexBacksLantUnicode();
[GeneratedRegex("<[^>]*>")]
private static partial Regex RegexHtmlTag();
[GeneratedRegex("^(\\d{3})\\d{4}(\\d{4})$")]
private static partial Regex RegexMobile();
[GeneratedRegex("\\\\u([a-fA-F0-9]{4})")]
private static partial Regex RegexPercentUnicode();
[GeneratedRegex("([A-Z])")]
private static partial Regex RegexUpperCaseLetter();
}

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,7 +1,8 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<TargetFrameworks>net7.0</TargetFrameworks>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
</PropertyGroup>
<ItemGroup>
@@ -12,5 +13,5 @@
</PackageReference>
</ItemGroup>
<Import Project="../CodeQuality.props"/>
</Project>