What is an implicit contract for a property type when used with the ConfigurationProperty attribute?

As an example, I would like to serialize and deserialize the System.Version object as part of the user configuration section of the application. I am trying to do this with the following property declaration:

 public class ConfigElement : ConfigurationElement { [ConfigurationProperty("ver", IsRequired = false, DefaultValue = "1.2.4.8")] public Version Ver { get { return (Version)this["ver"]; } set { this["ver"] = value; } } } 

Unfortunately, an attempt to serialize or use this property (with or without DefaultValue ) gives the following exception message.

System.Configuration.ConfigurationErrorsException: The value of the 'ver' property cannot be converted to a string. Error: Unable to find a converter that supports conversion to / from string for the 'ver' property of type 'Version'.

System.Version.ToString() writes the object to the well-known string format, which is spent on System.Version.ctor(string) , so it seems possible that a "converter" exists for this type. Comparatively, the System.TimeSpan type has similar methods and functions ( Parse in place of .ctor(string) ), and this type works well with the configuration system (the converter must already exist).

How to find out if the type has a suitable converter? Which contract (implicit or otherwise) should correspond to this type?

+4
source share
1 answer

For ConfigurationProperty to work, the type used must be associated with a TypeConverter , than to know how to convert from a string. ConfigurationProperty has a Converter property, but, alas, it is read-only. And, really bad luck, the version does not have an implicit TypeConverter declared either.

What you can do is add TypeConverterAttribute to the version class programmatically, and this will do about all these issues. Therefore, you need to basically call this line once in your program before accessing the configuration:

 TypeDescriptor.AddAttributes(typeof(Version), new TypeConverterAttribute(typeof(VersionTypeConverter))); // ... you can call configuration code now... 

with the following custom VersionTypeConverter:

 public class VersionTypeConverter : TypeConverter { public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) { return new Version((string)value); } public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) { if (sourceType == typeof(string)) return true; return base.CanConvertFrom(context, sourceType); } } 
+4
source

Source: https://habr.com/ru/post/1340402/


All Articles