// Licensed to the .NET Foundation under one or more agreements. // 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.Globalization; using System.Threading; namespace System.ComponentModel { /// /// Specifies the default value for a property. /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1019:DefineAccessorsForAttributeArguments")] [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1813:AvoidUnsealedAttributes")] [AttributeUsage(AttributeTargets.All)] public class DefaultValueAttribute : Attribute { /// /// This is the default value. /// 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 /// specified type, and using the U.S. English culture as the /// translation /// context. /// public DefaultValueAttribute(Type type, string value) { // The try/catch here is because attributes should never throw exceptions. We would fail to // load an otherwise normal class. try { if (TryConvertFromInvariantString(type, value, out object convertedValue)) { _value = convertedValue; } else if (type.IsSubclassOf(typeof(Enum))) { _value = Enum.Parse(type, value, true); } else if (type == typeof(TimeSpan)) { _value = TimeSpan.Parse(value); } else { _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 { } } /// /// Initializes a new instance of the class using a Unicode /// character. /// public DefaultValueAttribute(char value) { _value = value; } /// /// Initializes a new instance of the class using an 8-bit unsigned /// integer. /// public DefaultValueAttribute(byte value) { _value = value; } /// /// Initializes a new instance of the class using a 16-bit signed /// integer. /// public DefaultValueAttribute(short value) { _value = value; } /// /// Initializes a new instance of the class using a 32-bit signed /// integer. /// public DefaultValueAttribute(int value) { _value = value; } /// /// Initializes a new instance of the class using a 64-bit signed /// integer. /// public DefaultValueAttribute(long value) { _value = value; } /// /// Initializes a new instance of the class using a /// single-precision floating point /// number. /// public DefaultValueAttribute(float value) { _value = value; } /// /// Initializes a new instance of the class using a /// double-precision floating point /// number. /// public DefaultValueAttribute(double value) { _value = value; } /// /// Initializes a new instance of the class using a /// value. /// public DefaultValueAttribute(bool value) { _value = value; } /// /// Initializes a new instance of the class using a . /// public DefaultValueAttribute(string value) { _value = value; } /// /// Initializes a new instance of the /// class. /// public DefaultValueAttribute(object value) { _value = value; } /// /// Initializes a new instance of the class using a /// value. /// [CLSCompliant(false)] public DefaultValueAttribute(sbyte value) { _value = value; } /// /// Initializes a new instance of the class using a /// value. /// [CLSCompliant(false)] public DefaultValueAttribute(ushort value) { _value = value; } /// /// Initializes a new instance of the class using a /// value. /// [CLSCompliant(false)] public DefaultValueAttribute(uint value) { _value = value; } /// /// Initializes a new instance of the class using a /// value. /// [CLSCompliant(false)] public DefaultValueAttribute(ulong value) { _value = value; } /// /// /// Gets the default value of the property this /// attribute is /// bound to. /// /// public virtual object Value { get { return _value; } } public override bool Equals(object obj) { if (obj == this) { return true; } if (obj is DefaultValueAttribute other) { if (Value != null) { return Value.Equals(other.Value); } else { return (other.Value == null); } } return false; } public override int GetHashCode() { return base.GetHashCode(); } protected void SetValue(object value) { _value = value; } } }