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


93

我正在使用C#express 2008创建一个简单的Windows Forms应用程序。我是一位经验丰富的C ++开发人员,但是对于C#和.NET来说,我几乎是全新的。

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

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

现在,我想存储一个整数数组(int[])或一个整数列表(List< int >)作为设置。但是,我不知道如何做到这一点。我已经搜索了文档,stackoverflow和google,但找不到关于如何执行此操作的详细说明。

基于发现的稀疏示例,我的直觉是我必须创建一个可序列化的类,该类可以包装我的数组或List,然后可以在设置设计器中使用该Type。但是,我不确定如何执行此操作。

Answers:


136

还有另一种解决方案-需要一些手动编辑设置文件,但是之后在VS环境和代码中可以正常工作。并且不需要其他功能或包装。

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

现在转到项目文件夹,并使用文本编辑器(例如,记事本)打开“ Properties \ Settings.settings”文件。或者,您也可以通过在解决方案资源管理器中右键单击“->属性-> Settings.settings”,在VS中打开该文件。 ”,选择“打开方式...”,然后选择“ XML编辑器”或“源代码(文本)编辑器”。在打开的xml设置中找到您的设置(如下所示):

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

将“类型”参数从更改System.StringSystem.Int32[]。现在,本节将如下所示:

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

现在保存更改并重新打开项目设置-贴吧!-我们具有类型为SomeTestSetting的设置System.Int32[],可以通过VS设置设计器(也可以是值)以及在代码中进行访问和编辑。


5
太棒了 要使用Visual Studio中的编辑器将某些内容输入设置,您应该粘贴这样的内容,这是针对字符串数组的,这就是我需要的<?xml version =“ 1.0” encoding =“ utf-16”?> <ArrayOfString xmlns:xsi =“ w3.org/2001/XMLSchema-instance ” xmlns:xsd =“ w3.org/2001/XMLSchema ”> <string> String1 </ string> <string> String2 </ string> </ ArrayOfString>
卡尔斯滕

9
+1 ..不明白为什么这是不被接受的答案..不需要额外的代码(只需修改现有xml的一行),您将获得类型安全性以及对设计师的全面支持!
克里斯,

1
克里斯,谢谢:)事情是,我添加的答案比最初接受的答案要晚得多(大约一年后,实际上是:))。只是分享经验而已:)
Jen-Ari

6
对于任何好奇的人,配置文件的XML语法int[]如下所示(除了漂亮的印刷内容):<setting name="SomeTestSetting" serializeAs="String"><value><ArrayOfInt xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><int>1</int><int>2</int><int>3</int></ArrayOfInt></value></setting>
aaaantoine 2015年

1
同意,这是一个更好的答案,所以我更改了标记。
sidewinderguy

40

储藏:

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

重新创建:

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

编辑:亚伯建议!


好的,这看起来就像您要手动将数据序列化为字符串,反之亦然。我想这行得通,我可以将数据存储为字符串设置。我曾想做这样的事情,但我一直在寻找更“干净”或“标准”或更多的.NET'ish内容。如果没有更好的收获,我会牢记这一点。谢谢。
sidewinderguy

嗨,那我就走麦凯的大街!(配置部分/部分组)
Mike Gleason jr Couturier

我将继续使用它,因为它很简单。感谢每个人的所有想法,我相信它们会为您提供帮助。
sidewinderguy

2
注意:您需要System.Linq添加到使用/导入中,以上技巧才能起作用。
肖恩·汉利

11

还有一种实现此结果的方法,它使用起来更清洁,但需要更多代码。我可以通过以下代码实现自定义类型和类型转换器:

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类上提供一些方便的方法,我们可以安全地分配给List和从List分配,完整的类如下所示:

[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类即可。

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


谢谢,这看起来很有趣。如果有机会,我会尝试一下。
sidewinderguy

3

将设置指定为System.Collections.ArrayList,然后:

Settings.Default.IntArray = new ArrayList(new int[] { 1, 2 });

int[] array = (int[])Settings.Default.IntArray.ToArray(typeof(int));

2

一个简单的解决方案是在属性中将设置的默认值设置为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;
        }
    }
}

感觉有点hacky,但是它很干净,并且可以按需工作,因为在调用构造函数之前,将属性初始化为它们的最后(或默认)设置。


2
应用程序设置文件的设计器会自动生成代码,因此,任何人使用设计器时,即使是偶然,这样的更改都会被覆盖。
卡尔·G

1

二手的System.Object

例:

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

提取:

arBytes = (byte[])Properties.Settings.Default.KeyObject;

1
我尝试使用System.Object,但设置在会话之间不持久。(是的,这是一个发布版本,可以独立安装,无论您想要调用什么,我都没有使用IDE进行调试)
EmanuelVintilă16年

0

我认为您对序列化设置是正确的。请参阅我对这个问题的回答以获取示例:

在两个应用之间共享配置的技术?

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

/// <summary>
/// Gets or sets the height.
/// </summary>
/// <value>The height.</value>
[XmlAttribute]
public int [] Numbers { get; set; }

0

进行一些将int数组转换为字符串的函数,但是在每个函数之间放置一个类似“”(空格)的字符。

因此,如果数组为{1,34,546,56},则字符串将为“ 1 34 645 56”

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.