我正在使用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[]
),或者可能存储一个int(List< int >
)列表作为设置。但是,我无法弄清楚如何做到这一点。我搜索了文档,stackoverflow和谷歌,我找不到如何做到这一点的正确解释。
基于我发现的稀疏示例,我的预感是我必须创建一个可序列化的类来包装我的数组或List,然后我将能够在设置设计器中使用该类型。但是,我不确定如何做到这一点。
答案 0 :(得分:128)
还有另一个解决方案 - 需要对设置文件进行一些手动编辑,但之后在VS环境和代码中工作正常。并且不需要额外的功能或包装。
问题是,VS允许在设置文件中默认序列化int[]
类型 - 它默认情况下不允许您选择它。
因此,创建一个具有所需名称的设置(例如SomeTestSetting)并使其成为任何类型(默认情况下为string
)。
保存更改。
现在转到项目文件夹并使用文本编辑器打开“Properties \ Settings.settings”文件(例如,记事本)或者您可以通过右键单击解决方案资源管理器中的“ - &gt;属性 - 在VS中打开它”。 &gt; 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类型System.Int32[]
,可以通过VS设置设计器(也是值)以及代码访问和编辑。
答案 1 :(得分:40)
存储:
string value = String.Join(",", intArray.Select(i => i.ToString()).ToArray());
重新创建:
int[] arr = value.Split(',').Select(s => Int32.Parse(s)).ToArray();
编辑:阿贝尔的建议!
答案 2 :(得分: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中分配,完整的类看起来像:
[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类即可。
这又是一个代码;但是,它可以应用于比简单数组更复杂的数据类型。
答案 3 :(得分:3)
将设置指定为System.Collections.ArrayList,然后:
Settings.Default.IntArray = new ArrayList(new int[] { 1, 2 });
int[] array = (int[])Settings.Default.IntArray.ToArray(typeof(int));
答案 4 :(得分: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;
}
}
}
感觉有点hacky,但它干净并且按照需要工作,因为在调用构造函数之前,属性被初始化为它们的最后(或默认)设置。
答案 5 :(得分:1)
使用System.Object
。
示例:
byte[] arBytes = new byte[] { 10, 20, 30 };
Properties.Settings.Default.KeyObject = arBytes;
提取物:
arBytes = (byte[])Properties.Settings.Default.KeyObject;
答案 6 :(得分: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; }
答案 7 :(得分:0)
创建一些在字符串中转换int数组的函数,但在每个函数之间放置一个像“”(空格)这样的字符。
因此,如果数组为{1,34,546,56},则字符串为“1 34 645 56”