2009-11-19 173 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」

相關問題