Fix the TypeConverter when enabling UseSystemResourceKeys (#68687)
authorTarek Mahmoud Sayed <tarekms@microsoft.com>
Sat, 30 Apr 2022 18:29:51 +0000 (11:29 -0700)
committerGitHub <noreply@github.com>
Sat, 30 Apr 2022 18:29:51 +0000 (11:29 -0700)
* Fix TypeConverter when enabling UseSystemResourceKeys

* Address the feedback

* Keep original behavior and enable running the added test with UseSystemResourceKeys on

13 files changed:
src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/ArrayConverter.cs
src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/CollectionConverter.cs
src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/CultureInfoConverter.cs
src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/DesignerOptionService.cs
src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/ExtendedPropertyDescriptor.cs
src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/InstanceCreationEditor.cs
src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/MultilineStringConverter.cs
src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/ReferenceConverter.cs
src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/TypeConverter.cs
src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/TypeListConverter.cs
src/libraries/System.ComponentModel.TypeConverter/src/System/Timers/TimersDescriptionAttribute.cs
src/libraries/System.ComponentModel.TypeConverter/tests/ContainerTests.cs
src/libraries/System.ComponentModel.TypeConverter/tests/CultureInfoConverterTests.cs

index f71ed58..5ee2d43 100644 (file)
@@ -19,7 +19,7 @@ namespace System.ComponentModel
         {
             if (destinationType == typeof(string) && value is Array)
             {
-                return SR.Format(SR.Array, value.GetType().Name);
+                return string.Format(SR.GetResourceString(nameof(SR.Array), "{0} Array"), value.GetType().Name);
             }
 
             return base.ConvertTo(context, culture, value, destinationType);
index 52b332b..4f0f1dc 100644 (file)
@@ -20,7 +20,7 @@ namespace System.ComponentModel
         {
             if (destinationType == typeof(string) && value is ICollection)
             {
-                return SR.Collection;
+                return SR.GetResourceString(nameof(SR.Collection), "(Collection)");
             }
 
             return base.ConvertTo(context, culture, value, destinationType);
index 20787a1..fc9d639 100644 (file)
@@ -22,7 +22,7 @@ namespace System.ComponentModel
         /// <summary>
         /// Retrieves the "default" name for our culture.
         /// </summary>
-        private static string DefaultCultureString => SR.CultureInfoConverterDefaultCultureString;
+        private static string DefaultCultureString => SR.GetResourceString(nameof(SR.CultureInfoConverterDefaultCultureString), "(Default)");
 
         private const string DefaultInvariantCultureString = "(Default)";
 
index ba0efec..444c060 100644 (file)
@@ -467,7 +467,7 @@ namespace System.ComponentModel.Design
             {
                 if (destinationType == typeof(string))
                 {
-                    return SR.CollectionConverterText;
+                    return SR.GetResourceString(nameof(SR.CollectionConverterText), "(Collection)");
                 }
                 return base.ConvertTo(cxt, culture, value, destinationType);
             }
index 959ce0d..645f469 100644 (file)
@@ -99,7 +99,7 @@ namespace System.ComponentModel
                     string? providerName = site?.Name;
                     if (providerName != null && providerName.Length > 0)
                     {
-                        name = SR.Format(SR.MetaExtenderName, name, providerName);
+                        name = string.Format(SR.GetResourceString(nameof(SR.MetaExtenderName), "{0} on {1}"), name, providerName);
                     }
                 }
                 return name;
index 68a5665..5f0ab1f 100644 (file)
@@ -11,7 +11,7 @@ namespace System.ComponentModel
     /// </summary>
     public abstract class InstanceCreationEditor
     {
-        public virtual string Text => SR.InstanceCreationEditorDefaultText;
+        public virtual string Text => SR.GetResourceString(nameof(SR.InstanceCreationEditorDefaultText), "(New...)");
 
         /// <summary>
         /// This method is invoked when you user chooses the link displayed by the PropertyGrid for the InstanceCreationEditor.
index 5a632e6..151085d 100644 (file)
@@ -20,7 +20,7 @@ namespace System.ComponentModel
 
             if (destinationType == typeof(string) && value is string)
             {
-                return SR.Text;
+                return SR.GetResourceString(nameof(SR.Text), "(Text)");
             }
 
             return base.ConvertTo(context, culture, value, destinationType);
index 5f01112..5d23a90 100644 (file)
@@ -15,7 +15,7 @@ namespace System.ComponentModel
     /// </summary>
     public class ReferenceConverter : TypeConverter
     {
-        private static readonly string s_none = SR.toStringNone;
+        private static readonly string s_none = SR.GetResourceString(nameof(SR.toStringNone), "(none)");
         private readonly Type _type;
 
         /// <summary>
index e3ffc2f..b22befb 100644 (file)
@@ -191,7 +191,7 @@ namespace System.ComponentModel
         /// </summary>
         protected Exception GetConvertFromException(object? value)
         {
-            string? valueTypeName = value == null ? SR.Null : value.GetType().FullName;
+            string? valueTypeName = value == null ? SR.GetResourceString(nameof(SR.Null), "(null)") : value.GetType().FullName;
             throw new NotSupportedException(SR.Format(SR.ConvertFromException, GetType().Name, valueTypeName));
         }
 
@@ -201,7 +201,7 @@ namespace System.ComponentModel
         /// </summary>
         protected Exception GetConvertToException(object? value, Type destinationType)
         {
-            string? valueTypeName = value == null ? SR.Null : value.GetType().FullName;
+            string? valueTypeName = value == null ? SR.GetResourceString(nameof(SR.Null), "(null)") : value.GetType().FullName;
             throw new NotSupportedException(SR.Format(SR.ConvertToException, GetType().Name, valueTypeName, destinationType.FullName));
         }
 
index 154cca5..3df91fb 100644 (file)
@@ -73,7 +73,7 @@ namespace System.ComponentModel
             {
                 if (value == null)
                 {
-                    return SR.none;
+                    return SR.GetResourceString(nameof(SR.none), "(none)");
                 }
                 else
                 {
index 8660f3b..66ee30e 100644 (file)
@@ -40,7 +40,10 @@ namespace System.Timers
                 if (!_replaced)
                 {
                     _replaced = true;
-                    DescriptionValue = SR.Format(base.Description);
+
+                    // We call string.Format here only to keep the original behavior which throws when having null description.
+                    // That will keep the exception is thrown from same original place with the exact parameters.
+                    DescriptionValue = string.Format(base.Description);
                 }
                 return base.Description;
             }
index f1f3319..1dde0eb 100644 (file)
@@ -322,7 +322,7 @@ namespace System.ComponentModel.Tests
             Assert.Equal(typeof(ArgumentException), ex.GetType());
             Assert.Null(ex.InnerException);
             Assert.NotNull(ex.Message);
-            Assert.True(ex.Message.IndexOf("'dup'") != -1);
+            Assert.True(ex.Message.IndexOf("'dup'") != -1 || ex.Message.IndexOf(" dup") != -1);
             Assert.Null(ex.ParamName);
             Assert.Equal(1, container.Components.Count);
 
@@ -334,7 +334,7 @@ namespace System.ComponentModel.Tests
             Assert.Equal(typeof(ArgumentException), ex.GetType());
             Assert.Null(ex.InnerException);
             Assert.NotNull(ex.Message);
-            Assert.True(ex.Message.IndexOf("'duP'") != -1);
+            Assert.True(ex.Message.IndexOf("'duP'") != -1 || ex.Message.IndexOf(" duP") != -1);
             Assert.Null(ex.ParamName);
             Assert.Equal(1, container.Components.Count);
 
@@ -356,7 +356,7 @@ namespace System.ComponentModel.Tests
             Assert.Equal(typeof(ArgumentException), ex.GetType());
             Assert.Null(ex.InnerException);
             Assert.NotNull(ex.Message);
-            Assert.True(ex.Message.IndexOf("'dup'") != -1);
+            Assert.True(ex.Message.IndexOf("'dup'") != -1 || ex.Message.IndexOf(" dup") != -1);
             Assert.Null(ex.ParamName);
             Assert.Equal(2, container.Components.Count);
             Assert.Equal(1, container2.Components.Count);
@@ -729,7 +729,7 @@ namespace System.ComponentModel.Tests
             Assert.Equal(typeof(ArgumentException), ex.GetType());
             Assert.Null(ex.InnerException);
             Assert.NotNull(ex.Message);
-            Assert.True(ex.Message.IndexOf("'dup'") != -1);
+            Assert.True(ex.Message.IndexOf("'dup'") != -1 || ex.Message.IndexOf(" dup") != -1);
             Assert.Null(ex.ParamName);
             Assert.Equal(2, _container.Components.Count);
             _container.InvokeValidateName(compB, "whatever");
@@ -742,7 +742,7 @@ namespace System.ComponentModel.Tests
             Assert.Equal(typeof(ArgumentException), ex.GetType());
             Assert.Null(ex.InnerException);
             Assert.NotNull(ex.Message);
-            Assert.True(ex.Message.IndexOf("'dup'") != -1);
+            Assert.True(ex.Message.IndexOf("'dup'") != -1 || ex.Message.IndexOf(" dup") != -1);
             Assert.Null(ex.ParamName);
             Assert.Equal(2, _container.Components.Count);
             _container.InvokeValidateName(compC, "whatever");
@@ -757,7 +757,7 @@ namespace System.ComponentModel.Tests
             Assert.Equal(typeof(ArgumentException), ex.GetType());
             Assert.Null(ex.InnerException);
             Assert.NotNull(ex.Message);
-            Assert.True(ex.Message.IndexOf("'dup'") != -1);
+            Assert.True(ex.Message.IndexOf("'dup'") != -1 || ex.Message.IndexOf(" dup") != -1);
             Assert.Null(ex.ParamName);
             Assert.Equal(2, _container.Components.Count);
             _container.InvokeValidateName(compD, "whatever");
index bbe5168..466d92d 100644 (file)
@@ -1,11 +1,13 @@
 // Licensed to the .NET Foundation under one or more agreements.
 // The .NET Foundation licenses this file to you under the MIT license.
 
+using Microsoft.DotNet.RemoteExecutor;
 using System.Collections.Generic;
 using System.ComponentModel.Design.Serialization;
 using System.Globalization;
 using System.Linq;
 using System.Reflection;
+using System.Tests;
 using Xunit;
 
 namespace System.ComponentModel.Tests
@@ -152,6 +154,23 @@ namespace System.ComponentModel.Tests
             Assert.Equal("Fixed", converter.ConvertTo(new CultureInfo("en-US"), typeof(string)));
         }
 
+        [ConditionalTheory(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))]
+        [InlineData(false)]
+        [InlineData(true)]
+        public void CultureInfoConverterForDefaultValue(bool useSystemResourceKeys)
+        {
+            RemoteInvokeOptions options = new RemoteInvokeOptions();
+            options.RuntimeConfigurationOptions.Add("System.Resources.UseSystemResourceKeys", useSystemResourceKeys);
+
+            RemoteExecutor.Invoke(() =>
+            {
+                using (new ThreadCultureChange(null, CultureInfo.InvariantCulture))
+                {
+                    Assert.Equal("", ((CultureInfo)TypeDescriptor.GetConverter(typeof(System.Globalization.CultureInfo)).ConvertFrom(null, null, "(Default)")).Name);
+                }
+            }, options).Dispose();
+        }
+
         private class SubCultureInfoConverter : CultureInfoConverter
         {
             public new string GetCultureName(CultureInfo culture)