From 97da7533d18119bfab2e9f26c043994c4bdb24ec Mon Sep 17 00:00:00 2001 From: Vinicius Dutra Date: Mon, 30 Sep 2019 10:08:12 -0300 Subject: [PATCH 1/4] included tests for each function changed + considered enum name or value during conversion --- .../Mvvm/AutoInitializeViewModelFixture.cs | 70 +++++++++++++++++++ Source/Prism/Common/ParametersExtensions.cs | 21 ++++-- 2 files changed, 85 insertions(+), 6 deletions(-) create mode 100644 Source/Prism.Tests/Mvvm/AutoInitializeViewModelFixture.cs diff --git a/Source/Prism.Tests/Mvvm/AutoInitializeViewModelFixture.cs b/Source/Prism.Tests/Mvvm/AutoInitializeViewModelFixture.cs new file mode 100644 index 000000000..a3c28c178 --- /dev/null +++ b/Source/Prism.Tests/Mvvm/AutoInitializeViewModelFixture.cs @@ -0,0 +1,70 @@ +using System.Collections.Generic; +using System.Linq; +using Prism.Common; +using Xunit; + +namespace Prism.Tests.Mvvm +{ + internal class MockParameters : ParametersBase + { + public MockParameters() : base() { } + public MockParameters(string query) : base(query) { } + } + + internal enum MockEnum + { + None = 0, + Foo = 1, + Bar = 2, + Fizz = 3 + } + + public class AutoInitializeViewModelFixture + { + [Fact] + public void TryGetValueOfT() + { + var parameters = new MockParameters("mock=Foo&mock2=1"); + bool success = false; + MockEnum value = default; + MockEnum value1 = default; + + var ex = Record.Exception(() => success = parameters.TryGetValue("mock", out value)); + var ex2 = Record.Exception(() => success = parameters.TryGetValue("mock2", out value1)); + Assert.Null(ex); + Assert.True(success); + Assert.Equal(MockEnum.Foo, value); + Assert.Equal(value, value1); + } + + [Fact] + public void GetValuesOfT() + { + var parameters = new MockParameters("mock=Foo&mock=2&mock=Fizz"); + bool success = false; + IEnumerable values = default; + + var ex = Record.Exception(() => values = parameters.GetValues("mock")); + Assert.Null(ex); + Assert.Equal(3, values.Count()); + Assert.Equal(MockEnum.Foo, values.ElementAt(0)); + Assert.Equal(MockEnum.Bar, values.ElementAt(1)); + Assert.Equal(MockEnum.Fizz, values.ElementAt(2)); + } + + + [Fact] + public void GetValue() + { + var parameters = new MockParameters("mock=Foo&mock1=2&mock2=Fizz"); + MockEnum value = default; + MockEnum value1 = default; + + var ex = Record.Exception(() => value = parameters.GetValue("mock")); + var ex2 = Record.Exception(() => value1 = parameters.GetValue("mock1")); + Assert.Null(ex); + Assert.Equal(MockEnum.Foo, value); + Assert.Equal(MockEnum.Bar, value1); + } + } +} diff --git a/Source/Prism/Common/ParametersExtensions.cs b/Source/Prism/Common/ParametersExtensions.cs index 5222fffcc..52786f7b0 100644 --- a/Source/Prism/Common/ParametersExtensions.cs +++ b/Source/Prism/Common/ParametersExtensions.cs @@ -25,6 +25,8 @@ public static object GetValue(this IEnumerable> par return kvp.Value; else if (type.IsAssignableFrom(kvp.Value.GetType())) return kvp.Value; + else if (type.IsEnum && (Enum.IsDefined(type, kvp.Value.ToString()) || int.TryParse(kvp.Value.ToString(), out var enumValue) && Enum.IsDefined(type, enumValue))) + return Enum.Parse(type, kvp.Value.ToString()); else return Convert.ChangeType(kvp.Value, type); } @@ -36,18 +38,22 @@ public static object GetValue(this IEnumerable> par [EditorBrowsable(EditorBrowsableState.Never)] public static bool TryGetValue(this IEnumerable> parameters, string key, out T value) { + var type = typeof(T); + foreach (var kvp in parameters) { if (string.Compare(kvp.Key, key, StringComparison.Ordinal) == 0) { if (kvp.Value == null) value = default; - else if (kvp.Value.GetType() == typeof(T)) + else if (kvp.Value.GetType() == type) value = (T)kvp.Value; - else if (typeof(T).IsAssignableFrom(kvp.Value.GetType())) + else if (type.IsAssignableFrom(kvp.Value.GetType())) value = (T)kvp.Value; + else if (type.IsEnum && (Enum.IsDefined(type, kvp.Value.ToString()) || int.TryParse(kvp.Value.ToString(), out var enumValue) && Enum.IsDefined(type, enumValue))) + value = (T)Enum.Parse(type, kvp.Value.ToString()); else - value = (T)Convert.ChangeType(kvp.Value, typeof(T)); + value = (T)Convert.ChangeType(kvp.Value, type); return true; } @@ -61,6 +67,7 @@ public static bool TryGetValue(this IEnumerable> public static IEnumerable GetValues(this IEnumerable> parameters, string key) { List values = new List(); + var type = typeof(T); foreach (var kvp in parameters) { @@ -68,12 +75,14 @@ public static IEnumerable GetValues(this IEnumerable Date: Thu, 29 Aug 2019 16:05:49 -0300 Subject: [PATCH 2/4] Allow bind Enum values in IAutoInitialize ViewModels Currently if anyone try pass through a enum value as raw type(value or name) within INavigationParameters get an error of conversion, to solve this problem was included the conditions above. --- Source/Prism/Common/ParametersExtensions.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Source/Prism/Common/ParametersExtensions.cs b/Source/Prism/Common/ParametersExtensions.cs index 52786f7b0..cf64042c6 100644 --- a/Source/Prism/Common/ParametersExtensions.cs +++ b/Source/Prism/Common/ParametersExtensions.cs @@ -25,8 +25,8 @@ public static object GetValue(this IEnumerable> par return kvp.Value; else if (type.IsAssignableFrom(kvp.Value.GetType())) return kvp.Value; - else if (type.IsEnum && (Enum.IsDefined(type, kvp.Value.ToString()) || int.TryParse(kvp.Value.ToString(), out var enumValue) && Enum.IsDefined(type, enumValue))) - return Enum.Parse(type, kvp.Value.ToString()); + else if (type.IsEnum && Enum.IsDefined(type, kvp.Value)) + return Enum.Parse(type, kvp.Value.ToString(), true); else return Convert.ChangeType(kvp.Value, type); } @@ -50,8 +50,8 @@ public static bool TryGetValue(this IEnumerable> value = (T)kvp.Value; else if (type.IsAssignableFrom(kvp.Value.GetType())) value = (T)kvp.Value; - else if (type.IsEnum && (Enum.IsDefined(type, kvp.Value.ToString()) || int.TryParse(kvp.Value.ToString(), out var enumValue) && Enum.IsDefined(type, enumValue))) - value = (T)Enum.Parse(type, kvp.Value.ToString()); + else if (type.IsEnum && Enum.TryParse(kvp.Value, true, out var enumValue)) + value = enumValue; else value = (T)Convert.ChangeType(kvp.Value, type); @@ -79,8 +79,8 @@ public static IEnumerable GetValues(this IEnumerable(kvp.Value, true, out var enumValue)) + value.Add(enumValue); else values.Add((T)Convert.ChangeType(kvp.Value, type)); } From 085ff46f1a47cf212590be1978ab1e9a8ee5fad2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vinicius=20C=C3=A2ndido?= Date: Sun, 1 Sep 2019 20:26:20 -0300 Subject: [PATCH 3/4] Update ParametersExtensions.cs --- Source/Prism/Common/ParametersExtensions.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Source/Prism/Common/ParametersExtensions.cs b/Source/Prism/Common/ParametersExtensions.cs index cf64042c6..9bb823ad7 100644 --- a/Source/Prism/Common/ParametersExtensions.cs +++ b/Source/Prism/Common/ParametersExtensions.cs @@ -26,7 +26,7 @@ public static object GetValue(this IEnumerable> par else if (type.IsAssignableFrom(kvp.Value.GetType())) return kvp.Value; else if (type.IsEnum && Enum.IsDefined(type, kvp.Value)) - return Enum.Parse(type, kvp.Value.ToString(), true); + return Enum.Parse(type, kvp.Value.ToString()); else return Convert.ChangeType(kvp.Value, type); } @@ -50,8 +50,8 @@ public static bool TryGetValue(this IEnumerable> value = (T)kvp.Value; else if (type.IsAssignableFrom(kvp.Value.GetType())) value = (T)kvp.Value; - else if (type.IsEnum && Enum.TryParse(kvp.Value, true, out var enumValue)) - value = enumValue; + else if (type.IsEnum && Enum.IsDefined(type, kvp.Value)) + value = (T)Enum.Parse(type, kvp.Value.ToString()); else value = (T)Convert.ChangeType(kvp.Value, type); @@ -79,8 +79,8 @@ public static IEnumerable GetValues(this IEnumerable(kvp.Value, true, out var enumValue)) - value.Add(enumValue); + else if (type.IsEnum && Enum.IsDefined(type, kvp.Value)) + values.Add((T)Enum.Parse(type, kvp.Value.ToString())); else values.Add((T)Convert.ChangeType(kvp.Value, type)); } From 05697ecaf676e0a6f7d496c9604255cd2b7af0f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vinicius=20C=C3=A2ndido?= Date: Sun, 1 Sep 2019 20:46:01 -0300 Subject: [PATCH 4/4] force to use only enum name I'm considering to use only the enum name because if the value is being considered during the conversion can cause side effect because the value as number can be refered to a lot of things in navigation parameters not the enum type searched. --- Source/Prism/Common/ParametersExtensions.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Source/Prism/Common/ParametersExtensions.cs b/Source/Prism/Common/ParametersExtensions.cs index 9bb823ad7..a2e0d33fe 100644 --- a/Source/Prism/Common/ParametersExtensions.cs +++ b/Source/Prism/Common/ParametersExtensions.cs @@ -25,7 +25,7 @@ public static object GetValue(this IEnumerable> par return kvp.Value; else if (type.IsAssignableFrom(kvp.Value.GetType())) return kvp.Value; - else if (type.IsEnum && Enum.IsDefined(type, kvp.Value)) + else if (type.IsEnum && Enum.IsDefined(type, kvp.Value.ToString())) return Enum.Parse(type, kvp.Value.ToString()); else return Convert.ChangeType(kvp.Value, type); @@ -50,7 +50,7 @@ public static bool TryGetValue(this IEnumerable> value = (T)kvp.Value; else if (type.IsAssignableFrom(kvp.Value.GetType())) value = (T)kvp.Value; - else if (type.IsEnum && Enum.IsDefined(type, kvp.Value)) + else if (type.IsEnum && Enum.IsDefined(type, kvp.Value.ToString())) value = (T)Enum.Parse(type, kvp.Value.ToString()); else value = (T)Convert.ChangeType(kvp.Value, type); @@ -79,7 +79,7 @@ public static IEnumerable GetValues(this IEnumerable