using System; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Reflection; using System.Text.Json; namespace Falcon.SugarApi { /// /// Object类型扩展方法 /// public static class ObjectExtend { /// /// 对source进行浅表复制,并复制到target中 /// /// 原对象类型 /// 原对象 /// 目标对象 /// 忽略大小写。默认false不忽略大小写 public static TSource CloneTo(this TSource source,[NotNull] object target,bool ignoreCase = false) where TSource : class { _ = source ?? throw new ArgumentNullException(nameof(source)); _ = target ?? throw new ArgumentNullException(nameof(target)); var all = from s in source.GetType().GetProperties() join t in target.GetType().GetProperties() on ignoreCase ? s.Name.ToLower() : s.Name equals ignoreCase ? t.Name.ToLower() : t.Name select new { s,t }; foreach(var item in all) { item.t.SetValue(target,item.s.GetValue(source).ChangeType(item.t.PropertyType)); } return source; } /// /// 从原对象中浅表复制属性值 /// /// 目标对象类型 /// 目标对象 /// 原对象 /// 忽略大小写。默认false不忽略大小写 /// 目标对象 public static Ttarget CloneFrom(this Ttarget target,object source,bool ignoreCase = false) where Ttarget : class { source.CloneTo(target,ignoreCase); return target; } /// /// 将对象转换成另一类型,如果转换失败可能返回null。 /// /// 原对象 /// 目标类型 /// 转换后的类型 public static object? ChangeType(this object? source,Type targetType) { if(targetType == null) { throw new ArgumentNullException("targetType"); } if(source == null) { return null; } if(targetType.IsGenericType && targetType.GetGenericTypeDefinition().Equals(typeof(Nullable<>))) { NullableConverter nullableConverter = new NullableConverter(targetType); targetType = nullableConverter.UnderlyingType; } return Convert.ChangeType(source,targetType); } /// /// 如果对象为null则抛出异常 /// /// 检测对象 /// 对象本身 /// 对象为null public static object? ThrowNullExceptionWhenNull(this object? obj) { if(obj == null) { throw new ArgumentNullException(); } return obj; } /// /// 扩展对象,获取属性枚举s /// /// 要扩展的对象 /// public static IEnumerable ExpandProperties(this object obj) { foreach(PropertyInfo p in obj.GetType().GetProperties()) { yield return new ExpandPropertyInfo { TargetObj = obj, Name = p.Name, Type = p.PropertyType, Value = p.CanRead ? p.GetValue(obj) : null, SetValue = new Action(v => p.SetValue(obj,v)), }; } } /// /// 对象是否为null /// /// 要测试的对象 /// True表示对象为null,否则不为null public static bool IsNull([AllowNull] this object obj) => obj == null; /// /// 对象是否不为null。与IsNull相反 /// /// 要测试的对象 /// True表示对象不为null,否则为null public static bool IsNotNull([AllowNull] this object obj) => !obj.IsNull(); /// /// 为对象属性设置属性值 /// /// 要设置的对象 /// 通过属性和原始值获取新值的方法委托 /// 设置属性值引发的异常 public static T SetPropertyValue(this T obj,Func getValue) where T : class { foreach(PropertyInfo info in obj.GetType().GetProperties()) { if(info.CanWrite && info.CanRead) { object? originalVal = info.GetValue(obj); var val = getValue(info,originalVal); try { info.SetValue(obj,val); } catch(Exception ex) { throw new ObjectSetValueException(obj,info,val,ex); } } } return obj; } /// /// 将对象转换为Json字符串格式 /// /// 对象的类型 /// 对象 /// 转换参数 /// 转换后字符串 public static string ToJson(this T obj,Action? OptionBuilder = null) { var option = new JsonSerializerOptions(); OptionBuilder?.Invoke(option); var ser = new JsonSerialize.JsonSerializeFactory().CreateJsonSerialize(option); return ser.Serialize(obj); } /// /// 获取当前方法开始向上的调用堆栈。 /// /// 一个对象。可以为任何对象,没有实际意义,可以直接使用this /// 开始级别。0为当前方法。默认0 /// 是否需要完整调用堆栈 /// 方法的调用堆栈枚举 public static IEnumerable GetStackTrace(this object _,int startLevel = 0,bool full = false) { var trace = new StackTrace(); var r = new List(); for(int i = startLevel;i < trace.FrameCount;i++) { var frame = trace.GetFrame(i); if(frame == null) { break; } if(!full && frame.GetILOffset() == StackFrame.OFFSET_UNKNOWN) { break; } var method = frame.GetMethod(); if(method == null) { break; } r.Add(method); } return r; } /// /// 为对象设置测试值。 /// /// 对象的类型 /// 原始对象,可以为null /// 可选,为目标对象复制 /// 设置了测试值的对象 public static T? ToTest(this T? source,Action? targetBuilder = null) where T : class, new() { var type = typeof(T); var typeName = type.FullName; if(typeName.IsNullOrEmpty()) { throw new Exception("typeof(T).FullName is null,can not createInstance!"); } var obj = type.Assembly.CreateInstance(typeName) as T ?? throw new Exception("创建目标对象失败!"); foreach(PropertyInfo p in type.GetProperties()) { if(!p.CanWrite || !p.CanRead) { continue; } //如果属性为字符串 if(p.PropertyType == typeof(string)) { var val = source == null ? null : p.GetValue(source) as string; if(val.IsNullOrEmpty()) { p.SetValue(obj,p.Name); } else { p.SetValue(obj,val); } continue; } //其他类型属性不做处理 } targetBuilder?.Invoke(obj); return obj as T; } } /// /// 展开的属性信息 /// public class ExpandPropertyInfo { /// /// 目标对象 /// public object TargetObj { get; set; } /// /// 属性名 /// public string Name { get; set; } /// /// 属性类型 /// public Type Type { get; set; } /// /// 属性值 /// public object? Value { get; set; } /// /// 设置对象值 /// public Action SetValue { get; set; } } /// /// 为目标属性设置值时引发的异常 /// public class ObjectSetValueException:Exception { /// /// 为目标属性设置值时引发的异常 /// /// 目标对象 /// 属性 /// 目标属性值 /// 内部异常 public ObjectSetValueException(object? obj,PropertyInfo? info,object? val,Exception innExceprtion) : base("为目标属性设置值时引发的异常",innExceprtion) { this.Obj = obj; this.Property = info; this.Value = val; } /// /// 目标对象 /// public object? Obj { get; set; } /// /// 目标属性 /// public PropertyInfo? Property { get; set; } /// /// 目标属性值 /// public object? Value { get; set; } } }