From ec15d1e5b014cf8cf08c55011e8e9edab070abf9 Mon Sep 17 00:00:00 2001 From: Marco Rossignoli Date: Wed, 15 Aug 2018 03:56:43 +0200 Subject: [PATCH] Add TypeConverter fallback to DefaultValueAttribute (dotnet/coreclr#19354) Commit migrated from https://github.com/dotnet/coreclr/commit/431d041b7697a7ce307caa6090fab01ffd7ae652 --- .../System/ComponentModel/DefaultValueAttribute.cs | 36 +++++++++++++++++++--- 1 file changed, 31 insertions(+), 5 deletions(-) diff --git a/src/libraries/System.Private.CoreLib/src/System/ComponentModel/DefaultValueAttribute.cs b/src/libraries/System.Private.CoreLib/src/System/ComponentModel/DefaultValueAttribute.cs index 3cdc907..5f7108a 100644 --- a/src/libraries/System.Private.CoreLib/src/System/ComponentModel/DefaultValueAttribute.cs +++ b/src/libraries/System.Private.CoreLib/src/System/ComponentModel/DefaultValueAttribute.cs @@ -2,11 +2,8 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using System; -using System.ComponentModel; -using System.Diagnostics; using System.Globalization; -using System.Runtime.InteropServices; +using System.Threading; namespace System.ComponentModel { @@ -23,6 +20,9 @@ namespace System.ComponentModel /// private object _value; + // Delegate ad hoc created 'TypeDescriptor.ConvertFromInvariantString' reflection object cache + static object s_convertFromInvariantString; + /// /// Initializes a new instance of the class, converting the /// specified value to the @@ -36,7 +36,11 @@ namespace System.ComponentModel // load an otherwise normal class. try { - if (type.IsSubclassOf(typeof(Enum))) + if (TryConvertFromInvariantString(type, value, out object convertedValue)) + { + _value = convertedValue; + } + else if (type.IsSubclassOf(typeof(Enum))) { _value = Enum.Parse(type, value, true); } @@ -48,6 +52,28 @@ namespace System.ComponentModel { _value = Convert.ChangeType(value, type, CultureInfo.InvariantCulture); } + + return; + + // Looking for ad hoc created TypeDescriptor.ConvertFromInvariantString(Type, string) + bool TryConvertFromInvariantString(Type typeToConvert, string stringValue, out object conversionResult) + { + conversionResult = null; + + // lazy init reflection objects + if (s_convertFromInvariantString == null) + { + Type typeDescriptorType = Type.GetType("System.ComponentModel.TypeDescriptor, System.ComponentModel.TypeConverter", throwOnError: false); + Volatile.Write(ref s_convertFromInvariantString, typeDescriptorType == null ? new object() : Delegate.CreateDelegate(typeof(Func), typeDescriptorType, "ConvertFromInvariantString", ignoreCase: false)); + } + + if (!(s_convertFromInvariantString is Func convertFromInvariantString)) + return false; + + conversionResult = convertFromInvariantString(typeToConvert, stringValue); + + return true; + } } catch { -- 2.7.4