From 766ef83f4b0f9e6f3f4367083f241e49f661b09e Mon Sep 17 00:00:00 2001 From: falcon <9504402@qq.com> Date: Thu, 5 Jan 2023 10:02:26 +0800 Subject: [PATCH] =?UTF-8?q?=E4=B8=BA=E5=AF=B9=E8=B1=A1=E5=A2=9E=E5=8A=A0Ex?= =?UTF-8?q?pandProperties=E6=96=B9=E6=B3=95=EF=BC=8C=E8=AF=A5=E6=96=B9?= =?UTF-8?q?=E6=B3=95=E6=89=A9=E5=B1=95=E5=AF=B9=E8=B1=A1=E7=9A=84=E5=B1=9E?= =?UTF-8?q?=E6=80=A7=E6=88=90=E4=B8=BAExpandPropertyInfo=E6=9E=9A=E4=B8=BE?= =?UTF-8?q?=E8=AE=B0=E5=BD=95=E5=B1=9E=E6=80=A7=E7=9A=84=E5=90=8D=E7=A7=B0?= =?UTF-8?q?=E3=80=81=E7=B1=BB=E5=9E=8B=E5=92=8C=E5=80=BC=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .editorconfig | 4 ++ Falcon.SugarApi.Test/ObjectExtendTest.cs | 66 +++++++++++++++++++---- Falcon.SugarApi.sln | 1 + Falcon.SugarApi/Falcon.SugarApi.csproj | 4 ++ Falcon.SugarApi/ObjectExtend.cs | 67 ++++++++++++++++++------ 5 files changed, 117 insertions(+), 25 deletions(-) create mode 100644 .editorconfig diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..65054c9 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,4 @@ +[*.cs] + +# CS8618: 在退出构造函数时,不可为 null 的字段必须包含非 null 值。请考虑声明为可以为 null。 +dotnet_diagnostic.CS8618.severity = none diff --git a/Falcon.SugarApi.Test/ObjectExtendTest.cs b/Falcon.SugarApi.Test/ObjectExtendTest.cs index 017133a..542ed78 100644 --- a/Falcon.SugarApi.Test/ObjectExtendTest.cs +++ b/Falcon.SugarApi.Test/ObjectExtendTest.cs @@ -15,22 +15,22 @@ namespace Falcon.SugarApi.Test public void CloneToTest() { var s = new SourceClass { }; var t = new TargetClass { }; - t.ica.ItemA = "itemb"; + t.ica.ItemA="itemb"; - Assert.IsTrue(t.ica.ItemA == "itemb"); + Assert.IsTrue(t.ica.ItemA=="itemb"); var r = s.CloneTo(t); Assert.IsNotNull(s); Assert.IsNotNull(r); Assert.IsNotNull(t); - Assert.IsTrue(s.ia == t.ia, $"a.id:{s.ia},t.ia:{t.ia}"); - Assert.IsTrue(t.ia == 1); - Assert.IsTrue(s.sa == t.sa); - Assert.IsTrue(s.sc == "sc"); - Assert.IsTrue(t.sd == "sd"); - Assert.IsTrue(s.ica.ItemA == "itema"); - Assert.IsTrue(t.ica.ItemA == "itema"); + Assert.IsTrue(s.ia==t.ia,$"a.id:{s.ia},t.ia:{t.ia}"); + Assert.IsTrue(t.ia==1); + Assert.IsTrue(s.sa==t.sa); + Assert.IsTrue(s.sc=="sc"); + Assert.IsTrue(t.sd=="sd"); + Assert.IsTrue(s.ica.ItemA=="itema"); + Assert.IsTrue(t.ica.ItemA=="itema"); Assert.IsTrue(t.ica.Equals(s.ica)); } @@ -48,9 +48,55 @@ namespace Falcon.SugarApi.Test public void ThrowNullExceptionWhenNullTest() { var obj = new object(); obj.ThrowNullExceptionWhenNull(); - obj = null; + obj=null; Assert.ThrowsException(() => obj.ThrowNullExceptionWhenNull()); } + + /// + /// 测试对象属性扩展 + /// + [TestMethod] + public void ExtendPropertyTest() { + var obj = new ExtendPropertyTestClass { + Id=1,Name="Falcon",Sex=null,Count="count" + }; + var ep = obj.ExpandProperties(); + Assert.IsNotNull(ep); + Assert.IsTrue(ep.Count()==4); + Assert.IsTrue(ep.Select(m => m.Name).Distinct().Count()==4); + foreach(var p in ep) { + if(p.Name=="Id") { + Assert.IsTrue(p.Type==typeof(int)); + Assert.IsTrue(p.Value.Equals(obj.Id)); + continue; + } + if(p.Name=="Name") { + Assert.IsTrue(p.Type==typeof(string)); + Assert.IsTrue(p.Value.Equals(obj.Name)); + continue; + } + if(p.Name=="Sex") { + Assert.IsTrue(p.Type==typeof(string)); + Assert.IsTrue(p.Value==null); + continue; + } + if(p.Name=="Count") { + Assert.IsTrue(p.Type==typeof(string)); + Assert.IsTrue(p.Value=="count"); + continue; + } + } + } + } + /// + /// 扩展属性测试类 + /// + public class ExtendPropertyTestClass + { + public int Id { get; set; } + public string Name { get; set; } + public string? Sex { get; set; } + public string Count { private get; set; } } public class SourceClass diff --git a/Falcon.SugarApi.sln b/Falcon.SugarApi.sln index 2a329d9..cb4c5fc 100644 --- a/Falcon.SugarApi.sln +++ b/Falcon.SugarApi.sln @@ -9,6 +9,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Falcon.SugarApi.Test", "Fal EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{08995833-E4C9-4222-9084-36BA32B9490E}" ProjectSection(SolutionItems) = preProject + .editorconfig = .editorconfig README.md = README.md EndProjectSection EndProject diff --git a/Falcon.SugarApi/Falcon.SugarApi.csproj b/Falcon.SugarApi/Falcon.SugarApi.csproj index 76bb987..ab3eb29 100644 --- a/Falcon.SugarApi/Falcon.SugarApi.csproj +++ b/Falcon.SugarApi/Falcon.SugarApi.csproj @@ -10,6 +10,10 @@ 1.0.0 + + + + diff --git a/Falcon.SugarApi/ObjectExtend.cs b/Falcon.SugarApi/ObjectExtend.cs index 506c65c..95ddbca 100644 --- a/Falcon.SugarApi/ObjectExtend.cs +++ b/Falcon.SugarApi/ObjectExtend.cs @@ -1,7 +1,9 @@ using System; +using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics.CodeAnalysis; using System.Linq; +using System.Reflection; namespace Falcon.SugarApi { @@ -16,15 +18,15 @@ namespace Falcon.SugarApi /// 原对象类型 /// 原对象 /// 目标对象 - public static TSource CloneTo(this TSource source, [NotNull] object target) where TSource : class { - _ = source ?? throw new ArgumentNullException(nameof(source)); - _ = target ?? throw new ArgumentNullException(nameof(target)); + public static TSource CloneTo(this TSource source,[NotNull] object target) 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 s.Name equals t.Name - select new { s, t }; - foreach (var item in all) { - //item.t.SetValue(target, Convert.ChangeType(item.s.GetValue(source), item.t.PropertyType)); - item.t.SetValue(target, item.s.GetValue(source).ChangeType(item.t.PropertyType)); + select new { s,t }; + foreach(var item in all) { + //item.t.SetValue(target, Convert.ChangeType(item.s.GetValue(source), item.t.Type)); + item.t.SetValue(target,item.s.GetValue(source).ChangeType(item.t.PropertyType)); } return source; } @@ -36,7 +38,7 @@ namespace Falcon.SugarApi /// 目标对象 /// 原对象 /// 目标对象 - public static Ttarget CloneFrom(this Ttarget target, object source) where Ttarget : class { + public static Ttarget CloneFrom(this Ttarget target,object source) where Ttarget : class { source.CloneTo(target); return target; } @@ -47,18 +49,18 @@ namespace Falcon.SugarApi /// 原对象 /// 目标类型 /// 转换后的类型 - public static object? ChangeType(this object? source, Type targetType) { - if (targetType == null) { + public static object? ChangeType(this object? source,Type targetType) { + if(targetType==null) { throw new ArgumentNullException("targetType"); } - if (source == null) { + if(source==null) { return null; } - if (targetType.IsGenericType && targetType.GetGenericTypeDefinition().Equals(typeof(Nullable<>))) { + if(targetType.IsGenericType&&targetType.GetGenericTypeDefinition().Equals(typeof(Nullable<>))) { NullableConverter nullableConverter = new NullableConverter(targetType); - targetType = nullableConverter.UnderlyingType; + targetType=nullableConverter.UnderlyingType; } - return Convert.ChangeType(source, targetType); + return Convert.ChangeType(source,targetType); } /// @@ -68,10 +70,45 @@ namespace Falcon.SugarApi /// 对象本身 /// 对象为null public static object? ThrowNullExceptionWhenNull(this object? obj) { - if (obj == null) { + 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 { + Name=p.Name, + Type=p.PropertyType, + Value=p.CanRead ? p.GetValue(obj) : null, + }; + } + } } + + /// + /// 展开的属性信息 + /// + public class ExpandPropertyInfo + { + /// + /// 属性名 + /// + public string Name { get; set; } + /// + /// 属性类型 + /// + public Type Type { get; set; } + /// + /// 属性值 + /// + public object? Value { get; set; } + } + }