添加项目文件。
This commit is contained in:
52
common/Tnb.Common/Extension/BooleanExtensions.cs
Normal file
52
common/Tnb.Common/Extension/BooleanExtensions.cs
Normal file
@@ -0,0 +1,52 @@
|
||||
using JNPF.DependencyInjection;
|
||||
|
||||
namespace JNPF.Common.Extension;
|
||||
|
||||
/// <summary>
|
||||
/// 布尔值<see cref="bool"/>类型的扩展辅助操作类.
|
||||
/// </summary>
|
||||
[SuppressSniffer]
|
||||
public static class BooleanExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// 把布尔值转换为小写字符串.
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
public static string ToLower(this bool value)
|
||||
{
|
||||
return value.ToString().ToLower();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 如果条件成立,则抛出异常.
|
||||
/// </summary>
|
||||
public static void TrueThrow(this bool flag, Exception exception)
|
||||
{
|
||||
if (flag)
|
||||
throw exception;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取布尔值.
|
||||
/// </summary>
|
||||
private static bool? GetBool(this object data)
|
||||
{
|
||||
switch (data.ToString().Trim().ToLower())
|
||||
{
|
||||
case "0":
|
||||
return false;
|
||||
case "1":
|
||||
return true;
|
||||
case "是":
|
||||
return true;
|
||||
case "否":
|
||||
return false;
|
||||
case "yes":
|
||||
return true;
|
||||
case "no":
|
||||
return false;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
157
common/Tnb.Common/Extension/ConcurrentDictionaryExtensions.cs
Normal file
157
common/Tnb.Common/Extension/ConcurrentDictionaryExtensions.cs
Normal file
@@ -0,0 +1,157 @@
|
||||
using JNPF.DependencyInjection;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Dynamic;
|
||||
using System.Reflection;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace JNPF.Common.Extension;
|
||||
|
||||
/// <summary>
|
||||
/// 多线程下的字典辅助扩展方法.
|
||||
/// </summary>
|
||||
[SuppressSniffer]
|
||||
public static class ConcurrentDictionaryExtensions
|
||||
{
|
||||
private static readonly ConcurrentDictionary<RuntimeTypeHandle, PropertyInfo[]> _dynamicObjectProperties = new ConcurrentDictionary<RuntimeTypeHandle, PropertyInfo[]>();
|
||||
|
||||
/// <summary>
|
||||
/// 获取object属性.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">对象类型.</typeparam>
|
||||
/// <returns></returns>
|
||||
private static PropertyInfo[] GetObjectProperties<T>()
|
||||
{
|
||||
var type = typeof(T);
|
||||
var key = type.TypeHandle;
|
||||
PropertyInfo[] queryPts = null;
|
||||
|
||||
_dynamicObjectProperties.TryGetValue(key, out queryPts);
|
||||
|
||||
if (queryPts == null)
|
||||
{
|
||||
queryPts = type.GetProperties();
|
||||
_dynamicObjectProperties.TryAdd(key, queryPts);
|
||||
}
|
||||
|
||||
return queryPts;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 合并2个对象.
|
||||
/// </summary>
|
||||
/// <typeparam name="TSource">对象1类型.</typeparam>
|
||||
/// <typeparam name="TTarget">对象2类型.</typeparam>
|
||||
/// <param name="s">对象1实例.</param>
|
||||
/// <param name="t">对象2实例.</param>
|
||||
/// <returns>合并后的动态对象.</returns>
|
||||
public static IDictionary<string, object> MergerObject<TSource, TTarget>(TSource s, TTarget t)
|
||||
{
|
||||
var targetPts = GetObjectProperties<TSource>();
|
||||
|
||||
PropertyInfo[] mergerPts = null;
|
||||
var _type = t.GetType();
|
||||
mergerPts = _type.Name.Contains("<>") ? _type.GetProperties() : GetObjectProperties<TTarget>();
|
||||
|
||||
var dynamicResult = new ExpandoObject() as IDictionary<string, object>;
|
||||
|
||||
foreach (var p in targetPts)
|
||||
{
|
||||
var attributes = p.GetCustomAttributes(typeof(JsonIgnoreAttribute), true);
|
||||
if (attributes.FirstOrDefault() != null) continue;
|
||||
|
||||
dynamicResult.Add(p.Name, p.GetValue(s, null));
|
||||
}
|
||||
|
||||
foreach (var p in mergerPts)
|
||||
{
|
||||
var attributes = p.GetCustomAttributes(typeof(JsonIgnoreAttribute), true);
|
||||
if (attributes.FirstOrDefault() != null) continue;
|
||||
|
||||
dynamicResult.Add(p.Name, p.GetValue(t, null));
|
||||
}
|
||||
|
||||
return dynamicResult;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 对象2值赋值至对象1内.
|
||||
/// </summary>
|
||||
/// <typeparam name="TSource">对象1类型.</typeparam>
|
||||
/// <typeparam name="TTarget">对象2类型.</typeparam>
|
||||
/// <param name="s">对象1实例.</param>
|
||||
/// <param name="t">对象2实例.</param>
|
||||
/// <returns>合并后的动态对象.</returns>
|
||||
public static IDictionary<string, object> AssignmentObject<TSource, TTarget>(TSource s, TTarget t)
|
||||
{
|
||||
var targetPts = GetObjectProperties<TSource>();
|
||||
|
||||
PropertyInfo[] mergerPts = null;
|
||||
var _type = t.GetType();
|
||||
mergerPts = _type.Name.Contains("<>") ? _type.GetProperties() : GetObjectProperties<TTarget>();
|
||||
|
||||
var dynamicResult = new ExpandoObject() as IDictionary<string, object>;
|
||||
|
||||
foreach (var p in targetPts)
|
||||
{
|
||||
var attributes = p.GetCustomAttributes(typeof(JsonIgnoreAttribute), true);
|
||||
if (attributes.FirstOrDefault() != null) continue;
|
||||
|
||||
dynamicResult.Add(p.Name, p.GetValue(s, null));
|
||||
}
|
||||
|
||||
foreach (var p in mergerPts)
|
||||
{
|
||||
var attributes = p.GetCustomAttributes(typeof(JsonIgnoreAttribute), true);
|
||||
if (attributes.FirstOrDefault() != null) continue;
|
||||
|
||||
dynamicResult[p.Name] = p.GetValue(t, null);
|
||||
}
|
||||
|
||||
return dynamicResult;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 合并2个对象.
|
||||
/// var result = MergerListObject<KeyValue, dynamic>(kk, new { p = new KeyValue2() { key2 = "dadad", key3 = "biubiu" } });
|
||||
/// </summary>
|
||||
/// <typeparam name="TSource">对象1类型.</typeparam>
|
||||
/// <typeparam name="TTarget">对象2类型.</typeparam>
|
||||
/// <param name="s">对象1实例.</param>
|
||||
/// <param name="t">对象2实例.</param>
|
||||
/// <returns>合并后的动态对象.</returns>
|
||||
public static List<IDictionary<string, object>> MergerListObject<TSource, TTarget>(List<TSource> s, TTarget t)
|
||||
{
|
||||
var targetPts = GetObjectProperties<TSource>();
|
||||
|
||||
PropertyInfo[] mergerPts = null;
|
||||
var _type = t.GetType();
|
||||
mergerPts = _type.Name.Contains("<>") ? _type.GetProperties() : GetObjectProperties<TTarget>();
|
||||
|
||||
var result = new List<IDictionary<string, object>>();
|
||||
|
||||
s.ForEach(x =>
|
||||
{
|
||||
var dynamicResult = new ExpandoObject() as IDictionary<string, object>;
|
||||
|
||||
foreach (var p in targetPts)
|
||||
{
|
||||
var attributes = p.GetCustomAttributes(typeof(JsonIgnoreAttribute), true);
|
||||
if (attributes.FirstOrDefault() != null) continue;
|
||||
|
||||
dynamicResult.Add(p.Name, p.GetValue(x, null));
|
||||
}
|
||||
|
||||
foreach (var p in mergerPts)
|
||||
{
|
||||
var attributes = p.GetCustomAttributes(typeof(JsonIgnoreAttribute), true);
|
||||
if (attributes.FirstOrDefault() != null) continue;
|
||||
|
||||
dynamicResult.Add(p.Name, p.GetValue(t, null));
|
||||
}
|
||||
|
||||
result.Add(dynamicResult);
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
58
common/Tnb.Common/Extension/DictionaryExtensions.cs
Normal file
58
common/Tnb.Common/Extension/DictionaryExtensions.cs
Normal file
@@ -0,0 +1,58 @@
|
||||
using JNPF.DependencyInjection;
|
||||
|
||||
namespace JNPF.Common.Extension;
|
||||
|
||||
/// <summary>
|
||||
/// 字典辅助扩展方法.
|
||||
/// </summary>
|
||||
[SuppressSniffer]
|
||||
public static class DictionaryExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// 从字典中获取值,不存在则返回字典<typeparamref name="TValue"/>类型的默认值.
|
||||
/// </summary>
|
||||
/// <typeparam name="TKey">字典键类型.</typeparam>
|
||||
/// <typeparam name="TValue">字典值类型.</typeparam>
|
||||
/// <param name="dictionary">要操作的字典.</param>
|
||||
/// <param name="key">指定键名.</param>
|
||||
/// <returns>获取到的值.</returns>
|
||||
public static TValue GetOrDefault<TKey, TValue>(this IDictionary<TKey, TValue> dictionary, TKey key)
|
||||
{
|
||||
return dictionary.TryGetValue(key, out TValue value) ? value : default(TValue);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取指定键的值,不存在则按指定委托添加值.
|
||||
/// </summary>
|
||||
/// <typeparam name="TKey">字典键类型.</typeparam>
|
||||
/// <typeparam name="TValue">字典值类型.</typeparam>
|
||||
/// <param name="dictionary">要操作的字典.</param>
|
||||
/// <param name="key">指定键名.</param>
|
||||
/// <param name="addFunc">添加值的委托.</param>
|
||||
/// <returns>获取到的值.</returns>
|
||||
public static TValue GetOrAdd<TKey, TValue>(this IDictionary<TKey, TValue> dictionary, TKey key, Func<TValue> addFunc)
|
||||
{
|
||||
if (dictionary.TryGetValue(key, out TValue value))
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
return dictionary[key] = addFunc();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 替换值.
|
||||
/// </summary>
|
||||
/// <param name="dictionary1"></param>
|
||||
/// <param name="dictionary2"></param>
|
||||
public static void ReplaceValue(this Dictionary<string, object> dictionary1, Dictionary<string, object> dictionary2)
|
||||
{
|
||||
foreach (var item in dictionary2.Keys)
|
||||
{
|
||||
if (dictionary1.ContainsKey(item))
|
||||
{
|
||||
dictionary1[item] = dictionary2[item];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
224
common/Tnb.Common/Extension/EnumExtensions.cs
Normal file
224
common/Tnb.Common/Extension/EnumExtensions.cs
Normal file
@@ -0,0 +1,224 @@
|
||||
using JNPF.Common.Security;
|
||||
using JNPF.DependencyInjection;
|
||||
using System.Collections.Concurrent;
|
||||
using System.ComponentModel;
|
||||
using System.Reflection;
|
||||
|
||||
namespace JNPF.Common.Extension;
|
||||
|
||||
/// <summary>
|
||||
/// 枚举<see cref="Enum"/>的扩展辅助操作方法.
|
||||
/// </summary>
|
||||
[SuppressSniffer]
|
||||
public static class EnumExtensions
|
||||
{
|
||||
// 枚举显示字典缓存
|
||||
private static readonly ConcurrentDictionary<Type, Dictionary<int, string>> EnumDisplayValueDict = new();
|
||||
|
||||
// 枚举值字典缓存
|
||||
private static readonly ConcurrentDictionary<Type, Dictionary<int, string>> EnumNameValueDict = new();
|
||||
|
||||
// 枚举类型缓存
|
||||
private static ConcurrentDictionary<string, Type> _enumTypeDict;
|
||||
|
||||
/// <summary>
|
||||
/// 获取枚举对象Key与名称的字典(缓存).
|
||||
/// </summary>
|
||||
/// <param name="enumType"></param>
|
||||
/// <returns></returns>
|
||||
public static Dictionary<int, string> GetEnumDictionary(this Type enumType)
|
||||
{
|
||||
if (!enumType.IsEnum)
|
||||
throw new ArgumentException("Type '" + enumType.Name + "' is not an enum.");
|
||||
|
||||
// 查询缓存
|
||||
var enumDic = EnumNameValueDict.ContainsKey(enumType) ? EnumNameValueDict[enumType] : new Dictionary<int, string>();
|
||||
if (enumDic.Count != 0)
|
||||
return enumDic;
|
||||
// 取枚举类型的Key/Value字典集合
|
||||
enumDic = GetEnumDictionaryItems(enumType);
|
||||
|
||||
// 缓存
|
||||
EnumNameValueDict[enumType] = enumDic;
|
||||
|
||||
return enumDic;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取枚举对象Key与名称的字典.
|
||||
/// </summary>
|
||||
/// <param name="enumType"></param>
|
||||
/// <returns></returns>
|
||||
private static Dictionary<int, string> GetEnumDictionaryItems(this Type enumType)
|
||||
{
|
||||
// 获取类型的字段,初始化一个有限长度的字典
|
||||
var enumFields = enumType.GetFields(BindingFlags.Public | BindingFlags.Static);
|
||||
Dictionary<int, string> enumDic = new(enumFields.Length);
|
||||
|
||||
// 遍历字段数组获取key和name
|
||||
foreach (var enumField in enumFields)
|
||||
{
|
||||
var intValue = (int)enumField.GetValue(enumType);
|
||||
enumDic[intValue] = enumField.Name;
|
||||
}
|
||||
|
||||
return enumDic;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取枚举类型key与描述的字典(缓存).
|
||||
/// </summary>
|
||||
/// <param name="enumType"></param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="Exception"></exception>
|
||||
public static Dictionary<int, string> GetEnumDescDictionary(this Type enumType)
|
||||
{
|
||||
if (!enumType.IsEnum)
|
||||
throw new ArgumentException("Type '" + enumType.Name + "' is not an enum.");
|
||||
|
||||
// 查询缓存
|
||||
var enumDic = EnumDisplayValueDict.ContainsKey(enumType)
|
||||
? EnumDisplayValueDict[enumType]
|
||||
: new Dictionary<int, string>();
|
||||
if (enumDic.Count != 0)
|
||||
return enumDic;
|
||||
// 取枚举类型的Key/Value字典集合
|
||||
enumDic = GetEnumDescDictionaryItems(enumType);
|
||||
|
||||
// 缓存
|
||||
EnumDisplayValueDict[enumType] = enumDic;
|
||||
|
||||
return enumDic;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取枚举类型key与描述的字典(没有描述则获取name).
|
||||
/// </summary>
|
||||
/// <param name="enumType"></param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="Exception"></exception>
|
||||
private static Dictionary<int, string> GetEnumDescDictionaryItems(this Type enumType)
|
||||
{
|
||||
// 获取类型的字段,初始化一个有限长度的字典
|
||||
var enumFields = enumType.GetFields(BindingFlags.Public | BindingFlags.Static);
|
||||
Dictionary<int, string> enumDic = new(enumFields.Length);
|
||||
|
||||
// 遍历字段数组获取key和name
|
||||
foreach (var enumField in enumFields)
|
||||
{
|
||||
var intValue = (int)enumField.GetValue(enumType);
|
||||
var desc = enumField.GetDescriptionValue<DescriptionAttribute>();
|
||||
enumDic[intValue] = desc != null && !string.IsNullOrEmpty(desc.Description) ? desc.Description : enumField.Name;
|
||||
}
|
||||
|
||||
return enumDic;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 从程序集中查找指定枚举类型.
|
||||
/// </summary>
|
||||
/// <param name="assembly"></param>
|
||||
/// <param name="typeName"></param>
|
||||
/// <returns></returns>
|
||||
public static Type TryToGetEnumType(Assembly assembly, string typeName)
|
||||
{
|
||||
// 枚举缓存为空则重新加载枚举类型字典
|
||||
_enumTypeDict ??= LoadEnumTypeDict(assembly);
|
||||
|
||||
// 按名称查找
|
||||
return _enumTypeDict.ContainsKey(typeName) ? _enumTypeDict[typeName] : null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 从程序集中加载所有枚举类型.
|
||||
/// </summary>
|
||||
/// <param name="assembly"></param>
|
||||
/// <returns></returns>
|
||||
private static ConcurrentDictionary<string, Type> LoadEnumTypeDict(Assembly assembly)
|
||||
{
|
||||
// 取程序集中所有类型
|
||||
var typeArray = assembly.GetTypes();
|
||||
|
||||
// 过滤非枚举类型,转成字典格式并返回
|
||||
var dict = typeArray.Where(o => o.IsEnum).ToDictionary(o => o.Name, o => o);
|
||||
ConcurrentDictionary<string, Type> enumTypeDict = new(dict);
|
||||
return enumTypeDict;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取枚举的Description.
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
/// <returns></returns>
|
||||
public static string GetDescription(this System.Enum value)
|
||||
{
|
||||
return value.GetType().GetMember(value.ToString()).FirstOrDefault()?.GetCustomAttribute<DescriptionAttribute>()?.Description;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取枚举的Description
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
/// <returns></returns>
|
||||
public static string GetDescription(this object value)
|
||||
{
|
||||
return value.GetType().GetMember(value.ToString() ?? string.Empty).FirstOrDefault()?.GetCustomAttribute<DescriptionAttribute>()?.Description;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将枚举转成枚举信息集合.
|
||||
/// </summary>
|
||||
/// <param name="type"></param>
|
||||
/// <returns></returns>
|
||||
public static List<EnumEntity> EnumToList(this Type type)
|
||||
{
|
||||
if (!type.IsEnum)
|
||||
throw new ArgumentException("Type '" + type.Name + "' is not an enum.");
|
||||
var arr = System.Enum.GetNames(type);
|
||||
return arr.Select(sl =>
|
||||
{
|
||||
var item = System.Enum.Parse(type, sl);
|
||||
return new EnumEntity
|
||||
{
|
||||
Name = item.ToString(),
|
||||
Describe = item.GetDescription(),
|
||||
Value = item.GetHashCode()
|
||||
};
|
||||
}).ToList();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 枚举ToList.
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="type"></param>
|
||||
/// <returns></returns>
|
||||
public static List<T> EnumToList<T>(this Type type)
|
||||
{
|
||||
if (!type.IsEnum)
|
||||
throw new ArgumentException("Type '" + type.Name + "' is not an enum.");
|
||||
var arr = System.Enum.GetNames(type);
|
||||
return arr.Select(name => (T)System.Enum.Parse(type, name)).ToList();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 枚举实体.
|
||||
/// </summary>
|
||||
public class EnumEntity
|
||||
{
|
||||
/// <summary>
|
||||
/// 枚举的描述.
|
||||
/// </summary>
|
||||
public string Describe { set; get; }
|
||||
|
||||
/// <summary>
|
||||
/// 枚举名称.
|
||||
/// </summary>
|
||||
public string Name { set; get; }
|
||||
|
||||
/// <summary>
|
||||
/// 枚举对象的值.
|
||||
/// </summary>
|
||||
public int Value { set; get; }
|
||||
}
|
||||
73
common/Tnb.Common/Extension/EnumerableExtensions.cs
Normal file
73
common/Tnb.Common/Extension/EnumerableExtensions.cs
Normal file
@@ -0,0 +1,73 @@
|
||||
using JNPF.DependencyInjection;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace JNPF.Common.Extension;
|
||||
|
||||
/// <summary>
|
||||
/// Enumerable集合扩展方法.
|
||||
/// </summary>
|
||||
[SuppressSniffer]
|
||||
public static class EnumerableExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// 将集合展开并分别转换成字符串,再以指定的分隔符衔接,拼成一个字符串返回。默认分隔符为逗号.
|
||||
/// </summary>
|
||||
/// <param name="collection"> 要处理的集合. </param>
|
||||
/// <param name="separator"> 分隔符,默认为逗号. </param>
|
||||
/// <returns> 拼接后的字符串. </returns>
|
||||
public static string ExpandAndToString<T>(this IEnumerable<T> collection, string separator = ",")
|
||||
{
|
||||
return collection.ExpandAndToString(item => item?.ToString() ?? string.Empty, separator);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 循环集合的每一项,调用委托生成字符串,返回合并后的字符串。默认分隔符为逗号.
|
||||
/// </summary>
|
||||
/// <param name="collection">待处理的集合.</param>
|
||||
/// <param name="itemFormatFunc">单个集合项的转换委托.</param>
|
||||
/// <param name="separator">分隔符,默认为逗号.</param>
|
||||
/// <typeparam name="T">泛型类型.</typeparam>
|
||||
/// <returns></returns>
|
||||
public static string ExpandAndToString<T>(this IEnumerable<T> collection, Func<T, string> itemFormatFunc, string separator = ",")
|
||||
{
|
||||
collection = collection as IList<T> ?? collection.ToList();
|
||||
if (!collection.Any())
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
int i = 0;
|
||||
int count = collection.Count();
|
||||
foreach (T item in collection)
|
||||
{
|
||||
if (i == count - 1)
|
||||
{
|
||||
sb.Append(itemFormatFunc(item));
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.Append(itemFormatFunc(item) + separator);
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 集合是否为空.
|
||||
/// </summary>
|
||||
/// <param name="collection"> 要处理的集合. </param>
|
||||
/// <typeparam name="T"> 动态类型. </typeparam>
|
||||
/// <returns> 为空返回True,不为空返回False. </returns>
|
||||
public static bool IsEmpty<T>(this IEnumerable<T> collection)
|
||||
{
|
||||
collection = collection as IList<T> ?? collection.ToList();
|
||||
return !collection.Any();
|
||||
}
|
||||
}
|
||||
101
common/Tnb.Common/Extension/Extensions.DateTime.cs
Normal file
101
common/Tnb.Common/Extension/Extensions.DateTime.cs
Normal file
@@ -0,0 +1,101 @@
|
||||
using JNPF.DependencyInjection;
|
||||
|
||||
namespace JNPF.Common.Extension;
|
||||
|
||||
/// <summary>
|
||||
/// 时间<see cref="DateTime"/>类型的扩展辅助操作类.
|
||||
/// </summary>
|
||||
[SuppressSniffer]
|
||||
public static partial class Extensions
|
||||
{
|
||||
#region 时间判断
|
||||
|
||||
/// <summary>
|
||||
/// 判断时间是否在某个时间段内.
|
||||
/// </summary>
|
||||
/// <param name="nowTime">数据时间.</param>
|
||||
/// <param name="beginHm">查询开始时间.</param>
|
||||
/// <param name="endHm">查询结束时间.</param>
|
||||
/// <param name="type">0-yyyy-MM-dd,1-yyyy-MM,2-yyyy.</param>
|
||||
/// <returns></returns>
|
||||
public static bool IsInTimeRange(DateTime nowTime, string beginHm, string endHm, int type = 0)
|
||||
{
|
||||
DateTime start = new DateTime();
|
||||
DateTime end = new DateTime();
|
||||
switch (type)
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
DateTime beginTime = beginHm.ParseToDateTime();
|
||||
DateTime endTime = endHm.ParseToDateTime();
|
||||
start = new DateTime(beginTime.Year, beginTime.Month, 1, 0, 0, 0, 0);
|
||||
end = new DateTime(endTime.Year, endTime.Month, DateTime.DaysInMonth(endTime.Year, endTime.Month), 23, 59, 59, 999);
|
||||
}
|
||||
|
||||
break;
|
||||
case 2:
|
||||
{
|
||||
DateTime beginTime = beginHm.ParseToDateTime();
|
||||
DateTime endTime = endHm.ParseToDateTime();
|
||||
start = new DateTime(beginTime.Year, 1, 1, 0, 0, 0, 0);
|
||||
end = new DateTime(endTime.Year, 12, 31, 23, 59, 59, 999);
|
||||
}
|
||||
|
||||
break;
|
||||
case 0:
|
||||
{
|
||||
DateTime beginTime = beginHm.ParseToDateTime();
|
||||
DateTime endTime = endHm.ParseToDateTime();
|
||||
start = new DateTime(beginTime.Year, beginTime.Month, beginTime.Day, 0, 0, 0, 0);
|
||||
end = new DateTime(endTime.Year, endTime.Month, endTime.Day, 23, 59, 59, 999);
|
||||
}
|
||||
|
||||
break;
|
||||
case 3:
|
||||
{
|
||||
DateTime beginTime = beginHm.ParseToDateTime();
|
||||
DateTime endTime = endHm.ParseToDateTime();
|
||||
start = new DateTime(beginTime.Year, beginTime.Month, beginTime.Day, beginTime.Hour, beginTime.Minute, beginTime.Second, 0);
|
||||
end = new DateTime(endTime.Year, endTime.Month, endTime.Day, endTime.Hour, endTime.Minute, endTime.Second, 999);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (ParseToUnixTime(nowTime) >= ParseToUnixTime(start) && ParseToUnixTime(nowTime) <= ParseToUnixTime(end))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 时间判断.
|
||||
/// </summary>
|
||||
/// <param name="nowTime">数据时间.</param>
|
||||
/// <param name="dayTimeStart">查询开始时间.</param>
|
||||
/// <param name="dayTimeEnd">查询结束时间.</param>
|
||||
/// <returns></returns>
|
||||
public static bool timeCalendar(string nowTime, string dayTimeStart, string dayTimeEnd)
|
||||
{
|
||||
// 设置当前时间
|
||||
DateTime date = nowTime.ParseToDateTime();
|
||||
|
||||
// 设置开始时间
|
||||
DateTime timeStart = dayTimeStart.ParseToDateTime();
|
||||
timeStart = new DateTime(timeStart.Year, timeStart.Month, timeStart.Day, 0, 0, 0, 0);
|
||||
|
||||
// 设置结束时间
|
||||
DateTime timeEnd = dayTimeEnd.ParseToDateTime();
|
||||
timeEnd = new DateTime(timeEnd.Year, timeEnd.Month, timeEnd.Day, 23, 59, 59, 999);
|
||||
|
||||
// 当date > timeStart时,date.CompareTo(timeStart)返回 1
|
||||
// 当date = timeStart时,date.CompareTo(timeStart)返回 0
|
||||
// 当date < timeStart时,date.CompareTo(timeStart)返回 -1
|
||||
if (DateTime.Compare(date, timeStart) >= 0 && DateTime.Compare(date, timeEnd) <= 0)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
696
common/Tnb.Common/Extension/Extensions.cs
Normal file
696
common/Tnb.Common/Extension/Extensions.cs
Normal file
@@ -0,0 +1,696 @@
|
||||
using System.Collections;
|
||||
using System.Globalization;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace JNPF.Common.Extension;
|
||||
|
||||
/// <summary>
|
||||
/// 转换扩展类.
|
||||
/// </summary>
|
||||
public static partial class Extensions
|
||||
{
|
||||
#region 转换为long
|
||||
|
||||
/// <summary>
|
||||
/// 将object转换为long,若转换失败,则返回0.不抛出异常.
|
||||
/// </summary>
|
||||
/// <param name="obj"></param>
|
||||
/// <returns></returns>
|
||||
public static long ParseToLong(this object obj)
|
||||
{
|
||||
try
|
||||
{
|
||||
return long.Parse(obj.ToString() ?? string.Empty);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return 0L;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将object转换为long,若转换失败,则返回指定值.不抛出异常.
|
||||
/// </summary>
|
||||
/// <param name="str"></param>
|
||||
/// <param name="defaultValue"></param>
|
||||
/// <returns></returns>
|
||||
public static long ParseToLong(this string str, long defaultValue)
|
||||
{
|
||||
try
|
||||
{
|
||||
return long.Parse(str);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 转换为int
|
||||
|
||||
/// <summary>
|
||||
/// 将object转换为int,若转换失败,则返回0。不抛出异常.
|
||||
/// </summary>
|
||||
/// <param name="str"></param>
|
||||
/// <returns></returns>
|
||||
public static int ParseToInt(this object str)
|
||||
{
|
||||
try
|
||||
{
|
||||
return Convert.ToInt32(str);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将object转换为int,若转换失败,则返回指定值。不抛出异常
|
||||
/// null返回默认值.
|
||||
/// </summary>
|
||||
/// <param name="str"></param>
|
||||
/// <param name="defaultValue"></param>
|
||||
/// <returns></returns>
|
||||
public static int ParseToInt(this object str, int defaultValue)
|
||||
{
|
||||
if (str == null)
|
||||
{
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
return Convert.ToInt32(str);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 转换为short
|
||||
|
||||
/// <summary>
|
||||
/// 将object转换为short,若转换失败,则返回0。不抛出异常.
|
||||
/// </summary>
|
||||
/// <param name="obj"></param>
|
||||
/// <returns></returns>
|
||||
public static short ParseToShort(this object obj)
|
||||
{
|
||||
try
|
||||
{
|
||||
return short.Parse(obj.ToString() ?? string.Empty);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将object转换为short,若转换失败,则返回指定值。不抛出异常.
|
||||
/// </summary>
|
||||
/// <param name="str"></param>
|
||||
/// <param name="defaultValue"></param>
|
||||
/// <returns></returns>
|
||||
public static short ParseToShort(this object str, short defaultValue)
|
||||
{
|
||||
try
|
||||
{
|
||||
return short.Parse(str.ToString() ?? string.Empty);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 转换为demical
|
||||
|
||||
/// <summary>
|
||||
/// 将object转换为demical,若转换失败,则返回指定值。不抛出异常.
|
||||
/// </summary>
|
||||
/// <param name="str"></param>
|
||||
/// <param name="defaultValue"></param>
|
||||
/// <returns></returns>
|
||||
public static decimal ParseToDecimal(this object str, decimal defaultValue)
|
||||
{
|
||||
try
|
||||
{
|
||||
return decimal.Parse(str.ToString() ?? string.Empty);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将object转换为demical,若转换失败,则返回0。不抛出异常.
|
||||
/// </summary>
|
||||
/// <param name="str"></param>
|
||||
/// <returns></returns>
|
||||
public static decimal ParseToDecimal(this object str)
|
||||
{
|
||||
try
|
||||
{
|
||||
return decimal.Parse(str.ToString() ?? string.Empty);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 转化为bool
|
||||
|
||||
/// <summary>
|
||||
/// 将object转换为bool,若转换失败,则返回false。不抛出异常.
|
||||
/// </summary>
|
||||
/// <param name="str"></param>
|
||||
/// <returns></returns>
|
||||
public static bool ParseToBool(this object str)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (str == null)
|
||||
return false;
|
||||
bool? value = GetBool(str);
|
||||
if (value != null)
|
||||
return value.Value;
|
||||
bool result;
|
||||
return bool.TryParse(str.ToString(), out result) && result;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将object转换为bool,若转换失败,则返回指定值。不抛出异常.
|
||||
/// </summary>
|
||||
/// <param name="str"></param>
|
||||
/// <param name="result"></param>
|
||||
/// <returns></returns>
|
||||
public static bool ParseToBool(this object str, bool result)
|
||||
{
|
||||
try
|
||||
{
|
||||
return bool.Parse(str.ToString() ?? string.Empty);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取布尔值.
|
||||
/// </summary>
|
||||
private static bool? GetBool(this object data)
|
||||
{
|
||||
switch (data.ToString().Trim().ToLower())
|
||||
{
|
||||
case "0":
|
||||
return false;
|
||||
case "1":
|
||||
return true;
|
||||
case "是":
|
||||
return true;
|
||||
case "否":
|
||||
return false;
|
||||
case "yes":
|
||||
return true;
|
||||
case "no":
|
||||
return false;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 转换为float
|
||||
|
||||
/// <summary>
|
||||
/// 将object转换为float,若转换失败,则返回0。不抛出异常.
|
||||
/// </summary>
|
||||
/// <param name="str"></param>
|
||||
/// <returns></returns>
|
||||
public static float ParseToFloat(this object str)
|
||||
{
|
||||
try
|
||||
{
|
||||
return float.Parse(str.ToString() ?? string.Empty);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将object转换为float,若转换失败,则返回指定值。不抛出异常.
|
||||
/// </summary>
|
||||
/// <param name="str"></param>
|
||||
/// <param name="result"></param>
|
||||
/// <returns></returns>
|
||||
public static float ParseToFloat(this object str, float result)
|
||||
{
|
||||
try
|
||||
{
|
||||
return float.Parse(str.ToString() ?? string.Empty);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 转换为Guid
|
||||
|
||||
/// <summary>
|
||||
/// 将string转换为Guid,若转换失败,则返回Guid.Empty。不抛出异常.
|
||||
/// </summary>
|
||||
/// <param name="str"></param>
|
||||
/// <returns></returns>
|
||||
public static Guid ParseToGuid(this string str)
|
||||
{
|
||||
try
|
||||
{
|
||||
return new Guid(str);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return Guid.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 转换为DateTime
|
||||
|
||||
/// <summary>
|
||||
/// 将string转换为DateTime,若转换失败,则返回日期最小值。不抛出异常.
|
||||
/// </summary>
|
||||
/// <param name="str"></param>
|
||||
/// <returns></returns>
|
||||
public static DateTime ParseToDateTime(this string str)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(str))
|
||||
{
|
||||
return DateTime.MinValue;
|
||||
}
|
||||
|
||||
if (str.Contains("-") || str.Contains("/"))
|
||||
{
|
||||
return DateTime.Parse(str);
|
||||
}
|
||||
|
||||
int length = str.Length;
|
||||
return length switch
|
||||
{
|
||||
4 => DateTime.ParseExact(str, "yyyy", CultureInfo.CurrentCulture),
|
||||
6 => DateTime.ParseExact(str, "yyyyMM", CultureInfo.CurrentCulture),
|
||||
8 => DateTime.ParseExact(str, "yyyyMMdd", CultureInfo.CurrentCulture),
|
||||
10 => DateTime.ParseExact(str, "yyyyMMddHH", CultureInfo.CurrentCulture),
|
||||
12 => DateTime.ParseExact(str, "yyyyMMddHHmm", CultureInfo.CurrentCulture),
|
||||
|
||||
// ReSharper disable once StringLiteralTypo
|
||||
14 => DateTime.ParseExact(str, "yyyyMMddHHmmss", CultureInfo.CurrentCulture),
|
||||
|
||||
// ReSharper disable once StringLiteralTypo
|
||||
_ => DateTime.ParseExact(str, "yyyyMMddHHmmss", CultureInfo.CurrentCulture)
|
||||
};
|
||||
}
|
||||
catch
|
||||
{
|
||||
return DateTime.MinValue;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将时间戳转为DateTime.
|
||||
/// </summary>
|
||||
/// <param name="timeStamp">时间戳.</param>
|
||||
/// <returns></returns>
|
||||
public static DateTime TimeStampToDateTime(this long timeStamp)
|
||||
{
|
||||
try
|
||||
{
|
||||
DateTimeOffset dto = DateTimeOffset.FromUnixTimeMilliseconds(timeStamp);
|
||||
return dto.ToLocalTime().DateTime;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将时间戳转为DateTime.
|
||||
/// </summary>
|
||||
/// <param name="timeStamp">时间戳.</param>
|
||||
/// <returns></returns>
|
||||
public static DateTime TimeStampToDateTime(this string timeStamp)
|
||||
{
|
||||
try
|
||||
{
|
||||
DateTimeOffset dto = DateTimeOffset.FromUnixTimeMilliseconds(Convert.ToInt64(timeStamp));
|
||||
return dto.ToLocalTime().DateTime;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将 DateTime? 转换为 DateTime.
|
||||
/// </summary>
|
||||
/// <param name="date"></param>
|
||||
/// <returns></returns>
|
||||
public static DateTime ParseToDateTime(this DateTime? date)
|
||||
{
|
||||
return Convert.ToDateTime(date);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将 DateTime 根据指定格式转换.
|
||||
/// </summary>
|
||||
/// <param name="date">时间.</param>
|
||||
/// <param name="format">格式字符串.</param>
|
||||
/// <returns></returns>
|
||||
public static DateTime ParseToDateTime(this DateTime? date, string format)
|
||||
{
|
||||
return Convert.ToDateTime(string.Format("{0:" + format + "}", date));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将 DateTime 根据指定格式转换.
|
||||
/// </summary>
|
||||
/// <param name="date">时间.</param>
|
||||
/// <param name="format">格式字符串.</param>
|
||||
/// <returns></returns>
|
||||
public static DateTime ParseToDateTime(this DateTime date, string format)
|
||||
{
|
||||
return Convert.ToDateTime(string.Format("{0:" + format + "}", date));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将string转换为DateTime,若转换失败,则返回默认值.
|
||||
/// </summary>
|
||||
/// <param name="str"></param>
|
||||
/// <param name="defaultValue"></param>
|
||||
/// <returns></returns>
|
||||
public static DateTime ParseToDateTime(this string str, DateTime? defaultValue)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(str))
|
||||
{
|
||||
return defaultValue.GetValueOrDefault();
|
||||
}
|
||||
|
||||
if (str.Contains("-") || str.Contains("/"))
|
||||
{
|
||||
return DateTime.Parse(str);
|
||||
}
|
||||
|
||||
int length = str.Length;
|
||||
return length switch
|
||||
{
|
||||
4 => DateTime.ParseExact(str, "yyyy", CultureInfo.CurrentCulture),
|
||||
6 => DateTime.ParseExact(str, "yyyyMM", CultureInfo.CurrentCulture),
|
||||
8 => DateTime.ParseExact(str, "yyyyMMdd", CultureInfo.CurrentCulture),
|
||||
10 => DateTime.ParseExact(str, "yyyyMMddHH", CultureInfo.CurrentCulture),
|
||||
12 => DateTime.ParseExact(str, "yyyyMMddHHmm", CultureInfo.CurrentCulture),
|
||||
|
||||
// ReSharper disable once StringLiteralTypo
|
||||
14 => DateTime.ParseExact(str, "yyyyMMddHHmmss", CultureInfo.CurrentCulture),
|
||||
|
||||
// ReSharper disable once StringLiteralTypo
|
||||
_ => DateTime.ParseExact(str, "yyyyMMddHHmmss", CultureInfo.CurrentCulture)
|
||||
};
|
||||
}
|
||||
catch
|
||||
{
|
||||
return defaultValue.GetValueOrDefault();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 转换为string
|
||||
|
||||
/// <summary>
|
||||
/// 将object转换为string,若转换失败,则返回""。不抛出异常.
|
||||
/// </summary>
|
||||
/// <param name="obj"></param>
|
||||
/// <returns></returns>
|
||||
public static string ParseToString(this object obj)
|
||||
{
|
||||
try
|
||||
{
|
||||
return obj == null ? string.Empty : obj.ToString();
|
||||
}
|
||||
catch
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将object转换为string.
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="obj"></param>
|
||||
/// <returns></returns>
|
||||
public static string ParseToStrings<T>(this object obj)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (obj is IEnumerable<T> list)
|
||||
{
|
||||
return string.Join(",", list);
|
||||
}
|
||||
|
||||
return obj.ToString();
|
||||
}
|
||||
catch
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 转换为double
|
||||
|
||||
/// <summary>
|
||||
/// 将object转换为double,若转换失败,则返回0。不抛出异常.
|
||||
/// </summary>
|
||||
/// <param name="obj"></param>
|
||||
/// <returns></returns>
|
||||
public static double ParseToDouble(this object obj)
|
||||
{
|
||||
try
|
||||
{
|
||||
return double.Parse(obj.ToString() ?? string.Empty);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将object转换为double,若转换失败,则返回指定值。不抛出异常.
|
||||
/// </summary>
|
||||
/// <param name="str"></param>
|
||||
/// <param name="defaultValue"></param>
|
||||
/// <returns></returns>
|
||||
public static double ParseToDouble(this object str, double defaultValue)
|
||||
{
|
||||
try
|
||||
{
|
||||
return double.Parse(str.ToString() ?? string.Empty);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 强制转换类型
|
||||
|
||||
/// <summary>
|
||||
/// 强制转换类型.
|
||||
/// </summary>
|
||||
/// <typeparam name="TResult"></typeparam>
|
||||
/// <param name="source"></param>
|
||||
/// <returns></returns>
|
||||
public static IEnumerable<TResult> CastSuper<TResult>(this IEnumerable source)
|
||||
{
|
||||
return from object item in source select (TResult)Convert.ChangeType(item, typeof(TResult));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 转换为ToUnixTime
|
||||
|
||||
public static long ParseToUnixTime(this DateTime nowTime)
|
||||
{
|
||||
DateTimeOffset dto = new DateTimeOffset(nowTime);
|
||||
return dto.ToUnixTimeMilliseconds();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 转换为帕斯卡命名法
|
||||
|
||||
/// <summary>
|
||||
/// 将字符串转为帕斯卡命名法.
|
||||
/// </summary>
|
||||
/// <param name="original">源字符串.</param>
|
||||
/// <returns></returns>
|
||||
public static string ParseToPascalCase(this string original)
|
||||
{
|
||||
Regex invalidCharsRgx = new Regex("[^_a-zA-Z0-9]");
|
||||
Regex whiteSpace = new Regex(@"(?<=\s)");
|
||||
Regex startsWithLowerCaseChar = new Regex("^[a-z]");
|
||||
Regex firstCharFollowedByUpperCasesOnly = new Regex("(?<=[A-Z])[A-Z0-9]+$");
|
||||
Regex lowerCaseNextToNumber = new Regex("(?<=[0-9])[a-z]");
|
||||
Regex upperCaseInside = new Regex("(?<=[A-Z])[A-Z]+?((?=[A-Z][a-z])|(?=[0-9]))");
|
||||
|
||||
// 用undescore替换空白,然后用空字符串替换所有无效字符
|
||||
var pascalCase = invalidCharsRgx.Replace(whiteSpace.Replace(original, "_"), string.Empty)
|
||||
|
||||
// 用下划线分割
|
||||
.Split(new char[] { '_' }, StringSplitOptions.RemoveEmptyEntries)
|
||||
|
||||
// 首字母设置为大写
|
||||
.Select(w => startsWithLowerCaseChar.Replace(w, m => m.Value.ToUpper()))
|
||||
|
||||
// 如果没有下一个小写字母(ABC -> Abc),则将第二个及所有后面的大写字母替换为小写字母
|
||||
.Select(w => firstCharFollowedByUpperCasesOnly.Replace(w, m => m.Value.ToLower()))
|
||||
|
||||
// 数字后面的第一个小写字母 设置大写(Ab9cd -> Ab9Cd)
|
||||
.Select(w => lowerCaseNextToNumber.Replace(w, m => m.Value.ToUpper()))
|
||||
|
||||
// 第二个小写字母和下一个大写字母,除非最后一个字母后跟任何小写字母 (ABcDEf -> AbcDef)
|
||||
.Select(w => upperCaseInside.Replace(w, m => m.Value.ToLower()));
|
||||
|
||||
return string.Concat(pascalCase);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IsEmpty
|
||||
|
||||
/// <summary>
|
||||
/// 是否为空.
|
||||
/// </summary>
|
||||
/// <param name="value">值.</param>
|
||||
public static bool IsEmpty(this string value)
|
||||
{
|
||||
return string.IsNullOrWhiteSpace(value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 是否为空.
|
||||
/// </summary>
|
||||
/// <param name="value">值.</param>
|
||||
public static bool IsEmpty(this Guid? value)
|
||||
{
|
||||
if (value == null)
|
||||
return true;
|
||||
return IsEmpty(value.Value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 是否为空.
|
||||
/// </summary>
|
||||
/// <param name="value">值.</param>
|
||||
public static bool IsEmpty(this Guid value)
|
||||
{
|
||||
if (value == Guid.Empty)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 是否为空.
|
||||
/// </summary>
|
||||
/// <param name="value">值.</param>
|
||||
public static bool IsEmpty(this object value)
|
||||
{
|
||||
if (value != null && !string.IsNullOrEmpty(value.ToString()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 判断是否为Null或者空.
|
||||
/// </summary>
|
||||
/// <param name="obj">对象.</param>
|
||||
/// <returns></returns>
|
||||
public static bool IsNullOrEmpty(this object obj)
|
||||
{
|
||||
if (obj == null)
|
||||
return true;
|
||||
else
|
||||
{
|
||||
string objStr = obj.ToString();
|
||||
return string.IsNullOrEmpty(objStr);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IsNotEmptyOrNull
|
||||
|
||||
/// <summary>
|
||||
/// 不为空.
|
||||
/// </summary>
|
||||
/// <param name="thisValue"></param>
|
||||
/// <returns></returns>
|
||||
public static string ObjToString(this object thisValue)
|
||||
{
|
||||
if (thisValue != null) return thisValue.ToString().Trim();
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 不为空.
|
||||
/// </summary>
|
||||
/// <param name="thisValue"></param>
|
||||
/// <returns></returns>
|
||||
public static bool IsNotEmptyOrNull(this object thisValue)
|
||||
{
|
||||
return ObjToString(thisValue) != string.Empty && ObjToString(thisValue) != "undefined" && ObjToString(thisValue) != "null";
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
311
common/Tnb.Common/Extension/RandomExtensions.cs
Normal file
311
common/Tnb.Common/Extension/RandomExtensions.cs
Normal file
File diff suppressed because one or more lines are too long
27
common/Tnb.Common/Extension/StreamExtensions.cs
Normal file
27
common/Tnb.Common/Extension/StreamExtensions.cs
Normal file
@@ -0,0 +1,27 @@
|
||||
using JNPF.DependencyInjection;
|
||||
using System.Text;
|
||||
|
||||
namespace JNPF.Common.Extension;
|
||||
|
||||
/// <summary>
|
||||
/// Stream扩展方法.
|
||||
/// </summary>
|
||||
[SuppressSniffer]
|
||||
public static class StreamExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// 把<see cref="Stream"/>转换为<see cref="string"/>.
|
||||
/// </summary>
|
||||
public static string ToString2(this Stream stream, Encoding? encoding = null)
|
||||
{
|
||||
if (encoding == null)
|
||||
{
|
||||
encoding = Encoding.UTF8;
|
||||
}
|
||||
|
||||
using (StreamReader reader = new StreamReader(stream, encoding))
|
||||
{
|
||||
return reader.ReadToEnd();
|
||||
}
|
||||
}
|
||||
}
|
||||
170
common/Tnb.Common/Extension/StringBuilderExtensions.cs
Normal file
170
common/Tnb.Common/Extension/StringBuilderExtensions.cs
Normal file
@@ -0,0 +1,170 @@
|
||||
using JNPF.DependencyInjection;
|
||||
using System.Text;
|
||||
|
||||
namespace JNPF.Common.Extension;
|
||||
|
||||
/// <summary>
|
||||
/// StringBuilder 扩展方法类.
|
||||
/// </summary>
|
||||
[SuppressSniffer]
|
||||
public static class StringBuilderExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// 去除<seealso cref="StringBuilder"/>开头的空格.
|
||||
/// </summary>
|
||||
/// <param name="sb">StringBuilder.</param>
|
||||
/// <returns>返回修改后的StringBuilder,主要用于链式操作.</returns>
|
||||
public static StringBuilder TrimStart(this StringBuilder sb)
|
||||
{
|
||||
return sb.TrimStart(' ');
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 去除<seealso cref="StringBuilder"/>开头的指定<seealso cref="char"/>.
|
||||
/// </summary>
|
||||
/// <param name="sb">StringBuilder.</param>
|
||||
/// <param name="c">要去掉的<seealso cref="char"/>.</param>
|
||||
/// <returns></returns>
|
||||
public static StringBuilder TrimStart(this StringBuilder sb, char c)
|
||||
{
|
||||
if (sb.Length == 0)
|
||||
return sb;
|
||||
while (c.Equals(sb[0]))
|
||||
{
|
||||
sb.Remove(0, 1);
|
||||
}
|
||||
|
||||
return sb;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 去除<seealso cref="StringBuilder"/>开头的指定字符数组.
|
||||
/// </summary>
|
||||
/// <param name="sb">StringBuilder.</param>
|
||||
/// <param name="cs">要去掉的字符数组.</param>
|
||||
/// <returns></returns>
|
||||
public static StringBuilder TrimStart(this StringBuilder sb, char[] cs)
|
||||
{
|
||||
return sb.TrimStart(new string(cs));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 去除<see cref="StringBuilder"/>开头的指定的<seealso cref="string"/>.
|
||||
/// </summary>
|
||||
/// <param name="sb">StringBuilder.</param>
|
||||
/// <param name="str">要去掉的<seealso cref="string"/>.</param>
|
||||
/// <returns></returns>
|
||||
public static StringBuilder TrimStart(this StringBuilder sb, string str)
|
||||
{
|
||||
if (string.IsNullOrEmpty(str)
|
||||
|| sb.Length == 0
|
||||
|| str.Length > sb.Length)
|
||||
return sb;
|
||||
while (sb.SubString(0, str.Length).Equals(str))
|
||||
{
|
||||
sb.Remove(0, str.Length);
|
||||
if (str.Length > sb.Length)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return sb;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 去除StringBuilder结尾的空格.
|
||||
/// </summary>
|
||||
/// <param name="sb">StringBuilder.</param>
|
||||
/// <returns>返回修改后的StringBuilder,主要用于链式操作.</returns>
|
||||
public static StringBuilder TrimEnd(this StringBuilder sb)
|
||||
{
|
||||
return sb.TrimEnd(' ');
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 去除<see cref="StringBuilder"/>结尾指定字符.
|
||||
/// </summary>
|
||||
/// <param name="sb">StringBuilder.</param>
|
||||
/// <param name="c">要去掉的字符.</param>
|
||||
/// <returns></returns>
|
||||
public static StringBuilder TrimEnd(this StringBuilder sb, char c)
|
||||
{
|
||||
if (sb.Length == 0)
|
||||
return sb;
|
||||
while (c.Equals(sb[sb.Length - 1]))
|
||||
{
|
||||
sb.Remove(sb.Length - 1, 1);
|
||||
}
|
||||
|
||||
return sb;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 去除<see cref="StringBuilder"/>结尾指定字符数组.
|
||||
/// </summary>
|
||||
/// <param name="sb">StringBuilder.</param>
|
||||
/// <param name="chars">要去除的字符数组.</param>
|
||||
/// <returns></returns>
|
||||
public static StringBuilder TrimEnd(this StringBuilder sb, char[] chars)
|
||||
{
|
||||
return sb.TrimEnd(new string(chars));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 去除<see cref="StringBuilder"/>结尾指定字符串.
|
||||
/// </summary>
|
||||
/// <param name="sb">StringBuilder.</param>
|
||||
/// <param name="str">要去除的字符串.</param>
|
||||
/// <returns></returns>
|
||||
public static StringBuilder TrimEnd(this StringBuilder sb, string str)
|
||||
{
|
||||
if (string.IsNullOrEmpty(str)
|
||||
|| sb.Length == 0
|
||||
|| str.Length > sb.Length)
|
||||
return sb;
|
||||
while (sb.SubString(sb.Length - str.Length, str.Length).Equals(str))
|
||||
{
|
||||
sb.Remove(sb.Length - str.Length, str.Length);
|
||||
if (sb.Length < str.Length)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return sb;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 去除StringBuilder两端的空格.
|
||||
/// </summary>
|
||||
/// <param name="sb">StringBuilder.</param>
|
||||
/// <returns>返回修改后的StringBuilder,主要用于链式操作.</returns>
|
||||
public static StringBuilder Trim(this StringBuilder sb)
|
||||
{
|
||||
if (sb.Length == 0)
|
||||
return sb;
|
||||
return sb.TrimEnd().TrimStart();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 返回<see cref="StringBuilder"/>从起始位置指定长度的字符串.
|
||||
/// </summary>
|
||||
/// <param name="sb">StringBuilder.</param>
|
||||
/// <param name="start">起始位置.</param>
|
||||
/// <param name="length">长度.</param>
|
||||
/// <returns>字符串.</returns>
|
||||
/// <exception cref="OverflowException">超出字符串索引长度异常.</exception>
|
||||
public static string SubString(this StringBuilder sb, int start, int length)
|
||||
{
|
||||
if (start + length > sb.Length)
|
||||
throw new IndexOutOfRangeException("超出字符串索引长度");
|
||||
char[] cs = new char[length];
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
cs[i] = sb[start + i];
|
||||
}
|
||||
|
||||
return new string(cs);
|
||||
}
|
||||
}
|
||||
926
common/Tnb.Common/Extension/StringExtensions.cs
Normal file
926
common/Tnb.Common/Extension/StringExtensions.cs
Normal file
@@ -0,0 +1,926 @@
|
||||
using JNPF.Common.Security;
|
||||
using JNPF.DependencyInjection;
|
||||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
using System.Text.Json;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Web;
|
||||
|
||||
namespace JNPF.Common.Extension;
|
||||
|
||||
/// <summary>
|
||||
/// 字符串<see cref="string"/>类型的扩展辅助操作类.
|
||||
/// </summary>
|
||||
[SuppressSniffer]
|
||||
public static class StringExtensions
|
||||
{
|
||||
#region 正则表达式
|
||||
|
||||
/// <summary>
|
||||
/// 指示所指定的正则表达式在指定的输入字符串中是否找到了匹配项.
|
||||
/// </summary>
|
||||
/// <param name="value">要搜索匹配项的字符串.</param>
|
||||
/// <param name="pattern">要匹配的正则表达式模式.</param>
|
||||
/// <param name="isContains">是否包含,否则全匹配.</param>
|
||||
/// <returns>如果正则表达式找到匹配项,则为 true;否则,为 false.</returns>
|
||||
public static bool IsMatch(this string value, string pattern, bool isContains = true)
|
||||
{
|
||||
if (value == null)
|
||||
return false;
|
||||
|
||||
return isContains
|
||||
? Regex.IsMatch(value, pattern)
|
||||
: Regex.Match(value, pattern).Success;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 在指定的输入字符串中搜索指定的正则表达式的第一个匹配项.
|
||||
/// </summary>
|
||||
/// <param name="value">要搜索匹配项的字符串.</param>
|
||||
/// <param name="pattern">要匹配的正则表达式模式.</param>
|
||||
/// <returns>一个对象,包含有关匹配项的信息.</returns>
|
||||
public static string Match(this string value, string pattern)
|
||||
{
|
||||
if (value == null)
|
||||
return string.Empty;
|
||||
|
||||
return Regex.Match(value, pattern).Value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 在指定的输入字符串中匹配并替换符合指定正则表达式的子串.
|
||||
/// </summary>
|
||||
public static string ReplaceRegex(this string value, string pattern, string replacement)
|
||||
{
|
||||
if (value == null)
|
||||
return string.Empty;
|
||||
|
||||
return Regex.Replace(value, pattern, replacement, RegexOptions.IgnoreCase);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 在指定的输入字符串中搜索指定的正则表达式的所有匹配项的字符串集合.
|
||||
/// </summary>
|
||||
/// <param name="value"> 要搜索匹配项的字符串.</param>
|
||||
/// <param name="pattern"> 要匹配的正则表达式模式.</param>
|
||||
/// <returns> 一个集合,包含有关匹配项的字符串值.</returns>
|
||||
public static IEnumerable<string> Matches(this string value, string pattern)
|
||||
{
|
||||
if (value == null)
|
||||
return new string[] { };
|
||||
|
||||
MatchCollection matches = Regex.Matches(value, pattern);
|
||||
return from Match match in matches select match.Value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 在指定的输入字符串中搜索指定的正则表达式的指定组匹配项的字符串.
|
||||
/// </summary>
|
||||
/// <param name="value"> 要搜索匹配项的字符串.</param>
|
||||
/// <param name="pattern"> 要匹配的正则表达式模式.</param>
|
||||
/// <param name="groups"> 指定组的字符串.</param>
|
||||
/// <returns> 一个集合,包含有关匹配项的字符串值.</returns>
|
||||
public static IEnumerable<string> Matches(this string value, string pattern, string groups)
|
||||
{
|
||||
if (value == null)
|
||||
return new string[] { };
|
||||
|
||||
MatchCollection matches = Regex.Matches(value, pattern);
|
||||
return from Match match in matches select match.Groups[groups].Value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 在指定的输入字符串中匹配第一个数字字符串.
|
||||
/// </summary>
|
||||
public static string MatchFirstNumber(this string value)
|
||||
{
|
||||
MatchCollection matches = Regex.Matches(value, @"\d+");
|
||||
if (matches.Count == 0)
|
||||
return string.Empty;
|
||||
|
||||
return matches[0].Value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 在指定字符串中匹配最后一个数字字符串.
|
||||
/// </summary>
|
||||
public static string MatchLastNumber(this string value)
|
||||
{
|
||||
MatchCollection matches = Regex.Matches(value, @"\d+");
|
||||
if (matches.Count == 0)
|
||||
return string.Empty;
|
||||
|
||||
return matches[matches.Count - 1].Value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 在指定字符串中匹配所有数字字符串.
|
||||
/// </summary>
|
||||
public static IEnumerable<string> MatchNumbers(this string value)
|
||||
{
|
||||
return Matches(value, @"\d+");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 检测指定字符串中是否包含数字.
|
||||
/// </summary>
|
||||
public static bool IsMatchNumber(this string value)
|
||||
{
|
||||
return IsMatch(value, @"\d");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 检测指定字符串是否全部为数字并且长度等于指定长度.
|
||||
/// </summary>
|
||||
public static bool IsMatchNumber(this string value, int length)
|
||||
{
|
||||
Regex regex = new Regex(@"^\d{" + length + "}$");
|
||||
return regex.IsMatch(value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 截取指定字符串之间的字符串.
|
||||
/// </summary>
|
||||
/// <param name="source"></param>
|
||||
/// <param name="startString">起始字符串.</param>
|
||||
/// <param name="endStrings">结束字符串,可多个.</param>
|
||||
/// <returns>返回的中间字符串.</returns>
|
||||
public static string Substring(this string source, string startString, params string[] endStrings)
|
||||
{
|
||||
if (source.IsMissing())
|
||||
return string.Empty;
|
||||
|
||||
int startIndex = 0;
|
||||
if (!string.IsNullOrEmpty(startString))
|
||||
{
|
||||
startIndex = source.IndexOf(startString, StringComparison.OrdinalIgnoreCase);
|
||||
if (startIndex < 0)
|
||||
throw new InvalidOperationException(string.Format("在源字符串中无法找到“{0}”的子串位置", startString));
|
||||
|
||||
startIndex = startIndex + startString.Length;
|
||||
}
|
||||
|
||||
int endIndex = source.Length;
|
||||
endStrings = endStrings.OrderByDescending(m => m.Length).ToArray();
|
||||
foreach (string endString in endStrings)
|
||||
{
|
||||
if (string.IsNullOrEmpty(endString))
|
||||
{
|
||||
endIndex = source.Length;
|
||||
break;
|
||||
}
|
||||
|
||||
endIndex = source.IndexOf(endString, startIndex, StringComparison.OrdinalIgnoreCase);
|
||||
if (endIndex < 0 || endIndex < startIndex)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (endIndex < 0 || endIndex < startIndex)
|
||||
{
|
||||
throw new InvalidOperationException(string.Format("在源字符串中无法找到“{0}”的子串位置", endStrings.ExpandAndToString()));
|
||||
}
|
||||
|
||||
int length = endIndex - startIndex;
|
||||
return source.Substring(startIndex, length);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 用正则表达式截取字符串.
|
||||
/// </summary>
|
||||
public static string? Substring2(this string source, string startString, string endString)
|
||||
{
|
||||
return source.Substring2(startString, endString, false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 用正则表达式截取字符串.
|
||||
/// </summary>
|
||||
public static string? Substring2(this string source, string startString, string endString, bool containsEmpty)
|
||||
{
|
||||
if (source.IsMissing())
|
||||
return string.Empty;
|
||||
|
||||
string inner = containsEmpty ? "\\s\\S" : "\\S";
|
||||
string result = source.Match(string.Format("(?<={0})([{1}]+?)(?={2})", startString, inner, endString));
|
||||
return result.IsMissing() ? null : result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 截取{}中的字符串.
|
||||
/// </summary>
|
||||
/// <param name="source"></param>
|
||||
/// <returns></returns>
|
||||
public static List<string> Substring3(this string source)
|
||||
{
|
||||
MatchCollection mc = Regex.Matches(source, "(?i){.*?}");
|
||||
return mc.Cast<Match>().Select(m => m.Value.TrimStart('{').TrimEnd('}')).ToList();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 是否电子邮件.
|
||||
/// </summary>
|
||||
public static bool IsEmail(this string value)
|
||||
{
|
||||
const string pattern = @"^[\w-]+(\.[\w-]+)*@[\w-]+(\.[\w-]+)+$";
|
||||
return value.IsMatch(pattern);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 是否是IP地址.
|
||||
/// </summary>
|
||||
public static bool IsIpAddress(this string value)
|
||||
{
|
||||
const string pattern = @"^((?:(?:25[0-5]|2[0-4]\d|((1\d{2})|([1-9]?\d)))\.){3}(?:25[0-5]|2[0-4]\d|((1\d{2})|([1-9]?\d))))$";
|
||||
return value.IsMatch(pattern);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 是否是整数.
|
||||
/// </summary>
|
||||
public static bool IsNumeric(this string value)
|
||||
{
|
||||
const string pattern = @"^\-?[0-9]+$";
|
||||
return value.IsMatch(pattern);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 是否是Unicode字符串.
|
||||
/// </summary>
|
||||
public static bool IsUnicode(this string value)
|
||||
{
|
||||
const string pattern = @"^[\u4E00-\u9FA5\uE815-\uFA29]+$";
|
||||
return value.IsMatch(pattern);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 是否Url字符串.
|
||||
/// </summary>
|
||||
public static bool IsUrl(this string value)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (value.IsNullOrEmpty() || value.Contains(' '))
|
||||
return false;
|
||||
|
||||
Uri uri = new Uri(value);
|
||||
return true;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 是否身份证号,验证如下3种情况:
|
||||
/// 1.身份证号码为15位数字;
|
||||
/// 2.身份证号码为18位数字;
|
||||
/// 3.身份证号码为17位数字+1个字母.
|
||||
/// </summary>
|
||||
public static bool IsIdentityCardId(this string value)
|
||||
{
|
||||
if (value.Length != 15 && value.Length != 18)
|
||||
return false;
|
||||
|
||||
Regex regex;
|
||||
string[] array;
|
||||
DateTime time;
|
||||
if (value.Length == 15)
|
||||
{
|
||||
regex = new Regex(@"^(\d{6})(\d{2})(\d{2})(\d{2})(\d{3})_");
|
||||
if (!regex.Match(value).Success)
|
||||
return false;
|
||||
|
||||
array = regex.Split(value);
|
||||
return DateTime.TryParse(string.Format("{0}-{1}-{2}", "19" + array[2], array[3], array[4]), out time);
|
||||
}
|
||||
|
||||
regex = new Regex(@"^(\d{6})(\d{4})(\d{2})(\d{2})(\d{3})([0-9Xx])$");
|
||||
if (!regex.Match(value).Success)
|
||||
return false;
|
||||
|
||||
array = regex.Split(value);
|
||||
if (!DateTime.TryParse(string.Format("{0}-{1}-{2}", array[2], array[3], array[4]), out time))
|
||||
return false;
|
||||
|
||||
// 校验最后一位
|
||||
string[] chars = value.ToCharArray().Select(m => m.ToString()).ToArray();
|
||||
int[] weights = { 7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2 };
|
||||
int sum = 0;
|
||||
for (int i = 0; i < 17; i++)
|
||||
{
|
||||
int num = int.Parse(chars[i]);
|
||||
sum = sum + (num * weights[i]);
|
||||
}
|
||||
|
||||
int mod = sum % 11;
|
||||
|
||||
// 检验码字符串
|
||||
string vCode = "10X98765432";
|
||||
string last = vCode.ToCharArray().ElementAt(mod).ToString();
|
||||
return chars.Last().ToUpper() == last;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 是否手机号码.
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
/// <param name="isRestrict">是否按严格格式验证.</param>
|
||||
public static bool IsMobileNumber(this string value, bool isRestrict = false)
|
||||
{
|
||||
string pattern = isRestrict ? @"^[1][3-8]\d{9}$" : @"^[1]\d{10}$";
|
||||
return value.IsMatch(pattern);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 其他操作
|
||||
|
||||
/// <summary>
|
||||
/// 指示指定的字符串是 null 或者 System.String.Empty 字符串.
|
||||
/// </summary>
|
||||
[DebuggerStepThrough]
|
||||
public static bool IsNullOrEmpty(this string value)
|
||||
{
|
||||
return string.IsNullOrEmpty(value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 指示指定的字符串是 null、空或者仅由空白字符组成.
|
||||
/// </summary>
|
||||
[DebuggerStepThrough]
|
||||
public static bool IsNullOrWhiteSpace(this string value)
|
||||
{
|
||||
return string.IsNullOrWhiteSpace(value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 指示指定的字符串是 null、空或者仅由空白字符组成.
|
||||
/// </summary>
|
||||
[DebuggerStepThrough]
|
||||
public static bool IsMissing(this string value)
|
||||
{
|
||||
return string.IsNullOrWhiteSpace(value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 为指定格式的字符串填充相应对象来生成字符串.
|
||||
/// </summary>
|
||||
/// <param name="format">字符串格式,占位符以{n}表示.</param>
|
||||
/// <param name="args">用于填充占位符的参数.</param>
|
||||
/// <returns>格式化后的字符串.</returns>
|
||||
[DebuggerStepThrough]
|
||||
public static string FormatWith(this string format, params object[] args)
|
||||
{
|
||||
return string.Format(CultureInfo.CurrentCulture, format, args);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将字符串反转.
|
||||
/// </summary>
|
||||
/// <param name="value">要反转的字符串.</param>
|
||||
public static string ReverseString(this string value)
|
||||
{
|
||||
return new string(value.Reverse().ToArray());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 单词变成单数形式.
|
||||
/// </summary>
|
||||
/// <param name="word"></param>
|
||||
/// <returns></returns>
|
||||
public static string ToSingular(this string word)
|
||||
{
|
||||
Regex plural1 = new Regex("(?<keep>[^aeiou])ies$");
|
||||
Regex plural2 = new Regex("(?<keep>[aeiou]y)s$");
|
||||
Regex plural3 = new Regex("(?<keep>[sxzh])es$");
|
||||
Regex plural4 = new Regex("(?<keep>[^sxzhyu])s$");
|
||||
|
||||
if (plural1.IsMatch(word))
|
||||
return plural1.Replace(word, "${keep}y");
|
||||
if (plural2.IsMatch(word))
|
||||
return plural2.Replace(word, "${keep}");
|
||||
if (plural3.IsMatch(word))
|
||||
return plural3.Replace(word, "${keep}");
|
||||
if (plural4.IsMatch(word))
|
||||
return plural4.Replace(word, "${keep}");
|
||||
|
||||
return word;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 单词变成复数形式.
|
||||
/// </summary>
|
||||
/// <param name="word"></param>
|
||||
/// <returns></returns>
|
||||
public static string ToPlural(this string word)
|
||||
{
|
||||
Regex plural1 = new Regex("(?<keep>[^aeiou])y$");
|
||||
Regex plural2 = new Regex("(?<keep>[aeiou]y)$");
|
||||
Regex plural3 = new Regex("(?<keep>[sxzh])$");
|
||||
Regex plural4 = new Regex("(?<keep>[^sxzhy])$");
|
||||
|
||||
if (plural1.IsMatch(word))
|
||||
return plural1.Replace(word, "${keep}ies");
|
||||
if (plural2.IsMatch(word))
|
||||
return plural2.Replace(word, "${keep}s");
|
||||
if (plural3.IsMatch(word))
|
||||
return plural3.Replace(word, "${keep}es");
|
||||
if (plural4.IsMatch(word))
|
||||
return plural4.Replace(word, "${keep}s");
|
||||
|
||||
return word;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 判断指定路径是否图片文件.
|
||||
/// </summary>
|
||||
public static bool IsImageFile(this string filename)
|
||||
{
|
||||
if (!File.Exists(filename))
|
||||
return false;
|
||||
byte[] fileData = File.ReadAllBytes(filename);
|
||||
if (fileData.Length == 0)
|
||||
return false;
|
||||
ushort code = BitConverter.ToUInt16(fileData, 0);
|
||||
switch (code)
|
||||
{
|
||||
// bmp
|
||||
case 0x4D42:
|
||||
// jpg
|
||||
case 0xD8FF:
|
||||
// gif
|
||||
case 0x4947:
|
||||
// png
|
||||
case 0x5089:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 以指定字符串作为分隔符将指定字符串分隔成数组.
|
||||
/// </summary>
|
||||
/// <param name="value">要分割的字符串.</param>
|
||||
/// <param name="strSplit">字符串类型的分隔符.</param>
|
||||
/// <param name="removeEmptyEntries">是否移除数据中元素为空字符串的项.</param>
|
||||
/// <returns>分割后的数据.</returns>
|
||||
public static string[] Split(this string value, string strSplit, bool removeEmptyEntries = false)
|
||||
{
|
||||
return value.Split(new[] { strSplit }, removeEmptyEntries ? StringSplitOptions.RemoveEmptyEntries : StringSplitOptions.None);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取字符串的MD5 Hash值.
|
||||
/// </summary>
|
||||
public static string ToMd5Hash(this string value)
|
||||
{
|
||||
return HashHelper.GetMd5(value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 支持汉字的字符串长度,汉字长度计为2.
|
||||
/// </summary>
|
||||
/// <param name="value">参数字符串.</param>
|
||||
/// <returns>当前字符串的长度,汉字长度为2.</returns>
|
||||
public static int TextLength(this string value)
|
||||
{
|
||||
ASCIIEncoding ascii = new ASCIIEncoding();
|
||||
int tempLen = 0;
|
||||
byte[] bytes = ascii.GetBytes(value);
|
||||
foreach (byte b in bytes)
|
||||
{
|
||||
if (b == 63)
|
||||
tempLen += 2;
|
||||
else
|
||||
tempLen += 1;
|
||||
}
|
||||
|
||||
return tempLen;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将JSON字符串还原为对象.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">要转换的目标类型.</typeparam>
|
||||
/// <param name="json">JSON字符串. </param>
|
||||
/// <returns></returns>
|
||||
public static T? FromJsonString<T>(this string json) => JsonSerializer.Deserialize<T>(json);
|
||||
|
||||
/// <summary>
|
||||
/// 将JSON字符串还原为对象.
|
||||
/// </summary>
|
||||
/// <param name="json">JSON字符串. </param>
|
||||
/// <param name="type">数据类型.</param>
|
||||
public static object? FromJsonString(this string json, Type type) => JsonSerializer.Deserialize(json, type);
|
||||
|
||||
/// <summary>
|
||||
/// 给URL添加查询参数.
|
||||
/// </summary>
|
||||
/// <param name="url">URL字符串.</param>
|
||||
/// <param name="queries">要添加的参数,形如:"id=1,cid=2".</param>
|
||||
/// <returns></returns>
|
||||
public static string AddUrlQuery(this string url, params string[] queries)
|
||||
{
|
||||
foreach (string query in queries)
|
||||
{
|
||||
if (!url.Contains('?'))
|
||||
url += "?";
|
||||
else if (!url.EndsWith("&"))
|
||||
url += "&";
|
||||
|
||||
url = url + query;
|
||||
}
|
||||
|
||||
return url;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取URL中指定参数的值,不存在返回空字符串.
|
||||
/// </summary>
|
||||
public static string GetUrlQuery(this string url, string key)
|
||||
{
|
||||
Uri uri = new Uri(url);
|
||||
string query = uri.Query;
|
||||
if (query.IsNullOrEmpty())
|
||||
return string.Empty;
|
||||
|
||||
query = query.TrimStart('?');
|
||||
Dictionary<string, string>? dict = (from m in query.Split("&", true)
|
||||
let strs = m.Split("=")
|
||||
select new KeyValuePair<string, string>(strs[0], strs[1]))
|
||||
.ToDictionary(m => m.Key, m => m.Value);
|
||||
if (dict.ContainsKey(key))
|
||||
return dict[key];
|
||||
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 给URL添加 # 参数.
|
||||
/// </summary>
|
||||
/// <param name="url">URL字符串.</param>
|
||||
/// <param name="query">要添加的参数.</param>
|
||||
/// <returns></returns>
|
||||
public static string AddHashFragment(this string url, string query)
|
||||
{
|
||||
if (!url.Contains("#"))
|
||||
url += "#";
|
||||
|
||||
return url + query;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将字符串转换为<see cref="byte"/>[]数组,默认编码为<see cref="Encoding.UTF8"/>.
|
||||
/// </summary>
|
||||
public static byte[] ToBytes(this string value, Encoding? encoding = null)
|
||||
{
|
||||
if (encoding == null)
|
||||
encoding = Encoding.UTF8;
|
||||
|
||||
return encoding.GetBytes(value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将<see cref="byte"/>[]数组转换为字符串,默认编码为<see cref="Encoding.UTF8"/>.
|
||||
/// </summary>
|
||||
public static string ToString2(this byte[] bytes, Encoding? encoding = null)
|
||||
{
|
||||
if (encoding == null)
|
||||
encoding = Encoding.UTF8;
|
||||
|
||||
return encoding.GetString(bytes);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将<see cref="byte"/>[]数组转换为Base64字符串.
|
||||
/// </summary>
|
||||
public static string ToBase64String(this byte[] bytes)
|
||||
{
|
||||
return Convert.ToBase64String(bytes);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将字符串转换为Base64字符串,默认编码为<see cref="Encoding.UTF8"/>.
|
||||
/// </summary>
|
||||
/// <param name="source">正常的字符串.</param>
|
||||
/// <param name="encoding">编码.</param>
|
||||
/// <returns>Base64字符串.</returns>
|
||||
public static string ToBase64String(this string source, Encoding? encoding = null)
|
||||
{
|
||||
if (encoding == null)
|
||||
encoding = Encoding.UTF8;
|
||||
|
||||
return Convert.ToBase64String(encoding.GetBytes(source));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将Base64字符串转换为正常字符串,默认编码为<see cref="Encoding.UTF8"/>.
|
||||
/// </summary>
|
||||
/// <param name="base64String">Base64字符串.</param>
|
||||
/// <param name="encoding">编码.</param>
|
||||
/// <returns>正常字符串.</returns>
|
||||
public static string FromBase64String(this string base64String, Encoding? encoding = null)
|
||||
{
|
||||
if (encoding == null)
|
||||
encoding = Encoding.UTF8;
|
||||
|
||||
byte[] bytes = Convert.FromBase64String(base64String);
|
||||
return encoding.GetString(bytes);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将字符串进行UrlDecode解码.
|
||||
/// </summary>
|
||||
/// <param name="source">待UrlDecode解码的字符串.</param>
|
||||
/// <returns>UrlDecode解码后的字符串.</returns>
|
||||
public static string ToUrlDecode(this string source)
|
||||
{
|
||||
return HttpUtility.UrlDecode(source);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将字符串进行UrlEncode编码.
|
||||
/// </summary>
|
||||
/// <param name="source">待UrlEncode编码的字符串.</param>
|
||||
/// <returns>UrlEncode编码后的字符串.</returns>
|
||||
public static string ToUrlEncode(this string source)
|
||||
{
|
||||
return HttpUtility.UrlEncode(source);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将字符串进行HtmlDecode解码.
|
||||
/// </summary>
|
||||
/// <param name="source">待HtmlDecode解码的字符串.</param>
|
||||
/// <returns>HtmlDecode解码后的字符串.</returns>
|
||||
public static string ToHtmlDecode(this string source)
|
||||
{
|
||||
return HttpUtility.HtmlDecode(source);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将字符串进行HtmlEncode编码.
|
||||
/// </summary>
|
||||
/// <param name="source">待HtmlEncode编码的字符串.</param>
|
||||
/// <returns>HtmlEncode编码后的字符串.</returns>
|
||||
public static string ToHtmlEncode(this string source)
|
||||
{
|
||||
return HttpUtility.HtmlEncode(source);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将字符串转换为十六进制字符串,默认编码为<see cref="Encoding.UTF8"/>.
|
||||
/// </summary>
|
||||
public static string ToHexString(this string source, Encoding? encoding = null)
|
||||
{
|
||||
if (encoding == null)
|
||||
encoding = Encoding.UTF8;
|
||||
|
||||
byte[] bytes = encoding.GetBytes(source);
|
||||
return bytes.ToHexString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将十六进制字符串转换为常规字符串,默认编码为<see cref="Encoding.UTF8"/>.
|
||||
/// </summary>
|
||||
public static string FromHexString(this string hexString, Encoding? encoding = null)
|
||||
{
|
||||
if (encoding == null)
|
||||
encoding = Encoding.UTF8;
|
||||
|
||||
byte[] bytes = hexString.ToHexBytes();
|
||||
return encoding.GetString(bytes);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将byte[]编码为十六进制字符串.
|
||||
/// </summary>
|
||||
/// <param name="bytes">byte[]数组.</param>
|
||||
/// <returns>十六进制字符串.</returns>
|
||||
public static string ToHexString(this byte[] bytes)
|
||||
{
|
||||
return bytes.Aggregate(string.Empty, (current, t) => current + t.ToString("X2"));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将十六进制字符串转换为byte[].
|
||||
/// </summary>
|
||||
/// <param name="hexString">十六进制字符串.</param>
|
||||
/// <returns>byte[]数组.</returns>
|
||||
public static byte[] ToHexBytes(this string hexString)
|
||||
{
|
||||
hexString = hexString ?? string.Empty;
|
||||
hexString = hexString.Replace(" ", string.Empty);
|
||||
byte[] bytes = new byte[hexString.Length / 2];
|
||||
for (int i = 0; i < bytes.Length; i++)
|
||||
{
|
||||
bytes[i] = Convert.ToByte(hexString.Substring(i * 2, 2), 16);
|
||||
}
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将字符串进行Unicode编码,变成形如“\u7f16\u7801”的形式.
|
||||
/// </summary>
|
||||
/// <param name="source">要进行编号的字符串.</param>
|
||||
public static string ToUnicodeString(this string source)
|
||||
{
|
||||
Regex regex = new Regex(@"[^\u0000-\u00ff]");
|
||||
return regex.Replace(source, m => string.Format(@"\u{0:x4}", (short)m.Value[0]));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将形如“\u7f16\u7801”的Unicode字符串解码.
|
||||
/// </summary>
|
||||
public static string FromUnicodeString(this string source)
|
||||
{
|
||||
Regex regex = new Regex(@"\\u([0-9a-fA-F]{4})", RegexOptions.Compiled);
|
||||
return regex.Replace(
|
||||
source,
|
||||
m =>
|
||||
{
|
||||
short s;
|
||||
if (short.TryParse(m.Groups[1].Value, NumberStyles.HexNumber, CultureInfo.InstalledUICulture, out s))
|
||||
return string.Empty + (char)s;
|
||||
|
||||
return m.Value;
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将驼峰字符串按单词拆分并转换成小写,再以特定字符串分隔.
|
||||
/// </summary>
|
||||
/// <param name="str">待转换的字符串.</param>
|
||||
/// <param name="splitStr">分隔符字符.</param>
|
||||
/// <returns></returns>
|
||||
public static string UpperToLowerAndSplit(this string str, string splitStr = "-")
|
||||
{
|
||||
if (string.IsNullOrEmpty(str))
|
||||
return str;
|
||||
|
||||
List<string> words = new List<string>();
|
||||
while (str.Length > 0)
|
||||
{
|
||||
char c = str.FirstOrDefault(char.IsUpper);
|
||||
if (c == default(char))
|
||||
{
|
||||
words.Add(str);
|
||||
break;
|
||||
}
|
||||
|
||||
int upperIndex = str.IndexOf(c);
|
||||
|
||||
// admin
|
||||
if (upperIndex < 0)
|
||||
return str;
|
||||
|
||||
// adminAdmin
|
||||
if (upperIndex > 0)
|
||||
{
|
||||
string first = str.Substring(0, upperIndex);
|
||||
words.Add(first);
|
||||
str = str.Substring(upperIndex, str.Length - upperIndex);
|
||||
continue;
|
||||
}
|
||||
|
||||
str = char.ToLower(str[0]) + str.Substring(1, str.Length - 1);
|
||||
}
|
||||
|
||||
return words.ExpandAndToString(splitStr);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将驼峰字符串的第一个字符小写.
|
||||
/// </summary>
|
||||
public static string ToLowerCase(this string str)
|
||||
{
|
||||
if (string.IsNullOrEmpty(str) || !char.IsUpper(str[0]))
|
||||
return str;
|
||||
|
||||
if (str.Length == 1)
|
||||
return char.ToLower(str[0]).ToString();
|
||||
|
||||
return char.ToLower(str[0]) + str.Substring(1, str.Length - 1);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将小驼峰字符串的第一个字符大写.
|
||||
/// </summary>
|
||||
public static string ToUpperCase(this string str)
|
||||
{
|
||||
if (string.IsNullOrEmpty(str) || !char.IsLower(str[0]))
|
||||
return str;
|
||||
|
||||
if (str.Length == 1)
|
||||
return char.ToUpper(str[0]).ToString();
|
||||
|
||||
return char.ToUpper(str[0]) + str.Substring(1, str.Length - 1);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 计算当前字符串与指定字符串的编辑距离(相似度).
|
||||
/// </summary>
|
||||
/// <param name="source">源字符串.</param>
|
||||
/// <param name="target">目标字符串.</param>
|
||||
/// <param name="similarity">输出相似度.</param>
|
||||
/// <param name="ignoreCase">是否忽略大小写.</param>
|
||||
/// <returns>编辑距离.</returns>
|
||||
public static int LevenshteinDistance(this string source, string target, out double similarity, bool ignoreCase = false)
|
||||
{
|
||||
if (string.IsNullOrEmpty(source))
|
||||
{
|
||||
if (string.IsNullOrEmpty(target))
|
||||
{
|
||||
similarity = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
similarity = 0;
|
||||
return target.Length;
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(target))
|
||||
{
|
||||
similarity = 0;
|
||||
return source.Length;
|
||||
}
|
||||
|
||||
string from, to;
|
||||
if (ignoreCase)
|
||||
{
|
||||
from = source;
|
||||
to = target;
|
||||
}
|
||||
else
|
||||
{
|
||||
from = source.ToLower();
|
||||
to = source.ToLower();
|
||||
}
|
||||
|
||||
int m = from.Length, n = to.Length;
|
||||
int[,] mn = new int[m + 1, n + 1];
|
||||
for (int i = 0; i <= m; i++)
|
||||
{
|
||||
mn[i, 0] = i;
|
||||
}
|
||||
|
||||
for (int j = 1; j <= n; j++)
|
||||
{
|
||||
mn[0, j] = j;
|
||||
}
|
||||
|
||||
for (int i = 1; i <= m; i++)
|
||||
{
|
||||
char c = from[i - 1];
|
||||
for (int j = 1; j <= n; j++)
|
||||
{
|
||||
if (c == to[j - 1])
|
||||
{
|
||||
mn[i, j] = mn[i - 1, j - 1];
|
||||
}
|
||||
else
|
||||
{
|
||||
mn[i, j] = Math.Min(mn[i - 1, j - 1], Math.Min(mn[i - 1, j], mn[i, j - 1])) + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int maxLength = Math.Max(m, n);
|
||||
similarity = (double)(maxLength - mn[m, n]) / maxLength;
|
||||
return mn[m, n];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 计算两个字符串的相似度,应用公式:相似度=kq*q/(kq*q+kr*r+ks*s)(kq>0,kr>=0,ka>=0)
|
||||
/// 其中,q是字符串1和字符串2中都存在的单词的总数,s是字符串1中存在,字符串2中不存在的单词总数,r是字符串2中存在,字符串1中不存在的单词总数. kq,kr和ka分别是q,r,s的权重,根据实际的计算情况,我们设kq=2,kr=ks=1.
|
||||
/// </summary>
|
||||
/// <param name="source">源字符串.</param>
|
||||
/// <param name="target">目标字符串.</param>
|
||||
/// <param name="ignoreCase">是否忽略大小写.</param>
|
||||
/// <returns>字符串相似度.</returns>
|
||||
public static double GetSimilarityWith(this string source, string target, bool ignoreCase = false)
|
||||
{
|
||||
if (string.IsNullOrEmpty(source) && string.IsNullOrEmpty(target))
|
||||
return 1;
|
||||
|
||||
if (string.IsNullOrEmpty(source) || string.IsNullOrEmpty(target))
|
||||
return 0;
|
||||
|
||||
const double kq = 2, kr = 1, ks = 1;
|
||||
char[] sourceChars = source.ToCharArray(), targetChars = target.ToCharArray();
|
||||
|
||||
// 获取交集数量
|
||||
int q = sourceChars.Intersect(targetChars).Count(), s = sourceChars.Length - q, r = targetChars.Length - q;
|
||||
return kq * q / ((kq * q) + (kr * r) + (ks * s));
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
Reference in New Issue
Block a user