开发者

error using type converter for application setting

After reading some of the msdn docs I thought I had figured out how to use a custom type as an app setting via the visual studio designer.

The designer stores my string happily enough but I get an error message when I run a unit test to see if I can actually use the setting.

I was getting serialization errors on some of the other types that make up the custom type in question - I made them go away by reluctantly making several properties setters public. BUT the docs suggest that if a Type Converter is supplied that it will be used in lieu of serialization. Must I provide a type converter for every type that makes up the type I want as a setting?

Cheers,

Berryl

generated code from designer setting

[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's 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.App开发者_StackOverflow中文版licationSettingsBase.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()

type 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 ommited)

[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!)

Answer goes to the first person that sees what part of the puzzle I was missing. Hint #1 - the original TypeConverter code was fine. Hint # 2 - The System.ComponentModel is pretty powerful!


@Berryl - I got this working (with some modifications, like creating my own TimeQuantity class). Did you remember to add a TypeConverterAttribute to your TimeQuantity class?

[TypeConverter(typeof(TimeQuantityTypeConverter))]
public class TimeQuantity
{

If you set a breakpoint inside your CanConvertFrom(...) and ConvertFrom(...) methods, you should see them hit when you read the property. Without that TypeConverter attribute, I get the same error you got.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜