|
4 | 4 |
|
5 | 5 | using System;
|
6 | 6 | using System.Collections.Generic;
|
| 7 | +using System.ComponentModel.DataAnnotations; |
7 | 8 | using System.Linq;
|
8 | 9 | using System.Reflection;
|
| 10 | +using System.Text.Json.Serialization; |
9 | 11 | using System.Threading;
|
10 | 12 | using System.Threading.Tasks;
|
| 13 | +using System.Xml.Serialization; |
11 | 14 | using CommunityToolkit.Mvvm.ComponentModel;
|
12 | 15 | using CommunityToolkit.Mvvm.Input;
|
13 | 16 | using Microsoft.VisualStudio.TestTools.UnitTesting;
|
@@ -565,6 +568,97 @@ public void Test_RelayCommandAttribute_CanExecuteWithNullabilityAnnotations()
|
565 | 568 | Assert.IsTrue(model.DoSomething3Command.CanExecute((0, "Hello")));
|
566 | 569 | }
|
567 | 570 |
|
| 571 | + [TestMethod] |
| 572 | + public void Test_RelayCommandAttribute_WithExplicitAttributesForFieldAndProperty() |
| 573 | + { |
| 574 | + FieldInfo fooField = typeof(MyViewModelWithExplicitFieldAndPropertyAttributes).GetField("fooCommand", BindingFlags.Instance | BindingFlags.NonPublic)!; |
| 575 | + |
| 576 | + Assert.IsNotNull(fooField.GetCustomAttribute<RequiredAttribute>()); |
| 577 | + Assert.IsNotNull(fooField.GetCustomAttribute<MinLengthAttribute>()); |
| 578 | + Assert.AreEqual(fooField.GetCustomAttribute<MinLengthAttribute>()!.Length, 1); |
| 579 | + Assert.IsNotNull(fooField.GetCustomAttribute<MaxLengthAttribute>()); |
| 580 | + Assert.AreEqual(fooField.GetCustomAttribute<MaxLengthAttribute>()!.Length, 100); |
| 581 | + |
| 582 | + PropertyInfo fooProperty = typeof(MyViewModelWithExplicitFieldAndPropertyAttributes).GetProperty("FooCommand")!; |
| 583 | + |
| 584 | + Assert.IsNotNull(fooProperty.GetCustomAttribute<RequiredAttribute>()); |
| 585 | + Assert.IsNotNull(fooProperty.GetCustomAttribute<MinLengthAttribute>()); |
| 586 | + Assert.AreEqual(fooProperty.GetCustomAttribute<MinLengthAttribute>()!.Length, 1); |
| 587 | + Assert.IsNotNull(fooProperty.GetCustomAttribute<MaxLengthAttribute>()); |
| 588 | + Assert.AreEqual(fooProperty.GetCustomAttribute<MaxLengthAttribute>()!.Length, 100); |
| 589 | + |
| 590 | + PropertyInfo barProperty = typeof(MyViewModelWithExplicitFieldAndPropertyAttributes).GetProperty("BarCommand")!; |
| 591 | + |
| 592 | + Assert.IsNotNull(barProperty.GetCustomAttribute<JsonPropertyNameAttribute>()); |
| 593 | + Assert.AreEqual(barProperty.GetCustomAttribute<JsonPropertyNameAttribute>()!.Name, "bar"); |
| 594 | + Assert.IsNotNull(barProperty.GetCustomAttribute<XmlIgnoreAttribute>()); |
| 595 | + |
| 596 | + PropertyInfo bazProperty = typeof(MyViewModelWithExplicitFieldAndPropertyAttributes).GetProperty("BazCommand")!; |
| 597 | + |
| 598 | + Assert.IsNotNull(bazProperty.GetCustomAttribute<Test_ObservablePropertyAttribute.TestAttribute>()); |
| 599 | + |
| 600 | + static void ValidateTestAttribute(TestValidationAttribute testAttribute) |
| 601 | + { |
| 602 | + Assert.IsNotNull(testAttribute); |
| 603 | + Assert.IsNull(testAttribute.O); |
| 604 | + Assert.AreEqual(testAttribute.T, typeof(MyViewModelWithExplicitFieldAndPropertyAttributes)); |
| 605 | + Assert.AreEqual(testAttribute.Flag, true); |
| 606 | + Assert.AreEqual(testAttribute.D, 6.28); |
| 607 | + CollectionAssert.AreEqual(testAttribute.Names, new[] { "Bob", "Ross" }); |
| 608 | + |
| 609 | + object[]? nestedArray = (object[]?)testAttribute.NestedArray; |
| 610 | + |
| 611 | + Assert.IsNotNull(nestedArray); |
| 612 | + Assert.AreEqual(nestedArray!.Length, 3); |
| 613 | + Assert.AreEqual(nestedArray[0], 1); |
| 614 | + Assert.AreEqual(nestedArray[1], "Hello"); |
| 615 | + Assert.IsTrue(nestedArray[2] is int[]); |
| 616 | + CollectionAssert.AreEqual((int[])nestedArray[2], new[] { 2, 3, 4 }); |
| 617 | + |
| 618 | + Assert.AreEqual(testAttribute.Animal, Test_ObservablePropertyAttribute.Animal.Llama); |
| 619 | + } |
| 620 | + |
| 621 | + FieldInfo fooBarField = typeof(MyViewModelWithExplicitFieldAndPropertyAttributes).GetField("fooBarCommand", BindingFlags.Instance | BindingFlags.NonPublic)!; |
| 622 | + |
| 623 | + ValidateTestAttribute(fooBarField.GetCustomAttribute<TestValidationAttribute>()!); |
| 624 | + |
| 625 | + PropertyInfo fooBarProperty = typeof(MyViewModelWithExplicitFieldAndPropertyAttributes).GetProperty("FooBarCommand")!; |
| 626 | + |
| 627 | + ValidateTestAttribute(fooBarProperty.GetCustomAttribute<TestValidationAttribute>()!); |
| 628 | + |
| 629 | + FieldInfo barBazField = typeof(MyViewModelWithExplicitFieldAndPropertyAttributes).GetField("barBazCommand", BindingFlags.Instance | BindingFlags.NonPublic)!; |
| 630 | + |
| 631 | + Assert.IsNotNull(barBazField.GetCustomAttribute<Test_ObservablePropertyAttribute.TestAttribute>()); |
| 632 | + |
| 633 | + PropertyInfo barBazCommand = typeof(MyViewModelWithExplicitFieldAndPropertyAttributes).GetProperty("BarBazCommand")!; |
| 634 | + |
| 635 | + Assert.IsNotNull(barBazCommand.GetCustomAttribute<Test_ObservablePropertyAttribute.TestAttribute>()); |
| 636 | + |
| 637 | + Test_ObservablePropertyAttribute.PropertyInfoAttribute testAttribute2 = barBazCommand.GetCustomAttribute<Test_ObservablePropertyAttribute.PropertyInfoAttribute>()!; |
| 638 | + |
| 639 | + Assert.IsNotNull(testAttribute2); |
| 640 | + Assert.IsNull(testAttribute2.O); |
| 641 | + Assert.AreEqual(testAttribute2.T, typeof(MyViewModelWithExplicitFieldAndPropertyAttributes)); |
| 642 | + Assert.AreEqual(testAttribute2.Flag, true); |
| 643 | + Assert.AreEqual(testAttribute2.D, 6.28); |
| 644 | + Assert.IsNotNull(testAttribute2.Objects); |
| 645 | + Assert.IsTrue(testAttribute2.Objects is object[]); |
| 646 | + Assert.AreEqual(((object[])testAttribute2.Objects).Length, 1); |
| 647 | + Assert.AreEqual(((object[])testAttribute2.Objects)[0], "Test"); |
| 648 | + CollectionAssert.AreEqual(testAttribute2.Names, new[] { "Bob", "Ross" }); |
| 649 | + |
| 650 | + object[]? nestedArray2 = (object[]?)testAttribute2.NestedArray; |
| 651 | + |
| 652 | + Assert.IsNotNull(nestedArray2); |
| 653 | + Assert.AreEqual(nestedArray2!.Length, 4); |
| 654 | + Assert.AreEqual(nestedArray2[0], 1); |
| 655 | + Assert.AreEqual(nestedArray2[1], "Hello"); |
| 656 | + Assert.AreEqual(nestedArray2[2], 42); |
| 657 | + Assert.IsNull(nestedArray2[3]); |
| 658 | + |
| 659 | + Assert.AreEqual(testAttribute2.Animal, (Test_ObservablePropertyAttribute.Animal)67); |
| 660 | + } |
| 661 | + |
568 | 662 | #region Region
|
569 | 663 | public class Region
|
570 | 664 | {
|
@@ -1038,4 +1132,74 @@ private void DoSomething3((int A, string? B) parameter)
|
1038 | 1132 | {
|
1039 | 1133 | }
|
1040 | 1134 | }
|
| 1135 | + |
| 1136 | + public partial class MyViewModelWithExplicitFieldAndPropertyAttributes |
| 1137 | + { |
| 1138 | + [RelayCommand] |
| 1139 | + [field: Required] |
| 1140 | + [field: MinLength(1)] |
| 1141 | + [field: MaxLength(100)] |
| 1142 | + [property: Required] |
| 1143 | + [property: MinLength(1)] |
| 1144 | + [property: MaxLength(100)] |
| 1145 | + private void Foo() |
| 1146 | + { |
| 1147 | + } |
| 1148 | + |
| 1149 | + [RelayCommand] |
| 1150 | + [property: JsonPropertyName("bar")] |
| 1151 | + [property: XmlIgnore] |
| 1152 | + private void Bar() |
| 1153 | + { |
| 1154 | + } |
| 1155 | + |
| 1156 | + [RelayCommand] |
| 1157 | + [property: Test_ObservablePropertyAttribute.Test] |
| 1158 | + private async Task BazAsync() |
| 1159 | + { |
| 1160 | + await Task.Yield(); |
| 1161 | + } |
| 1162 | + |
| 1163 | + [RelayCommand] |
| 1164 | + [field: TestValidation(null, typeof(MyViewModelWithExplicitFieldAndPropertyAttributes), true, 6.28, new[] { "Bob", "Ross" }, NestedArray = new object[] { 1, "Hello", new int[] { 2, 3, 4 } }, Animal = Test_ObservablePropertyAttribute.Animal.Llama)] |
| 1165 | + [property: TestValidation(null, typeof(MyViewModelWithExplicitFieldAndPropertyAttributes), true, 6.28, new[] { "Bob", "Ross" }, NestedArray = new object[] { 1, "Hello", new int[] { 2, 3, 4 } }, Animal = Test_ObservablePropertyAttribute.Animal.Llama)] |
| 1166 | + private void FooBar() |
| 1167 | + { |
| 1168 | + } |
| 1169 | + |
| 1170 | + [RelayCommand] |
| 1171 | + [field: Test_ObservablePropertyAttribute.Test] |
| 1172 | + [property: Test_ObservablePropertyAttribute.Test] |
| 1173 | + [property: Test_ObservablePropertyAttribute.PropertyInfo(null, typeof(MyViewModelWithExplicitFieldAndPropertyAttributes), true, 6.28, new[] { "Bob", "Ross" }, new object[] { "Test" }, NestedArray = new object[] { 1, "Hello", 42, null }, Animal = (Test_ObservablePropertyAttribute.Animal)67)] |
| 1174 | + private void BarBaz() |
| 1175 | + { |
| 1176 | + } |
| 1177 | + } |
| 1178 | + |
| 1179 | + // Copy of the attribute from Test_ObservablePropertyAttribute, to test nested types |
| 1180 | + private sealed class TestValidationAttribute : ValidationAttribute |
| 1181 | + { |
| 1182 | + public TestValidationAttribute(object? o, Type t, bool flag, double d, string[] names) |
| 1183 | + { |
| 1184 | + O = o; |
| 1185 | + T = t; |
| 1186 | + Flag = flag; |
| 1187 | + D = d; |
| 1188 | + Names = names; |
| 1189 | + } |
| 1190 | + |
| 1191 | + public object? O { get; } |
| 1192 | + |
| 1193 | + public Type T { get; } |
| 1194 | + |
| 1195 | + public bool Flag { get; } |
| 1196 | + |
| 1197 | + public double D { get; } |
| 1198 | + |
| 1199 | + public string[] Names { get; } |
| 1200 | + |
| 1201 | + public object? NestedArray { get; set; } |
| 1202 | + |
| 1203 | + public Test_ObservablePropertyAttribute.Animal Animal { get; set; } |
| 1204 | + } |
1041 | 1205 | }
|
0 commit comments