| File: System\Configuration\SettingsPropertyValue.cs | Web Access |
| Project: src\runtime\src\libraries\System.Configuration.ConfigurationManager\src\System.Configuration.ConfigurationManager.csproj (System.Configuration.ConfigurationManager) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.ComponentModel; using System.Diagnostics; using System.Globalization; using System.IO; using System.Reflection; using System.Runtime.Serialization.Formatters.Binary; using System.Xml.Serialization; namespace System.Configuration { public class SettingsPropertyValue { private object _value; private object _serializedValue; private bool _changedSinceLastSerialized; public string Name => Property.Name; public bool IsDirty { get; set; } public SettingsProperty Property { get; private set; } public bool UsingDefaultValue { get; private set; } public bool Deserialized { get; set; } public SettingsPropertyValue(SettingsProperty property) { Property = property; } public object PropertyValue { get { if (!Deserialized) { _value = Deserialize(); Deserialized = true; } if (_value != null && !Property.PropertyType.IsPrimitive && !(_value is string) && !(_value is DateTime)) { UsingDefaultValue = false; _changedSinceLastSerialized = true; IsDirty = true; } return _value; } set { _value = value; IsDirty = true; _changedSinceLastSerialized = true; Deserialized = true; UsingDefaultValue = false; } } public object SerializedValue { get { if (_changedSinceLastSerialized) { _changedSinceLastSerialized = false; _serializedValue = SerializePropertyValue(); } return _serializedValue; } set { UsingDefaultValue = false; _serializedValue = value; } } private object Deserialize() { object value = null; // Attempt 1: Try creating from SerializedValue if (SerializedValue != null) { bool throwBinaryFormatterDeprecationException = false; try { if (SerializedValue is string) { value = GetObjectFromString(Property.PropertyType, Property.SerializeAs, (string)SerializedValue); } else if (SerializedValue is byte[] serializedBytes) { if (SettingsProperty.EnableUnsafeBinaryFormatterInPropertyValueSerialization) { using (MemoryStream ms = new MemoryStream(serializedBytes)) { #pragma warning disable SYSLIB0011 // BinaryFormatter serialization is obsolete and should not be used. value = (new BinaryFormatter()).Deserialize(ms); #pragma warning restore SYSLIB0011 } } else { throwBinaryFormatterDeprecationException = true; } } } catch (Exception) { } if (throwBinaryFormatterDeprecationException) { throw new NotSupportedException(Obsoletions.BinaryFormatterMessage); } if (value != null && !Property.PropertyType.IsAssignableFrom(value.GetType())) // is it the correct type value = null; } // Attempt 2: Try creating from default value if (value == null) { UsingDefaultValue = true; if (Property.DefaultValue == null || Property.DefaultValue.ToString() == "[null]") { if (Property.PropertyType.IsValueType) return TypeUtil.CreateInstance(Property.PropertyType); else return null; } if (!(Property.DefaultValue is string)) { value = Property.DefaultValue; } else { try { value = GetObjectFromString(Property.PropertyType, Property.SerializeAs, (string)Property.DefaultValue); } catch (Exception e) { throw new ArgumentException(SR.Format(SR.Could_not_create_from_default_value, Property.Name, e.Message)); } } if (value != null && !Property.PropertyType.IsAssignableFrom(value.GetType())) // is it the correct type throw new ArgumentException(SR.Format(SR.Could_not_create_from_default_value_2, Property.Name)); } // Attempt 3: Create via the parameterless constructor if (value == null) { if (Property.PropertyType == typeof(string)) { value = string.Empty; } else { try { value = TypeUtil.CreateInstance(Property.PropertyType); } catch { } } } return value; } private static object GetObjectFromString(Type type, SettingsSerializeAs serializeAs, string serializedValue) { // Deal with string types if (type == typeof(string) && (serializedValue == null || serializedValue.Length < 1 || serializeAs == SettingsSerializeAs.String)) return serializedValue; // Return null if there is nothing to convert if (serializedValue == null || serializedValue.Length < 1) return null; // Convert based on the serialized type switch (serializeAs) { #pragma warning disable CS0618 // Type or member is obsolete case SettingsSerializeAs.Binary: #pragma warning restore CS0618 // Type or member is obsolete if (SettingsProperty.EnableUnsafeBinaryFormatterInPropertyValueSerialization) { byte[] buffer = Convert.FromBase64String(serializedValue); using (MemoryStream ms = new MemoryStream(buffer)) { #pragma warning disable SYSLIB0011 // BinaryFormatter serialization is obsolete and should not be used. return (new BinaryFormatter()).Deserialize(ms); #pragma warning restore SYSLIB0011 } } else { throw new NotSupportedException(Obsoletions.BinaryFormatterMessage); } case SettingsSerializeAs.Xml: StringReader sr = new StringReader(serializedValue); XmlSerializer xs = new XmlSerializer(type); return xs.Deserialize(sr); case SettingsSerializeAs.String: TypeConverter converter = TypeDescriptor.GetConverter(type); if (converter != null && converter.CanConvertTo(typeof(string)) && converter.CanConvertFrom(typeof(string))) return converter.ConvertFromInvariantString(serializedValue); throw new ArgumentException(SR.Format(SR.Unable_to_convert_type_from_string, type), nameof(type)); default: return null; } } private object SerializePropertyValue() { if (_value == null) return null; #pragma warning disable CS0618 // Type or member is obsolete if (Property.SerializeAs != SettingsSerializeAs.Binary) #pragma warning restore CS0618 // Type or member is obsolete { return ConvertObjectToString(_value, Property.PropertyType, Property.SerializeAs, Property.ThrowOnErrorSerializing); } if (SettingsProperty.EnableUnsafeBinaryFormatterInPropertyValueSerialization) { using (MemoryStream ms = new MemoryStream()) { #pragma warning disable SYSLIB0011 // BinaryFormatter serialization is obsolete and should not be used. BinaryFormatter bf = new BinaryFormatter(); bf.Serialize(ms, _value); #pragma warning restore SYSLIB0011 return ms.ToArray(); } } else { throw new NotSupportedException(Obsoletions.BinaryFormatterMessage); } } private static string ConvertObjectToString(object propertyValue, Type type, SettingsSerializeAs serializeAs, bool throwOnError) { if (serializeAs == SettingsSerializeAs.ProviderSpecific) { if (type == typeof(string) || type.IsPrimitive) serializeAs = SettingsSerializeAs.String; else serializeAs = SettingsSerializeAs.Xml; } try { switch (serializeAs) { case SettingsSerializeAs.String: TypeConverter converter = TypeDescriptor.GetConverter(type); if (converter != null && converter.CanConvertTo(typeof(string)) && converter.CanConvertFrom(typeof(string))) return converter.ConvertToInvariantString(propertyValue); throw new ArgumentException(SR.Format(SR.Unable_to_convert_type_to_string, type), nameof(type)); case SettingsSerializeAs.Xml: XmlSerializer xs = new XmlSerializer(type); StringWriter sw = new StringWriter(CultureInfo.InvariantCulture); xs.Serialize(sw, propertyValue); return sw.ToString(); #pragma warning disable CS0618 // Type or member is obsolete case SettingsSerializeAs.Binary: #pragma warning restore CS0618 // Type or member is obsolete Debug.Fail("Should not have gotten here with Binary formatting"); break; } } catch (Exception) { if (throwOnError) throw; } return null; } } }