using NCC.Dependency;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Text.Json;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
namespace NCC.Extensions
{
///
/// 对象拓展类
///
[SuppressSniffer]
public static class ObjectExtensions
{
///
/// 将 DateTimeOffset 转换成本地 DateTime
///
///
///
public static DateTime ConvertToDateTime(this DateTimeOffset dateTime)
{
if (dateTime.Offset.Equals(TimeSpan.Zero))
return dateTime.UtcDateTime;
if (dateTime.Offset.Equals(TimeZoneInfo.Local.GetUtcOffset(dateTime.DateTime)))
return dateTime.ToLocalTime().DateTime;
else
return dateTime.DateTime;
}
///
/// 将 DateTime 转换成 DateTimeOffset
///
///
///
public static DateTimeOffset ConvertToDateTimeOffset(this DateTime dateTime)
{
return DateTime.SpecifyKind(dateTime, DateTimeKind.Local);
}
///
/// 判断是否是富基元类型
///
/// 类型
///
internal static bool IsRichPrimitive(this Type type)
{
// 处理元组类型
if (type.IsValueTuple()) return false;
// 处理数组类型,基元数组类型也可以是基元类型
if (type.IsArray) return type.GetElementType().IsRichPrimitive();
// 基元类型或值类型或字符串类型
if (type.IsPrimitive || type.IsValueType || type == typeof(string)) return true;
if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>)) return type.GenericTypeArguments[0].IsRichPrimitive();
return false;
}
///
/// 合并两个字典
///
///
/// 字典
/// 新字典
///
internal static Dictionary AddOrUpdate(this Dictionary dic, Dictionary newDic)
{
foreach (var key in newDic.Keys)
{
if (dic.ContainsKey(key))
dic[key] = newDic[key];
else
dic.Add(key, newDic[key]);
}
return dic;
}
///
/// 合并两个字典
///
///
/// 字典
/// 新字典
internal static void AddOrUpdate(this ConcurrentDictionary dic, Dictionary newDic)
{
foreach (var (key, value) in newDic)
{
dic.AddOrUpdate(key, value, (key, old) => value);
}
}
///
/// 判断是否是元组类型
///
/// 类型
///
internal static bool IsValueTuple(this Type type)
{
return type.ToString().StartsWith(typeof(ValueTuple).FullName);
}
///
/// 判断方法是否是异步
///
/// 方法
///
internal static bool IsAsync(this MethodInfo method)
{
return method.GetCustomAttribute() != null
|| method.ReturnType.ToString().StartsWith(typeof(Task).FullName);
}
///
/// 判断类型是否实现某个泛型
///
/// 类型
/// 泛型类型
/// bool
internal static bool HasImplementedRawGeneric(this Type type, Type generic)
{
// 检查接口类型
var isTheRawGenericType = type.GetInterfaces().Any(IsTheRawGenericType);
if (isTheRawGenericType) return true;
// 检查类型
while (type != null && type != typeof(object))
{
isTheRawGenericType = IsTheRawGenericType(type);
if (isTheRawGenericType) return true;
type = type.BaseType;
}
return false;
// 判断逻辑
bool IsTheRawGenericType(Type type) => generic == (type.IsGenericType ? type.GetGenericTypeDefinition() : type);
}
///
/// 判断是否是匿名类型
///
/// 对象
///
internal static bool IsAnonymous(this object obj)
{
var type = obj.GetType();
return Attribute.IsDefined(type, typeof(CompilerGeneratedAttribute), false)
&& type.IsGenericType && type.Name.Contains("AnonymousType")
&& (type.Name.StartsWith("<>") || type.Name.StartsWith("VB$"))
&& type.Attributes.HasFlag(TypeAttributes.NotPublic);
}
///
/// 获取所有祖先类型
///
///
///
internal static IEnumerable GetAncestorTypes(this Type type)
{
var ancestorTypes = new List();
while (type != null && type != typeof(object))
{
if (IsNoObjectBaseType(type))
{
var baseType = type.BaseType;
ancestorTypes.Add(baseType);
type = baseType;
}
else break;
}
return ancestorTypes;
static bool IsNoObjectBaseType(Type type) => type.BaseType != typeof(object);
}
///
/// 获取方法真实返回类型
///
///
///
internal static Type GetRealReturnType(this MethodInfo method)
{
// 判断是否是异步方法
var isAsyncMethod = method.IsAsync();
// 获取类型返回值并处理 Task 和 Task 类型返回值
var returnType = method.ReturnType;
return isAsyncMethod ? (returnType.GenericTypeArguments.FirstOrDefault() ?? typeof(void)) : returnType;
}
///
/// 将一个对象转换为指定类型
///
///
///
///
internal static T ChangeType(this object obj)
{
return (T)ChangeType(obj, typeof(T));
}
///
/// 将一个对象转换为指定类型
///
/// 待转换的对象
/// 目标类型
/// 转换后的对象
internal static object ChangeType(this object obj, Type type)
{
if (type == null) return obj;
if (type == typeof(string)) return obj?.ToString();
if (type == typeof(Guid) && obj != null) return Guid.Parse(obj.ToString());
if (obj == null) return type.IsValueType ? Activator.CreateInstance(type) : null;
var underlyingType = Nullable.GetUnderlyingType(type);
if (type.IsAssignableFrom(obj.GetType())) return obj;
else if ((underlyingType ?? type).IsEnum)
{
if (underlyingType != null && string.IsNullOrWhiteSpace(obj.ToString())) return null;
else return Enum.Parse(underlyingType ?? type, obj.ToString());
}
// 处理DateTime -> DateTimeOffset 类型
else if (obj.GetType().Equals(typeof(DateTime)) && (underlyingType ?? type).Equals(typeof(DateTimeOffset)))
{
return ((DateTime)obj).ConvertToDateTimeOffset();
}
// 处理 DateTimeOffset -> DateTime 类型
else if (obj.GetType().Equals(typeof(DateTimeOffset)) && (underlyingType ?? type).Equals(typeof(DateTime)))
{
return ((DateTimeOffset)obj).ConvertToDateTime();
}
else if (typeof(IConvertible).IsAssignableFrom(underlyingType ?? type))
{
try
{
return Convert.ChangeType(obj, underlyingType ?? type, null);
}
catch
{
return underlyingType == null ? Activator.CreateInstance(type) : null;
}
}
else
{
var converter = TypeDescriptor.GetConverter(type);
if (converter.CanConvertFrom(obj.GetType())) return converter.ConvertFrom(obj);
var constructor = type.GetConstructor(Type.EmptyTypes);
if (constructor != null)
{
var o = constructor.Invoke(null);
var propertys = type.GetProperties();
var oldType = obj.GetType();
foreach (var property in propertys)
{
var p = oldType.GetProperty(property.Name);
if (property.CanWrite && p != null && p.CanRead)
{
property.SetValue(o, ChangeType(p.GetValue(obj, null), property.PropertyType), null);
}
}
return o;
}
}
return obj;
}
///
/// 查找方法指定特性,如果没找到则继续查找声明类
///
///
///
///
///
internal static TAttribute GetFoundAttribute(this MethodInfo method, bool inherit)
where TAttribute : Attribute
{
// 获取方法所在类型
var declaringType = method.DeclaringType;
var attributeType = typeof(TAttribute);
// 判断方法是否定义指定特性,如果没有再查找声明类
var foundAttribute = method.IsDefined(attributeType, inherit)
? method.GetCustomAttribute(inherit)
: (
declaringType.IsDefined(attributeType, inherit)
? declaringType.GetCustomAttribute(inherit)
: default
);
return foundAttribute;
}
///
/// 格式化字符串
///
///
///
///
internal static string Format(this string str, params object[] args)
{
return args == null || args.Length == 0 ? str : string.Format(str, args);
}
///
/// 切割骆驼命名式字符串
///
///
///
internal static string[] SplitCamelCase(this string str)
{
if (str == null) return Array.Empty();
if (string.IsNullOrWhiteSpace(str)) return new string[] { str };
if (str.Length == 1) return new string[] { str };
return Regex.Split(str, @"(?=\p{Lu}\p{Ll})|(?<=\p{Ll})(?=\p{Lu})")
.Where(u => u.Length > 0)
.ToArray();
}
///
/// JsonElement 转 Object
///
///
///
internal static object ToObject(this JsonElement jsonElement)
{
switch (jsonElement.ValueKind)
{
case JsonValueKind.String:
return jsonElement.GetString();
case JsonValueKind.Undefined:
case JsonValueKind.Null:
return default;
case JsonValueKind.Number:
return jsonElement.GetDecimal();
case JsonValueKind.True:
case JsonValueKind.False:
return jsonElement.GetBoolean();
case JsonValueKind.Object:
var enumerateObject = jsonElement.EnumerateObject();
var dic = new Dictionary();
foreach (var item in enumerateObject)
{
dic.Add(item.Name, item.Value.ToObject());
}
return dic;
case JsonValueKind.Array:
var enumerateArray = jsonElement.EnumerateArray();
var list = new List