【问题标题】:error using type converter for application setting使用类型转换器进行应用程序设置时出错
【发布时间】:2011-06-13 08:16:45
【问题描述】:

在阅读了一些msdn docs 之后,我想我已经弄清楚了如何通过 Visual Studio 设计器将自定义类型用作应用设置。

设计师很高兴地存储了我的字符串,但是当我运行单元测试以查看我是否可以实际使用该设置时收到一条错误消息。

在构成相关自定义类型的其他一些类型上,我遇到了序列化错误 - 我不情愿地公开了几个属性设置器,从而使它们消失了。但是文档建议如果提供类型转换器,它将用于代替序列化。我必须为构成我想要作为设置的类型的每种类型提供一个类型转换器吗?

干杯,
浆果

根据设计器设置生成的代码

[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"]));
        }
    }

单元测试和错误

    [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.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()

类型转换器

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);
    }
}

设置文件(省略了几个用户设置)

[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"]));
        }
    }
}

更新(已修复!)

答案交给第一个看到我遗漏的谜题部分的人。提示 #1 - 原始的 TypeConverter 代码很好。提示 #2 - System.ComponentModel 非常强大!

【问题讨论】:

  • 你的设置文件是什么样的?
  • @Chris。我在帖子末尾发布了更多生成的代码,以及我在 TypeConverter 中使用 InstanceDescriptor 的最新更改。设置文件中的其他设置都可以使用。
  • @Chris。不,我毕竟不想要 InstanceDescriptor。回到我原来的代码和错误。呸

标签: c# .net visual-studio settings type-conversion


【解决方案1】:

@Berryl - 我得到了这个工作(做了一些修改,比如创建我自己的 TimeQuantity 类)。你还记得在你的 TimeQuantity 类中添加一个 TypeConverterAttribute 吗?

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

如果您在 CanConvertFrom(...) 和 ConvertFrom(...) 方法中设置断点,您应该会在读取属性时看到它们被命中。如果没有那个 TypeConverter 属性,我会得到和你一样的错误。

【讨论】:

  • 是的,福尔摩斯。该属性是我所缺少的。干杯!
猜你喜欢
  • 1970-01-01
  • 2012-01-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-10-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多