After reading some msdn docs, I thought I understood how to use a custom type as an application setup through the visual studio designer.
The designer saves my line happily enough, but I get an error when I run unit test to see if I can really use this parameter.
I got serialization errors on some of the other types that make up the particular type in question - I made them go away, reluctantly making several properties public setters. BUT DOCUMENTS WARN that if a type converter is installed, it will be used instead of serialization. Should I provide a type converter for each type that makes up the type that I want as a parameter?
Cheers
Berryl
generated code from designer settings
[global::System.Configuration.ApplicationScopedSettingAttribute()] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Configuration.DefaultSettingValueAttribute("8 hours")] public global::Smack.Core.Lib.Domains.Temporal.TimeQuantity WorkQuota_Daily { get { return ((global::Smack.Core.Lib.Domains.Temporal.TimeQuantity)(this["WorkQuota_Daily"])); } }
unit test and error
[Test] public void WorkQuota_Daily_CanRead() { var setting = Properties.Settings.Default.WorkQuota_Daily; Assert.That(setting, Is.EqualTo(TimeQuantity.Hours(8))); } Test failed: System.ArgumentException : The property 'WorkQuota_Daily' could not be created from it default value. Error message: There is an error in XML document (1, 1). at System.Configuration.SettingsPropertyValue.Deserialize() at System.Configuration.SettingsPropertyValue.get_PropertyValue() at System.Configuration.SettingsBase.GetPropertyValueByName(String propertyName) at System.Configuration.SettingsBase.get_Item(String propertyName) at System.Configuration.ApplicationSettingsBase.GetPropertyValue(String propertyName) at System.Configuration.ApplicationSettingsBase.get_Item(String propertyName) C:\Users\Lord & Master\Documents\Projects\Smack\trunk\src\ConstructionAdmin.TestingSupport\Properties\Settings.Designer.cs(211,0): at Smack.ConstructionAdmin.TestingSupport.Properties.Settings.get_WorkQuota_Daily() General\ApplicationSettingsTests.cs(22,0): at Smack.ConstructionAdmin.TestingSupport.General.ApplicationSettingsTests.WorkQuota_Daily_CanRead()
Converter
public class TimeQuantityTypeConverter : TypeConverter { public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) { return sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); } public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) { if (value is string) { var v = ((string)value).Split(); var amt = v[0]; var unit = v[1]; var timeSliceFactory = new TimeSliceFactory(); var map = TimeSliceFactory.GetUnitMap(timeSliceFactory); var key = unit.ToLowerInvariant(); if (!map.ContainsKey(key)) throw new ArgumentException(string.Format("There is no time slice unit key fpr '{0}", key)); return new TimeQuantity(amt, map[key]); } return base.ConvertFrom(context, culture, value); } public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType) { if (destinationType == typeof(string)) { return string.Format("{0} {1}", ((TimeQuantity) value).Amount, ((TimeQuantity) value).Unit.PluralForm); } return base.ConvertTo(context, culture, value, destinationType); } }
settings file (several user settings)
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "10.0.0.0")] public sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); public static Settings Default { get { return defaultInstance; } } [global::System.Configuration.ApplicationScopedSettingAttribute()] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Configuration.DefaultSettingValueAttribute("8 hours")] public global::Smack.Core.Lib.Domains.Temporal.TimeQuantity WorkQuota_Daily { get { return ((global::Smack.Core.Lib.Domains.Temporal.TimeQuantity)(this["WorkQuota_Daily"])); } } [global::System.Configuration.ApplicationScopedSettingAttribute()] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Configuration.DefaultSettingValueAttribute("Monday")] public global::System.DayOfWeek StartDay { get { return ((global::System.DayOfWeek)(this["StartDay"])); } } }
Update (fixed!)
Answers the first person who sees which part of the puzzle I was missing. Hint # 1 - The original TypeConverter code was fine. Hint # 2 - System.ComponentModel is pretty powerful!