diff --git a/src/BootstrapBlazor/Utils/Utility.cs b/src/BootstrapBlazor/Utils/Utility.cs index e33efed13b27cd4e0d7f02aadc12a009f6842edc..e6073bafa67949087edc55718f8e46818226332a 100644 --- a/src/BootstrapBlazor/Utils/Utility.cs +++ b/src/BootstrapBlazor/Utils/Utility.cs @@ -155,21 +155,30 @@ namespace BootstrapBlazor.Components if (instance != null) { ret = (TModel)instance; - var valType = ret?.GetType(); - if (valType != null) + if (ret != null) { + var valType = ret.GetType(); + // 20200608 tian_teng@outlook.com 支持字段和只读属性 foreach (var f in type.GetFields()) { var v = f.GetValue(item); - valType.GetField(f.Name)?.SetValue(ret, v); + var field = valType.GetField(f.Name); + if (field != null) + { + field.SetValue(ret, v); + } }; foreach (var p in type.GetProperties()) { if (p.CanWrite) { var v = p.GetValue(item); - valType.GetProperty(p.Name)?.SetValue(ret, v); + var property = valType.GetProperty(p.Name); + if (property != null) + { + property.SetValue(ret, v); + } } }; } @@ -189,26 +198,23 @@ namespace BootstrapBlazor.Components /// public static void Copy(TModel source, TModel destination) where TModel : class { - if (source != null && destination != null) + var type = source.GetType(); + var valType = destination.GetType(); + if (valType != null) { - var type = source.GetType(); - var valType = destination.GetType(); - if (valType != null) + type.GetFields().ToList().ForEach(f => { - type.GetFields().ToList().ForEach(f => - { - var v = f.GetValue(source); - valType.GetField(f.Name)?.SetValue(destination, v); - }); - type.GetProperties().ToList().ForEach(p => + var v = f.GetValue(source); + valType.GetField(f.Name)!.SetValue(destination, v); + }); + type.GetProperties().ToList().ForEach(p => + { + if (p.CanWrite) { - if (p.CanWrite) - { - var v = p.GetValue(source); - valType.GetProperty(p.Name)?.SetValue(destination, v); - } - }); - } + var v = p.GetValue(source); + valType.GetProperty(p.Name)!.SetValue(destination, v); + } + }); } } @@ -218,15 +224,7 @@ namespace BootstrapBlazor.Components /// /// /// - public static IEnumerable GenerateColumns(Func? predicate = null) - { - if (predicate == null) - { - predicate = p => true; - } - - return InternalTableColumn.GetProperties().Where(predicate); - } + public static IEnumerable GenerateColumns(Func predicate) => InternalTableColumn.GetProperties().Where(predicate); /// /// diff --git a/test/UnitTest/Emit/TypeTest.cs b/test/UnitTest/Emit/TypeTest.cs index 381c37d16fb9a6f0991cb66be9b62bc942b8812a..949b9bef7858cce82c913620b76c1481309529c0 100644 --- a/test/UnitTest/Emit/TypeTest.cs +++ b/test/UnitTest/Emit/TypeTest.cs @@ -3,11 +3,7 @@ // Website: https://www.blazor.zone or https://argozhang.github.io/ using BootstrapBlazor.Components; -using Microsoft.AspNetCore.Components; -using System; -using System.Collections.Generic; using System.Linq; -using System.Threading.Tasks; using Xunit; namespace UnitTest.Emit @@ -17,128 +13,21 @@ namespace UnitTest.Emit [Fact] public void CreateType_Ok() { - var cols = new Foo[] - { - new("Id", typeof(int)), - new("Name", typeof(string)) - }; - // 创建动态类型基类是 DynamicObject - var instanceType = EmitHelper.CreateTypeByName("Test", cols, typeof(DynamicObject)); + var instanceType = DynamicObjectHelper.CreateDynamicType(); Assert.NotNull(instanceType); + Assert.Equal(typeof(DynamicObject), instanceType.BaseType); - if (instanceType != null) - { - Assert.Equal(typeof(DynamicObject), instanceType.BaseType); - - // 创建动态类型实例 - var instance = Activator.CreateInstance(instanceType); - Assert.NotNull(instance); - - if (instance != null) - { - var properties = instance.GetType().GetProperties().Select(p => p.Name); - Assert.Contains(nameof(DynamicObject.DynamicObjectPrimaryKey), properties); - } - } - } - - private class Foo : ITableColumn - { - public Foo(string fieldName, Type propertyType) => (FieldName, PropertyType) = (fieldName, propertyType); - - public string FieldName { get; } - - public Type PropertyType { get; } - - public bool Editable { get; set; } - - public bool Readonly { get; set; } - - /// - /// 获得/设置 新建时此列只读 默认为 false - /// - public bool IsReadonlyWhenAdd { get; set; } - - /// - /// 获得/设置 编辑时此列只读 默认为 false - /// - public bool IsReadonlyWhenEdit { get; set; } - - public bool SkipValidate { get; set; } - - public string? Text { get; set; } - - public IEnumerable? Items { get; set; } - - public object? Step { get; set; } - - public int Rows { get; set; } - - public RenderFragment? EditTemplate { get; set; } - - public System.Type? ComponentType { get; set; } - - public IEnumerable? Lookup { get; set; } - - public bool Sortable { get; set; } - - public bool DefaultSort { get; set; } - - public SortOrder DefaultSortOrder { get; set; } - - public bool Filterable { get; set; } - - public bool Searchable { get; set; } - - public int? Width { get; set; } - - public bool Fixed { get; set; } - - public bool Visible { get; set; } - - public bool TextWrap { get; set; } - - public bool TextEllipsis { get; set; } - - public string? CssClass { get; set; } - - public BreakPoint ShownWithBreakPoint { get; set; } - - public RenderFragment? Template { get; set; } - - public RenderFragment? SearchTemplate { get; set; } - - public RenderFragment? FilterTemplate { get; set; } - - public RenderFragment? HeaderTemplate { get; set; } - - public IFilter? Filter { get; set; } - - public string? FormatString { get; set; } - - public Func>? Formatter { get; set; } - - public Alignment Align { get; set; } - - public bool ShowTips { get; set; } - - public int Order { get; set; } - - public Action? OnCellRender { get; set; } - - public IEnumerable>? ComponentParameters { get; set; } - - public string? PlaceHolder { get; set; } - - /// - /// 获得/设置 自定义验证集合 - /// - public List? ValidateRules { get; set; } + // 创建动态类型实例 + var instance = DynamicObjectHelper.CreateDynamicObject(); + Assert.NotNull(instance); - public string GetDisplayName() => Text ?? FieldName; + var properties = instance.GetType().GetProperties().Select(p => p.Name); + Assert.Contains(nameof(DynamicObject.DynamicObjectPrimaryKey), properties); - public string GetFieldName() => FieldName; + // Utility + var v = Utility.GetPropertyValue(instance, "Name"); + Assert.Null(v); } } } diff --git a/test/UnitTest/Misc/DynamicObjectHelper.cs b/test/UnitTest/Misc/DynamicObjectHelper.cs new file mode 100644 index 0000000000000000000000000000000000000000..0e032bcbbac55c075dcf1d6423275d762f3d00a7 --- /dev/null +++ b/test/UnitTest/Misc/DynamicObjectHelper.cs @@ -0,0 +1,33 @@ +// Copyright (c) Argo Zhang (argo@163.com). All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +// Website: https://www.blazor.zone or https://argozhang.github.io/ + +using BootstrapBlazor.Components; +using System; + +namespace UnitTest +{ + internal static class DynamicObjectHelper + { + public static Type CreateDynamicType(string typeName = "Test") + { + var cols = new MockTableColumn[] + { + new("Id", typeof(int)), + new("Name", typeof(string)) + }; + + // 创建动态类型基类是 DynamicObject + var instanceType = EmitHelper.CreateTypeByName(typeName, cols, typeof(DynamicObject)); + return instanceType!; + } + + public static object CreateDynamicObject(string typeName = "Test") + { + var instanceType = CreateDynamicType(typeName); + + // 创建动态类型实例 + return Activator.CreateInstance(instanceType)!; + } + } +} diff --git a/test/UnitTest/Misc/MockTableColumn.cs b/test/UnitTest/Misc/MockTableColumn.cs new file mode 100644 index 0000000000000000000000000000000000000000..bb999b3b72a330d75fab895396ea9f618e738b23 --- /dev/null +++ b/test/UnitTest/Misc/MockTableColumn.cs @@ -0,0 +1,112 @@ +// Copyright (c) Argo Zhang (argo@163.com). All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +// Website: https://www.blazor.zone or https://argozhang.github.io/ + +using BootstrapBlazor.Components; +using Microsoft.AspNetCore.Components; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace UnitTest +{ + internal class MockTableColumn : ITableColumn + { + public MockTableColumn(string fieldName, Type propertyType) => (FieldName, PropertyType) = (fieldName, propertyType); + + public string FieldName { get; } + + public Type PropertyType { get; } + + public bool Editable { get; set; } + + public bool Readonly { get; set; } + + /// + /// 获得/设置 新建时此列只读 默认为 false + /// + public bool IsReadonlyWhenAdd { get; set; } + + /// + /// 获得/设置 编辑时此列只读 默认为 false + /// + public bool IsReadonlyWhenEdit { get; set; } + + public bool SkipValidate { get; set; } + + public string? Text { get; set; } + + public IEnumerable? Items { get; set; } + + public object? Step { get; set; } + + public int Rows { get; set; } + + public RenderFragment? EditTemplate { get; set; } + + public System.Type? ComponentType { get; set; } + + public IEnumerable? Lookup { get; set; } + + public bool Sortable { get; set; } + + public bool DefaultSort { get; set; } + + public SortOrder DefaultSortOrder { get; set; } + + public bool Filterable { get; set; } + + public bool Searchable { get; set; } + + public int? Width { get; set; } + + public bool Fixed { get; set; } + + public bool Visible { get; set; } + + public bool TextWrap { get; set; } + + public bool TextEllipsis { get; set; } + + public string? CssClass { get; set; } + + public BreakPoint ShownWithBreakPoint { get; set; } + + public RenderFragment? Template { get; set; } + + public RenderFragment? SearchTemplate { get; set; } + + public RenderFragment? FilterTemplate { get; set; } + + public RenderFragment? HeaderTemplate { get; set; } + + public IFilter? Filter { get; set; } + + public string? FormatString { get; set; } + + public Func>? Formatter { get; set; } + + public Alignment Align { get; set; } + + public bool ShowTips { get; set; } + + public int Order { get; set; } + + public Action? OnCellRender { get; set; } + + public IEnumerable>? ComponentParameters { get; set; } + + public string? PlaceHolder { get; set; } + + /// + /// 获得/设置 自定义验证集合 + /// + public List? ValidateRules { get; set; } + + public string GetDisplayName() => Text ?? FieldName; + + public string GetFieldName() => FieldName; + } +} diff --git a/test/UnitTest/UnitTest.csproj b/test/UnitTest/UnitTest.csproj index 93cd6c0b1bf23a3f7132e7d7fe35278ddbb82376..5797723a4814eb9b9792ca899680f694adb8bb1f 100644 --- a/test/UnitTest/UnitTest.csproj +++ b/test/UnitTest/UnitTest.csproj @@ -25,7 +25,7 @@ - + diff --git a/test/UnitTest/Utils/UtilityTest.cs b/test/UnitTest/Utils/UtilityTest.cs new file mode 100644 index 0000000000000000000000000000000000000000..3bedc47aeca4708624f825bfdac52366e2bbd6b3 --- /dev/null +++ b/test/UnitTest/Utils/UtilityTest.cs @@ -0,0 +1,120 @@ +// Copyright (c) Argo Zhang (argo@163.com). All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +// Website: https://www.blazor.zone or https://argozhang.github.io/ + +using BootstrapBlazor.Components; +using BootstrapBlazor.Shared; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Localization; +using System; +using System.Linq; +using UnitTest.Core; +using Xunit; + +namespace UnitTest.Utils +{ + public class UtilityTest : BootstrapBlazorTestBase + { + public Foo Model { get; set; } + + public UtilityTest() + { + Model = new Foo() + { + Name = "Test" + }; + } + + [Fact] + public void GetPropertyValue_Ok() + { + var v = Utility.GetPropertyValue(Model, nameof(Foo.Name)); + Assert.Equal("Test", v); + } + + [Fact] + public void GetSortFunc_Ok() + { + var localizer = Context.Services.GetRequiredService>(); + var foos = Foo.GenerateFoo(localizer, 2); + var invoker = Utility.GetSortFunc(); + var data = invoker.Invoke(foos, nameof(Foo.Count), SortOrder.Asc).ToList(); + Assert.True(data[0].Count < data[1].Count); + + data = invoker.Invoke(foos, nameof(Foo.Count), SortOrder.Desc).ToList(); + Assert.True(data[0].Count > data[1].Count); + } + + [Fact] + public void GetPlaceHolder_Ok() + { + var ph = Utility.GetPlaceHolder(typeof(Foo), "Name"); + Assert.Equal("不可为空", ph); + + // 动态类型 + ph = Utility.GetPlaceHolder(DynamicObjectHelper.CreateDynamicType(), "Name"); + Assert.Null(ph); + } + + [Fact] + public void Reset_Ok() + { + var foo = new Foo() + { + Name = "张三" + }; + Utility.Reset(foo); + Assert.Null(foo.Name); + } + + [Fact] + public void Clone_Ok() + { + var dummy = new Dummy() + { + Name = "Test" + }; + var d = Utility.Clone(dummy); + Assert.NotEqual(d, dummy); + Assert.Equal(d.Name, dummy.Name); + + // ICloneable + var o = new MockClone() + { + Name = "Test" + }; + var mo = Utility.Clone(o); + Assert.NotEqual(o, mo); + Assert.Equal(o.Name, mo.Name); + } + + private class Dummy + { + public string? Name { get; set; } + + public string? Id; + } + + private class MockClone : ICloneable + { + public string? Name { get; set; } + + public object Clone() + { + return new MockClone() + { + Name = Name + }; + } + } + + [Fact] + public void Copy_Ok() + { + var d1 = new Dummy() { Name = "Test" }; + var d2 = new Dummy(); + Utility.Copy(d1, d2); + Assert.Equal("Test", d2.Name); + } + } +}