mirror of
https://github.com/BeyondDimension/SteamTools.git
synced 2026-10-27 04:41:15 +08:00
V1.2 新构架
This commit is contained in:
@@ -0,0 +1,26 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// ReSharper disable once CheckNamespace
|
||||
namespace System
|
||||
{
|
||||
public static class ByteArrayExtensions
|
||||
{
|
||||
public static sbyte[] ToSByteArray(this byte[] buffer)
|
||||
{
|
||||
ReadOnlySpan<byte> _buffer = buffer;
|
||||
return _buffer.ToSByteArray();
|
||||
}
|
||||
|
||||
public static sbyte[] ToSByteArray(this ReadOnlySpan<byte> buffer)
|
||||
=> MemoryMarshal.Cast<byte, sbyte>(buffer).ToArray();
|
||||
|
||||
public static byte[] ToByteArray(this sbyte[] buffer)
|
||||
{
|
||||
ReadOnlySpan<sbyte> _buffer = buffer;
|
||||
return _buffer.ToByteArray();
|
||||
}
|
||||
|
||||
public static byte[] ToByteArray(this ReadOnlySpan<sbyte> buffer)
|
||||
=> MemoryMarshal.Cast<sbyte, byte>(buffer).ToArray();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
using System.Properties;
|
||||
|
||||
// ReSharper disable once CheckNamespace
|
||||
namespace System
|
||||
{
|
||||
/// <summary>
|
||||
/// Enum 扩展 <see cref="DayOfWeek"/>
|
||||
/// </summary>
|
||||
public static partial class DayOfWeekEnumExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// 将 <see cref="DayOfWeek"/>(周) 转换为字符串
|
||||
/// </summary>
|
||||
/// <param name="dayOfWeek"></param>
|
||||
/// <param name="format_short_or_long">使用[(<see langword="true"/>)短]或[(<see langword="false"/>)长]的格式,默认使用长格式</param>
|
||||
/// <returns></returns>
|
||||
public static string ToString2(this DayOfWeek dayOfWeek, bool format_short_or_long = false)
|
||||
=> dayOfWeek switch
|
||||
{
|
||||
DayOfWeek.Monday => format_short_or_long ? SR.DayOfWeek_S1 : SR.DayOfWeek_L1,
|
||||
DayOfWeek.Tuesday => format_short_or_long ? SR.DayOfWeek_S2 : SR.DayOfWeek_L2,
|
||||
DayOfWeek.Wednesday => format_short_or_long ? SR.DayOfWeek_S3 : SR.DayOfWeek_L3,
|
||||
DayOfWeek.Thursday => format_short_or_long ? SR.DayOfWeek_S4 : SR.DayOfWeek_L4,
|
||||
DayOfWeek.Friday => format_short_or_long ? SR.DayOfWeek_S5 : SR.DayOfWeek_L5,
|
||||
DayOfWeek.Saturday => format_short_or_long ? SR.DayOfWeek_S6 : SR.DayOfWeek_L6,
|
||||
DayOfWeek.Sunday => format_short_or_long ? SR.DayOfWeek_S0 : SR.DayOfWeek_L0,
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(dayOfWeek), dayOfWeek, null),
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
// ReSharper disable once CheckNamespace
|
||||
namespace System
|
||||
{
|
||||
public static partial class EnumExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// 返回一个布尔值,该值指示给定的整数值或其名称字符串是否存在于指定的枚举中
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
/// <returns>如果 enumType 中的某个常量的值等于 value,则为 <see langword="true"/>;否则为 <see langword="false"/></returns>
|
||||
public static bool IsDefined(this Enum value) => Enum.IsDefined(value.GetType(), value);
|
||||
|
||||
public static TEnum ConvertToEnum<TEnum>(this int value)
|
||||
where TEnum : struct, IConvertible
|
||||
=> Enum2.ConvertToEnum<TEnum, int>(value);
|
||||
|
||||
public static int ConvertToInt32<TEnum>(this TEnum value)
|
||||
where TEnum : struct, IConvertible
|
||||
=> Enum2.ConvertToEnum<int, TEnum>(value);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Properties;
|
||||
|
||||
// ReSharper disable once CheckNamespace
|
||||
namespace System
|
||||
{
|
||||
public static class EnumerableExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// 通过使用相应类型的默认相等比较器对序列的元素进行比较,以确定两个序列是否相等
|
||||
/// </summary>
|
||||
/// <typeparam name="TSource">输入序列中的元素的类型</typeparam>
|
||||
/// <param name="first">一个用于比较 second 的 <see cref="IEnumerable{T}"/></param>
|
||||
/// <param name="second">要与第一个序列进行比较的 <see cref="IEnumerable{T}"/></param>
|
||||
/// <returns></returns>
|
||||
public static bool SequenceEqual_Nullable<TSource>(this IEnumerable<TSource>? first, IEnumerable<TSource>? second)
|
||||
{
|
||||
if (first == null) return second == null;
|
||||
if (second == null) return first == null;
|
||||
return first.SequenceEqual(second);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 确定序列是否包含任何元素
|
||||
/// </summary>
|
||||
/// <typeparam name="TSource">source 的元素类型</typeparam>
|
||||
/// <param name="source">要检查是否为空的 <see cref="IEnumerable{T}"/></param>
|
||||
/// <returns>如果源序列包含任何元素,则为 <see langword="true"/>;否则为 <see langword="false"/></returns>
|
||||
public static bool Any_Nullable<TSource>(this IEnumerable<TSource>? source)
|
||||
{
|
||||
if (source == null) return false;
|
||||
return source.Any();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 确定序列是否包含任何元素(带条件)
|
||||
/// </summary>
|
||||
/// <typeparam name="TSource"></typeparam>
|
||||
/// <param name="source"></param>
|
||||
/// <param name="predicate"></param>
|
||||
/// <returns></returns>
|
||||
public static bool Any_Nullable<TSource>(this IEnumerable<TSource>? source, Func<TSource, bool> predicate)
|
||||
{
|
||||
if (source == null) return false;
|
||||
return source.Any(predicate);
|
||||
}
|
||||
|
||||
public static Dictionary<TKey, TValue> ReverseKeyValue<TValue, TKey>(this IEnumerable<KeyValuePair<TValue, TKey>> source) where TKey : notnull
|
||||
=> source.ToDictionary(k => k.Value, v => v.Key);
|
||||
|
||||
/// <inheritdoc cref="List{T}.AddRange(IEnumerable{T})"/>
|
||||
public static void AddRange<T>(this IList<T> ts, IEnumerable<T> collection)
|
||||
{
|
||||
if (ts is List<T> list)
|
||||
{
|
||||
list.AddRange(collection);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ts.IsReadOnly) throw new NotSupportedException(SR.NotSupported_FixedSizeCollection);
|
||||
var c = collection == ts ? collection.ToArray() : collection;
|
||||
foreach (var item in c)
|
||||
{
|
||||
ts.Add(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
using System.Threading.Tasks;
|
||||
|
||||
// ReSharper disable once CheckNamespace
|
||||
namespace System
|
||||
{
|
||||
public static class ExceptionExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// 是否为取消操作异常
|
||||
/// </summary>
|
||||
/// <param name="exception"></param>
|
||||
/// <returns></returns>
|
||||
public static bool IsCanceledException(this Exception e)
|
||||
{
|
||||
if (e is TaskCanceledException || e is OperationCanceledException)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (DI.Platform == Platform.Android)
|
||||
{
|
||||
if (e.Message == "Canceled" && e.GetType().FullName == "Java.IO.IOException")
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
using System.Common;
|
||||
|
||||
// ReSharper disable once CheckNamespace
|
||||
namespace System
|
||||
{
|
||||
public static class GuidExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// 返回 <see cref="Guid"/> 结构的此实例值的字符串表示形式(格式N)
|
||||
/// </summary>
|
||||
/// <param name="guid"></param>
|
||||
/// <returns></returns>
|
||||
public static string ToStringN(this Guid guid) => guid.ToString(Constants.N);
|
||||
|
||||
/// <summary>
|
||||
/// 返回 <see cref="Guid"/> 结构的此实例值的字符串表示形式(格式N)
|
||||
/// </summary>
|
||||
/// <param name="guid"></param>
|
||||
/// <returns></returns>
|
||||
public static string? ToStringN(this Guid? guid) => guid.HasValue ? guid.Value.ToStringN() : null;
|
||||
|
||||
static bool TryParseGuid_Format_D(string? input, out Guid result) => Guid.TryParse(input, out result);
|
||||
|
||||
static bool TryParseGuid_Format_N(string? input, out Guid result) => Guid.TryParseExact(input, Constants.N, out result);
|
||||
|
||||
static bool TryParseGuid(string? input, out Guid result, bool isFormatNFirst)
|
||||
{
|
||||
if (isFormatNFirst)
|
||||
{
|
||||
if (TryParseGuid_Format_N(input, out result))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else if (TryParseGuid_Format_D(input, out result))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (TryParseGuid_Format_D(input, out result))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else if (TryParseGuid_Format_N(input, out result))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将包含 <see cref="Guid"/> 表示形式的指定只读字符范围转换为等效的 Guid 结构
|
||||
/// <para>优先尝试使用格式D</para>
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <param name="result"></param>
|
||||
/// <returns></returns>
|
||||
public static bool TryParseGuid(this string? input, out Guid result) => TryParseGuid(input, out result, false);
|
||||
|
||||
/// <summary>
|
||||
/// 将包含 <see cref="Guid"/> 表示形式的指定只读字符范围转换为等效的 Guid 结构
|
||||
/// <para>优先尝试使用格式D</para>
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
public static Guid? TryParseGuid(this string? input) => TryParseGuid(input, out var result) ? result : default;
|
||||
|
||||
/// <summary>
|
||||
/// 将包含 <see cref="Guid"/> 表示形式的指定只读字符范围转换为等效的 Guid 结构
|
||||
/// <para>优先尝试使用格式N</para>
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <param name="result"></param>
|
||||
/// <returns></returns>
|
||||
public static bool TryParseGuidN(this string? input, out Guid result) => TryParseGuid(input, out result, true);
|
||||
|
||||
/// <summary>
|
||||
/// 将包含 <see cref="Guid"/> 表示形式的指定只读字符范围转换为等效的 Guid 结构
|
||||
/// <para>优先尝试使用格式N</para>
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
public static Guid? TryParseGuidN(this string? input) => TryParseGuidN(input, out var result) ? result : default;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
// ReSharper disable once CheckNamespace
|
||||
namespace System
|
||||
{
|
||||
public static class ObjectExtensions
|
||||
{
|
||||
public static T ThrowIsNull<T>(this T? t, string parameterName) where T : class
|
||||
{
|
||||
if (t == null)
|
||||
{
|
||||
throw new ArgumentNullException(parameterName);
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
||||
public static T ThrowIsNull<T>(this T? t, string parameterName) where T : struct
|
||||
{
|
||||
if (!t.HasValue)
|
||||
{
|
||||
throw new ArgumentNullException(parameterName);
|
||||
}
|
||||
return t.Value;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
using Xamarin.Essentials;
|
||||
|
||||
// ReSharper disable once CheckNamespace
|
||||
namespace System
|
||||
{
|
||||
/// <summary>
|
||||
/// Enum 扩展 <see cref="PermissionStatus"/>
|
||||
/// </summary>
|
||||
public static class PermissionStatusEnumExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// 权限是否已授予
|
||||
/// </summary>
|
||||
/// <param name="permissionStatus"></param>
|
||||
/// <returns></returns>
|
||||
public static bool IsOk(this PermissionStatus permissionStatus)
|
||||
=> permissionStatus == PermissionStatus.Granted;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
|
||||
// ReSharper disable once CheckNamespace
|
||||
namespace System
|
||||
{
|
||||
public static class ReflectionExtensions
|
||||
{
|
||||
const string TAG = "ReflectionEx";
|
||||
|
||||
/// <summary>
|
||||
/// 检索应用于指定程序集的指定类型的自定义特性。
|
||||
/// <para>如果发生 <see cref="FileNotFoundException"/> 将返回 <see langword="null"/></para>
|
||||
/// </summary>
|
||||
/// <param name="assembly"></param>
|
||||
/// <param name="attrType"></param>
|
||||
/// <returns></returns>
|
||||
public static Attribute[]? GetCustomAttributesSafe(this Assembly assembly, Type attrType)
|
||||
{
|
||||
try
|
||||
{
|
||||
return assembly.GetCustomAttributes(attrType).ToArray();
|
||||
}
|
||||
catch (FileNotFoundException)
|
||||
{
|
||||
// Sometimes the previewer doesn't actually have everything required for these loads to work
|
||||
Log.Warn(TAG, "Could not load assembly: {0} for Attribute {1} | Some renderers may not be loaded", assembly.FullName, attrType.FullName);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static T GetRequiredCustomAttribute<T>(this Assembly assembly) where T : Attribute
|
||||
{
|
||||
var requiredCustomAttribute = assembly.GetCustomAttribute<T>();
|
||||
if (requiredCustomAttribute == null)
|
||||
throw new NullReferenceException(nameof(requiredCustomAttribute));
|
||||
return requiredCustomAttribute;
|
||||
}
|
||||
|
||||
static bool IsNullableType(this Type t)
|
||||
{
|
||||
return t.IsGenericType && t.GetGenericTypeDefinition() == typeof(Nullable<>);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 类型是否为 <see cref="Nullable{T}"/> 可空类型
|
||||
/// </summary>
|
||||
/// <param name="t"></param>
|
||||
/// <returns></returns>
|
||||
public static bool IsNullable(this Type t)
|
||||
{
|
||||
if (t.IsValueType) // 值类型(struct)进行可空判断
|
||||
{
|
||||
return IsNullableType(t);
|
||||
}
|
||||
return true; // 引用类型(class)都可空
|
||||
}
|
||||
|
||||
public static bool IsStatic(this Type t) => t.IsAbstract && t.IsSealed;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
// ReSharper disable once CheckNamespace
|
||||
namespace System
|
||||
{
|
||||
public static partial class SingleExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// (向下取整)返回小于或等于指定数字的最大整数值
|
||||
/// </summary>
|
||||
/// <param name="f"></param>
|
||||
/// <returns></returns>
|
||||
public static int FloorToInt(this float f) => (int)MathF.Floor(f);
|
||||
|
||||
/// <summary>
|
||||
/// (进一法)返回大于或等于指定数字的最小整数值
|
||||
/// </summary>
|
||||
/// <param name="f"></param>
|
||||
/// <returns></returns>
|
||||
public static int CeilingToInt(this float f) => (int)MathF.Ceiling(f);
|
||||
|
||||
/// <summary>
|
||||
/// 将值舍入到最接近的整数或指定的小数位数
|
||||
/// </summary>
|
||||
/// <param name="f"></param>
|
||||
/// <param name="mode">在两个数字之间时如何舍入的规范</param>
|
||||
/// <returns></returns>
|
||||
public static int RoundToInt(this float f, MidpointRounding mode) => (int)MathF.Round(f, mode);
|
||||
|
||||
/// <summary>
|
||||
/// (五舍六入)将值舍入到最接近的整数或指定的小数位数
|
||||
/// </summary>
|
||||
/// <param name="f"></param>
|
||||
/// <returns></returns>
|
||||
public static int RoundToInt(this float f) => (int)MathF.Round(f);
|
||||
|
||||
/// <summary>
|
||||
/// (四舍五入)将值舍入到最接近的整数或指定的小数位数
|
||||
/// </summary>
|
||||
/// <param name="f"></param>
|
||||
/// <returns></returns>
|
||||
public static int Round2ToInt(this float f) => (int)MathF.Round(f, MidpointRounding.AwayFromZero);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,219 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
// ReSharper disable once CheckNamespace
|
||||
namespace System
|
||||
{
|
||||
public static partial class StringExtensions
|
||||
{
|
||||
#region System.String 内置函数增强型扩展(用于取代原有函数)
|
||||
|
||||
#region IndexOf
|
||||
|
||||
/// <summary>
|
||||
/// 报告指定 Unicode 字符在此字符串中的第一个匹配项的从零开始的索引。
|
||||
/// <para>注意:如果 value 仅为英文字符或数字符号,则使用原函数 <see cref="string.IndexOf(char)"/></para>
|
||||
/// </summary>
|
||||
/// <param name="str"></param>
|
||||
/// <param name="value">要查找的 Unicode 字符。</param>
|
||||
/// <returns>如果找到该字符,则为 value 的从零开始的索引位置;如果未找到,则为 -1。</returns>
|
||||
public static int IndexOf_(this string str, char value) => DI.IsRunningOnMono ? str.IndexOf(value) : str.IndexOf(value, StringComparison.Ordinal);
|
||||
|
||||
/// <summary>
|
||||
/// 报告指定 Unicode 字符在此字符串中的第一个匹配项的从零开始的索引。
|
||||
/// <para>注意:如果 value 仅为英文字符或数字符号,则使用原函数 <see cref="string.IndexOf(char)"/></para>
|
||||
/// </summary>
|
||||
/// <param name="str"></param>
|
||||
/// <param name="value">要查找的 Unicode 字符。</param>
|
||||
/// <returns>如果找到该字符,则为 value 的从零开始的索引位置;如果未找到,则为 -1。</returns>
|
||||
public static int IndexOf_Nullable(this string? str, char value)
|
||||
{
|
||||
if (str == null) return -1;
|
||||
return IndexOf_(str, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 报告指定字符串在此实例中的第一个匹配项的从零开始的索引。
|
||||
/// </summary>
|
||||
/// <param name="str"></param>
|
||||
/// <param name="value">要搜寻的字符串。</param>
|
||||
/// <returns>如果找到该字符串,则为 value 的从零开始的索引位置;如果未找到该字符串,则为 -1。 如果 value 为 Empty,则返回值为 0。</returns>
|
||||
public static int IndexOf_(this string str, string value) => str.IndexOf(value, StringComparison.Ordinal);
|
||||
|
||||
/// <summary>
|
||||
/// 报告指定字符串在此实例中的第一个匹配项的从零开始的索引。
|
||||
/// </summary>
|
||||
/// <param name="str"></param>
|
||||
/// <param name="value">要搜寻的字符串。</param>
|
||||
/// <returns>如果找到该字符串,则为 value 的从零开始的索引位置;如果未找到该字符串,则为 -1。 如果 value 为 Empty,则返回值为 0。</returns>
|
||||
public static int IndexOf_Nullable(this string? str, string value)
|
||||
{
|
||||
if (str == null) return -1;
|
||||
return IndexOf_(str, value);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Contains
|
||||
|
||||
/// <summary>
|
||||
/// 返回一个值,该值指示指定的字符是否出现在此字符串中。
|
||||
/// </summary>
|
||||
/// <param name="str"></param>
|
||||
/// <param name="value">要查找的字符。</param>
|
||||
/// <returns>如果 value 参数在此字符串中出现,则为 true;否则为 false。</returns>
|
||||
public static bool Contains_(this string str, char value) => str.Contains(value, StringComparison.Ordinal);
|
||||
|
||||
/// <summary>
|
||||
/// 返回一个值,该值指示指定的字符是否出现在此字符串中。
|
||||
/// </summary>
|
||||
/// <param name="str"></param>
|
||||
/// <param name="value">要查找的字符。</param>
|
||||
/// <returns>如果 value 参数在此字符串中出现,则为 true;否则为 false。</returns>
|
||||
public static bool Contains_Nullable(this string? str, char value)
|
||||
{
|
||||
if (str == null) return false;
|
||||
return Contains_(str, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 返回一个值,该值指示指定的子串是否出现在此字符串中。
|
||||
/// </summary>
|
||||
/// <param name="str"></param>
|
||||
/// <param name="value">要搜寻的字符串。</param>
|
||||
/// <returns>如果 true 参数出现在此字符串中,或者 value 为空字符串 (""),则为 value;否则为 false。</returns>
|
||||
public static bool Contains_(this string str, string value) => str.Contains(value, StringComparison.Ordinal);
|
||||
|
||||
/// <summary>
|
||||
/// 返回一个值,该值指示指定的子串是否出现在此字符串中。
|
||||
/// </summary>
|
||||
/// <param name="str"></param>
|
||||
/// <param name="value">要搜寻的字符串。</param>
|
||||
/// <returns>如果 true 参数出现在此字符串中,或者 value 为空字符串 (""),则为 value;否则为 false。</returns>
|
||||
public static bool Contains_Nullable(this string? str, string value)
|
||||
{
|
||||
if (str == null) return false;
|
||||
return Contains_(str, value);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// 将版本号字符串转换为 <see cref="Version"/> 对象,传入的字符串不能为 <see langword="null"/>
|
||||
/// </summary>
|
||||
/// <param name="version"></param>
|
||||
/// <returns></returns>
|
||||
public static Version? VersionTryParse(string version)
|
||||
{
|
||||
var versionChars = GetVersion(version).ToArray();
|
||||
if (versionChars.Any() && Version.TryParse(new string(versionChars), out var versionObj))
|
||||
{
|
||||
return versionObj;
|
||||
}
|
||||
static IEnumerable<char> GetVersion(string s)
|
||||
{
|
||||
var dianCount = 0;
|
||||
var findChar = false;
|
||||
foreach (var item in s)
|
||||
{
|
||||
var isDian = item == '.';
|
||||
if (isDian)
|
||||
{
|
||||
if (dianCount++ >= 3)
|
||||
{
|
||||
yield break;
|
||||
}
|
||||
}
|
||||
if (isDian || item >= '0' && item <= '9')
|
||||
{
|
||||
findChar = true;
|
||||
yield return item;
|
||||
}
|
||||
else if (findChar)
|
||||
{
|
||||
yield break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
#region TryParse
|
||||
|
||||
/// <summary>
|
||||
/// 尝试将数字的字符串表示形式转换为它的等效 32 位有符号整数
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
/// <returns></returns>
|
||||
public static int? TryParseInt32(this string value) => int.TryParse(value, out var temp) ? temp as int? : null;
|
||||
|
||||
#endregion
|
||||
|
||||
public static string TrimStart(this string s, string trimString)
|
||||
{
|
||||
if (trimString.StartsWith(trimString))
|
||||
{
|
||||
return s[trimString.Length..];
|
||||
}
|
||||
else
|
||||
{
|
||||
return s;
|
||||
}
|
||||
}
|
||||
|
||||
public static string TrimEnd(this string s, string trimString)
|
||||
{
|
||||
if (trimString.EndsWith(trimString))
|
||||
{
|
||||
return s.Substring(0, s.Length - trimString.Length);
|
||||
}
|
||||
else
|
||||
{
|
||||
return s;
|
||||
}
|
||||
}
|
||||
|
||||
#region 数字字母判断
|
||||
|
||||
/// <summary>
|
||||
/// 字符串是否是一个数字(可以零开头 无符号不能+-.)
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
public static bool IsDigital(this string input) => input?.All(IsDigital) ?? false;
|
||||
|
||||
public static bool IsDigital(this char input) => input >= '0' && input <= '9';
|
||||
|
||||
/// <summary>
|
||||
/// 字符串内含有数字
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
public static bool HasDigital(this string input) => input?.Any(x => x >= '0' && x <= '9') ?? false;
|
||||
|
||||
/// <summary>
|
||||
/// 字符串内含有小写字母
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
public static bool HasLowerLetter(this string input) => input?.Any(x => x >= 'a' && x <= 'z') ?? false;
|
||||
|
||||
/// <summary>
|
||||
/// 字符串内含有大写字母
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
public static bool HasUpperLetter(this string input) => input?.Any(x => x >= 'A' && x <= 'Z') ?? false;
|
||||
|
||||
/// <summary>
|
||||
/// 字符串内含有其他字符
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
public static bool HasOther(this string input) => input?.Any(x => !(x >= 'a' && x <= 'z' || x >= 'A' && x <= 'Z' || x >= '0' && x <= '9')) ?? false;
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
// https://github.com/aspnet/AspNetIdentity/blob/master/src/Microsoft.AspNet.Identity.Core/AsyncHelper.cs
|
||||
using System.Globalization;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
// ReSharper disable once CheckNamespace
|
||||
namespace System
|
||||
{
|
||||
public static class TaskExtensions
|
||||
{
|
||||
static readonly TaskFactory _myTaskFactory = new TaskFactory(CancellationToken.None,
|
||||
TaskCreationOptions.None, TaskContinuationOptions.None, TaskScheduler.Default);
|
||||
|
||||
public static TResult RunSync<TResult>(this Func<Task<TResult>> func)
|
||||
{
|
||||
var cultureUi = CultureInfo.CurrentUICulture;
|
||||
var culture = CultureInfo.CurrentCulture;
|
||||
return _myTaskFactory.StartNew(() =>
|
||||
{
|
||||
Thread.CurrentThread.CurrentCulture = culture;
|
||||
Thread.CurrentThread.CurrentUICulture = cultureUi;
|
||||
return func();
|
||||
}).Unwrap().GetAwaiter().GetResult();
|
||||
}
|
||||
|
||||
public static void RunSync(this Func<Task> func)
|
||||
{
|
||||
var cultureUi = CultureInfo.CurrentUICulture;
|
||||
var culture = CultureInfo.CurrentCulture;
|
||||
_myTaskFactory.StartNew(() =>
|
||||
{
|
||||
Thread.CurrentThread.CurrentCulture = culture;
|
||||
Thread.CurrentThread.CurrentUICulture = cultureUi;
|
||||
return func();
|
||||
}).Unwrap().GetAwaiter().GetResult();
|
||||
}
|
||||
|
||||
public static TResult RunSync<TResult>(this Func<ValueTask<TResult>> func)
|
||||
{
|
||||
var cultureUi = CultureInfo.CurrentUICulture;
|
||||
var culture = CultureInfo.CurrentCulture;
|
||||
return _myTaskFactory.StartNew(() =>
|
||||
{
|
||||
Thread.CurrentThread.CurrentCulture = culture;
|
||||
Thread.CurrentThread.CurrentUICulture = cultureUi;
|
||||
return func().AsTask();
|
||||
}).Unwrap().GetAwaiter().GetResult();
|
||||
}
|
||||
|
||||
public static void RunSync(this Func<ValueTask> func)
|
||||
{
|
||||
var cultureUi = CultureInfo.CurrentUICulture;
|
||||
var culture = CultureInfo.CurrentCulture;
|
||||
_myTaskFactory.StartNew(() =>
|
||||
{
|
||||
Thread.CurrentThread.CurrentCulture = culture;
|
||||
Thread.CurrentThread.CurrentUICulture = cultureUi;
|
||||
return func().AsTask();
|
||||
}).Unwrap().GetAwaiter().GetResult();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user