2009-11-19 166 views
79

我正在使用C#express 2008.创建一个简单的Windows Forms应用程序。我是一名经验丰富的C++开发人员,但我几乎全新的C#和.NET。如何在应用程序设置中存储int []数组

我目前存放一些使用设置设计器和代码这样我的简单的应用程序设置:

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

现在我想将任一整数数组(int[]),也可能是整数列表(List<int>)作为设置。但是,我无法弄清楚如何做到这一点。我搜索了文档,stackoverflow和谷歌,我找不到一个体面的解释如何做到这一点。

基于我发现的稀疏示例,我的预感是我必须创建一个可序列化的类来包装我的数组或List,然后我将能够在设置设计器中使用该类型。但是,我不确定如何做到这一点。

在此先感谢您的帮助!

+7

我也是全新的,以计算器(这是甜蜜的BTW),所以请不燃烧,如果我破坏了任何规则或准则。 :-) – sidewinderguy 2009-11-19 21:14:49

+3

欢迎!我们在这里帮助(你也可以做到,如果你喜欢),作为一个新手 – Abel 2009-11-19 21:18:55

+1

+1;) – 2009-11-19 21:24:16

回答

118

也有另一种解决方案 - 需要一点点的设置文件的手工编辑的,但事后在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.StringSystem.Int32[]。现在这部分将如下所示:

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

现在保存更改并重新打开项目设置 - voilà! - 我们设置了类型为System.Int32[]的SomeTestSetting,可以通过VS Settings Designer(值)以及代码来访问和编辑。

+5

太棒了。若要在Visual Studio中使用编辑器输入某些内容,应该粘贴如下所示的内容,这是针对字符串数组的,这正是我需要的<?xml version =“1.0”encoding =“utf-16”?> < ArrayOfString xmlns:xsi =“http://www.w3.org/2001/XMLSchema-instance”xmlns:xsd =“http://www.w3.org/2001/XMLSchema”> String1 String2 Karsten 2011-07-15 10:23:12

+9

+1 ..不明白为什么这是不被接受的答案..没有额外的代码需要(只需修改现有的一行xml),你会得到类型安全和完整的设计器支持! – Chris 2011-11-22 03:04:36

+1

克里斯,谢谢:)事情是,我已经在最初接受的答案之后添加了我的答案(大约一年后,实际上:))。 只是分享经验:) – 2011-11-23 15:20:36

38

存储:

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

重新创建:

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

编辑:阿贝尔建议!

+2

和我;-)。提示:“你可以删除ToCharArray()',并使用'value.Split(',')',这是一个更可读的。 – Abel 2009-11-19 21:24:48

+0

好吧,这看起来像你手动序列化数据到一个字符串, -versa。我想这会起作用,我可以将数据存储为字符串设置。我想过这样做,但我正在寻找更“干净”或“标准”或更多.NET'ish的东西。我会记住这一点,但如果没有更好的作物了。谢谢。 – sidewinderguy 2009-11-19 21:24:51

+0

嗨,我会去麦凯的大道然后!(配置节/部分组) – 2009-11-19 21:26:07

0

我认为你是正确的序列化你的设置。见我回答这个问题的一个样本:

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

指定设置的System.Collections.ArrayList和然后:

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

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

有一个其他的方式来实现这一结果是在使用清洁剂很多,但需要更多的代码。我实现自定义类型和类型转换器下面的代码是可能的:

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

要做到这一点,你需要一个类型转换器,允许转换和从字符串类型。

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

然后实现这种类型转换器类型转换器的推导:

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类,那么我们就可以放心地分配一些方便的方法您可以通过装饰与TypeConverterAttribute类型做到这一点来自列表,完整的类将看起来像这样:

[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类,然后离开你。

再次,这是一个很大的代码;然而,它可以应用于比简单数组更复杂的数据类型。

+0

谢谢你的看起来很有趣。当我有机会的时候,我会尝试一下。 – sidewinderguy 2009-11-20 17:23:09

2

一个简单的办法是设置在属性设置为null的默认值,但在构造函数检查,如果属性为null,如果是的话将它设置为实际的默认值。所以,如果你想要的int数组:

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

感觉那种哈克,但它的清洁和期望的,因为构造函数被调用之前的属性初始化为他们最后的(或默认)设置工作。

+1

为应用程序设定文件设计者自动生成的代码,所以这样一个变化将是ö任何时候任何人使用设计器,甚至意外地写。 – 2012-09-29 22:44:11

1

使用System.Object

实施例:

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

提取物:

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

我试过使用系统。对象,但设置不会在会话之间持续存在。 (是的,它是一个发布版本,独立安装,无论你想调用它,我没有使用IDE进行调试) – 2016-03-02 07:35:51

0

使一些函数转换int数组的字符串,但每个之间放置的字符,如 “”(空格)。

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

相关问题