代码之家  ›  专栏  ›  技术社区  ›  sidewinderguy

如何在应用程序设置中存储int[]数组

  •  87
  • sidewinderguy  · 技术社区  · 16 年前

    我用C++的Express 2008创建了一个简单的Windows窗体应用程序。我是一个有经验的C++开发人员,但我对C语言和.NET非常陌生。

    我目前正在使用设置设计器存储一些简单的应用程序设置,代码如下:

    // Store setting  
    Properties.Settings.Default.TargetLocation = txtLocation.Text;  
    ...  
    // Restore setting  
    txtLocation.Text = Properties.Settings.Default.TargetLocation;  
    

    现在我想存储一个int数组( int[] List< int > ),作为背景。然而,我不知道该怎么做。我已经搜索了文档、stackoverflow和google,但我找不到一个合适的解释来解释如何做到这一点。

    根据我发现的稀疏示例,我的直觉是,我必须创建一个可序列化的类来包装我的数组或列表,然后才能在设置设计器中使用该类型。然而,我不知道该怎么做。

    8 回复  |  直到 8 年前
        1
  •  140
  •   Jen-Ari    15 年前

    还有另一个解决方案-需要对设置文件进行一些手动编辑,但之后在VS环境和代码中工作良好。并且不需要额外的函数或包装。

    问题是,VS允许序列化 int[] 默认情况下,在设置文件中键入-默认情况下,它不允许您选择它。 因此,创建一个具有所需名称的设置(例如SomeTestSetting),并将其设置为任何类型(例如。 string 默认情况下)。

    现在转到项目文件夹,用文本编辑器(例如记事本)打开“Properties\Settings.Settings”文件,或者在解决方案资源管理器中右键单击“->房地产->Settings.Settings”,选择“打开时使用…”,然后选择“XML编辑器”或“源代码(文本)编辑器”。 在打开的xml设置中找到您的设置(如下所示):

    <Setting Name="SomeTestSetting" Type="System.String" Scope="User">
      <Value Profile="(Default)" />
    </Setting>
    

    将“类型”参数从 System.String System.Int32[]

    <Setting Name="SomeTestSetting" Type="System.Int32[]" Scope="User">
      <Value Profile="(Default)" />
    </Setting>
    

    现在保存更改并重新打开项目设置-瞧我们有一个类型为SomeTestSetting的设置 可以通过VS设置设计器(也可以是值)以及在代码中访问和编辑。

        2
  •  42
  •   Mike Gleason jr Couturier    16 年前

    string value = String.Join(",", intArray.Select(i => i.ToString()).ToArray());

    要重新创建:

    int[] arr = value.Split(',').Select(s => Int32.Parse(s)).ToArray();

    编辑:阿贝尔建议!

        3
  •  11
  •   csharptest.net    16 年前

    还有一种方法可以实现这个结果,它的使用更加简洁,但需要更多的代码。实现自定义类型和类型转换器时,可以使用以下代码:

    List<int> array = Settings.Default.Testing;
    array.Add(new Random().Next(10000));
    Settings.Default.Testing = array;
    Settings.Default.Save();
    

    要实现这一点,您需要一个带有类型转换器的类型,该类型转换器允许在字符串之间进行转换。您可以通过使用TypeConverterAttribute装饰类型来完成此操作:

    [TypeConverter(typeof(MyNumberArrayConverter))]
    public class MyNumberArray ...
    

    然后将此类型转换器作为TypeConverter的派生实现:

    class MyNumberArrayConverter : TypeConverter
    {
        public override bool CanConvertTo(ITypeDescriptorContext ctx, Type type)
        { return (type == typeof(string)); }
    
        public override bool CanConvertFrom(ITypeDescriptorContext ctx, Type type)
        { return (type == typeof(string)); }
    
        public override object ConvertTo(ITypeDescriptorContext ctx, CultureInfo ci, object value, Type type)
        {
            MyNumberArray arr = value as MyNumberArray;
            StringBuilder sb = new StringBuilder();
            foreach (int i in arr)
                sb.Append(i).Append(',');
            return sb.ToString(0, Math.Max(0, sb.Length - 1));
        }
    
        public override object ConvertFrom(ITypeDescriptorContext ctx, CultureInfo ci, object data)
        {
            List<int> arr = new List<int>();
            if (data != null)
            {
                foreach (string txt in data.ToString().Split(','))
                    arr.Add(int.Parse(txt));
            }
            return new MyNumberArray(arr);
        }
    }
    

    通过在MyNumberArray类上提供一些方便的方法,我们可以安全地从列表中分配到或分配给它,完整的类将如下所示:

    [TypeConverter(typeof(MyNumberArrayConverter))]
    public class MyNumberArray : IEnumerable<int>
    {
        List<int> _values;
    
        public MyNumberArray() { _values = new List<int>(); }
        public MyNumberArray(IEnumerable<int> values) { _values = new List<int>(values); }
    
        public static implicit operator List<int>(MyNumberArray arr)
        { return new List<int>(arr._values); }
        public static implicit operator MyNumberArray(List<int> values)
        { return new MyNumberArray(values); }
    
        public IEnumerator<int> GetEnumerator()
        { return _values.GetEnumerator(); }
        IEnumerator IEnumerable.GetEnumerator()
        { return ((IEnumerable)_values).GetEnumerator(); }
    }
    

    最后,要在设置中使用它,需要将上述类添加到程序集并编译。在Settings.Settings编辑器中,您只需单击“浏览”选项并选择MyNumberArray类即可。

    这是更多的代码;但是,它可以应用于比简单数组更复杂的数据类型。

        4
  •  3
  •   João Angelo    16 年前

    Settings.Default.IntArray = new ArrayList(new int[] { 1, 2 });
    
    int[] array = (int[])Settings.Default.IntArray.ToArray(typeof(int));
    
        5
  •  2
  •   Russell Bearden    15 年前

    一个简单的解决方案是在属性中将设置的默认值设置为null,但在构造函数中检查属性是否为null,如果为null,则将其设置为实际的默认值。因此,如果您想要一个整数数组:

    public class ApplicationSettings : ApplicationSettingsBase
    {
        public ApplicationSettings()
        {
            if( this.SomeIntArray == null )
                this.SomeIntArray = new int[] {1,2,3,4,5,6};
        }
    
        [UserScopedSetting()]
        [DefaultSettingValue("")]
        public int[] SomeIntArray
        {
            get
            {
                return (int[])this["SomeIntArray"];
            }
            set
            {
                this["SomeIntArray"] = (int[])value;
            }
        }
    }
    

        6
  •  1
  •   Uwe Keim    13 年前

    使用 System.Object

    例子:

    byte[] arBytes = new byte[] { 10, 20, 30 };
    Properties.Settings.Default.KeyObject = arBytes;
    

    摘录:

    arBytes = (byte[])Properties.Settings.Default.KeyObject;
    
        7
  •  0
  •   Community Mohan Dere    9 年前

    我认为你对序列化设置的看法是正确的。有关示例,请参见我对该问题的回答:

    Techniques for sharing a config between two apps?

    您将拥有一个数组属性,如下所示:

    /// <summary>
    /// Gets or sets the height.
    /// </summary>
    /// <value>The height.</value>
    [XmlAttribute]
    public int [] Numbers { get; set; }
    
        8
  •  0
  •   user1452079    13 年前

    因此,如果数组是{1,34546,56},字符串将是“13464556”