2009-11-19 17 views
79

Ich erstelle eine einfache Windows Forms-Anwendung mit C# Express 2008. Ich bin ein erfahrener C++ - Entwickler, aber ich bin ziemlich neu in C# und .NET.So speichern Sie int [] Array in Anwendung Einstellungen

Ich bin zur Zeit einige meiner einfachen Anwendungseinstellungen Speichern der Einstellungen Designer und Code wie folgt verwendet:

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

nun entweder ein Array von ints (int[]) oder möglicherweise ein speichern Ich möchte Liste von Ints (List<int>), als Einstellung. Ich kann jedoch nicht herausfinden, wie das geht. Ich habe die Dokumentation, stackoverflow und google durchsucht, und ich kann keine vernünftige Erklärung finden, wie dies zu tun ist.

Meine Ahnung basierend auf den spärlichen Beispielen, die ich gefunden habe, ist, dass ich eine Klasse erstellen muss, die serializable ist, die mein Array oder List umschließt, und dann kann ich diesen Typ im Einstellungsdesigner verwenden. Ich bin mir aber nicht sicher, wie ich das genau machen soll.

Vielen Dank im Voraus für Ihre Hilfe!

+7

Ich bin auch ganz neu zu Stackoverflow (die btw süß ist), also bitte, wenn ich nicht flammend habe irgendwelche Regeln oder Richtlinien gebrochen. :-) – sidewinderguy

+3

Willkommen! Wir sind hier, um zu helfen (und Sie können auch, wenn Sie möchten) – Abel

+1

+1 für ein Neuling;) –

Antwort

118

Es gibt auch eine andere Lösung - erfordert ein wenig manuelle Bearbeitung der Einstellungsdatei, aber danach funktioniert gut in VS-Umgebung und im Code. Und benötigt keine zusätzlichen Funktionen oder Wrapper.

Die Sache ist, dass VS ermöglicht, int[] Typ standardmäßig in der Einstellungsdatei zu serialisieren - es erlaubt Ihnen einfach nicht, es standardmäßig auszuwählen. Erstellen Sie also eine Einstellung mit dem gewünschten Namen (z. B. SomeTestSetting) und erstellen Sie einen beliebigen Typ (z. B. string standardmäßig). Speichern Sie die Änderungen.

Jetzt gehen Sie zu Ihrem Projektordner und öffnen Sie die Datei "Properties \ Settings.settings" mit Texteditor (zum Beispiel Editor) Oder Sie können es in VS öffnen, indem Sie im Projektmappen-Explorer mit der rechten Maustaste auf "-> Eigenschaften - > Settings.settings ", wählen Sie" Open With ... "und dann entweder" XML Editor "oder" Source Code (Text) Editor ". In den geöffneten XML-Einstellungen finden Sie Ihre Einstellung (es wird wie folgt aussehen):

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

Ändern Sie den „Typ“ param System.String-System.Int32[]. Jetzt sieht dieser Abschnitt wie folgt aus:

Speichern Sie jetzt Änderungen und öffnen Sie die Projekteinstellungen - voilà! - Wir haben die Einstellung SomeTestSetting mit dem Typ System.Int32[], auf die über den VS Settings Designer (auch Werte) sowie im Code zugegriffen werden kann.

+5

Ehrfürchtig . Um etwas in die Einstellung mit dem Editor in Visual Studio einzugeben, sollten Sie etwas wie diese einfügen, das ist für ein String-Array, das war was ich brauchte < ArrayOfString xmlns: xsi = "http://www.w3.org/2001/XMLSchema-instance" xmlns: xsd = "http://www.w3.org/2001/XMLSchema"> String1 String2 Karsten

+9

+1 .. verstehe nicht, warum dies nicht akzeptiert wurde Antwort .. kein zusätzlicher Code erforderlich (nur eine Zeile der bestehenden XML ändern) und Sie erhalten Typ Sicherheit und volle vs Designer-Unterstützung! – Chris

+1

Chris, danke :) Das Ding ist, ich habe meine Antwort viel später als die ursprünglich angenommene Antwort hinzugefügt (etwa ein Jahr später, eigentlich :)). Nur teilen Sie die Erfahrung aber :) –

38

zu speichern:

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

neu zu erstellen:

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

Edit: Abel Vorschlag!

+2

und ich ;-). Tipp "Sie können' ToCharArray() 'entfernen und' value.Split (',') 'verwenden, was etwas besser lesbar ist. – Abel

+0

Ok, es sieht also so aus, als würden Sie die Daten manuell in eine Zeichenfolge serialisieren und umgekehrt -versa: Ich denke, das würde funktionieren, ich könnte die Daten einfach als String-Einstellung speichern, ich dachte daran, so etwas zu tun, aber ich suchte nach etwas "sauberer" oder "Standard" oder einfach nur mehr. Ich behalte das jedoch im Hinterkopf, wenn nichts Besseres auftaucht. Danke. – sidewinderguy

+0

Hallo, ich würde dann mit McKays Avenue gehen! (Konfig-Sektion/Sektion-Gruppe) –

0

Ich denke, Sie haben Recht, Ihre Einstellungen zu serialisieren. Siehe meine Antwort auf diese Frage für eine Probe:

Techniques for sharing a config between two apps?

Sie würden eine Eigenschaft haben, die ein Array ist, wie folgt aus:

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

Geben Sie die Einstellung als System.Collections.ArrayList und dann:

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

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

Es gibt eine andere Möglichkeit, dieses Ergebnis zu erreichen, das viel sauberer ist, aber mehr Code erfordert. Meine Implementierung eines benutzerdefinierten Typ und Typkonverter der folgende Code ist möglich:

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

das Sie brauchen, um mit einem Typ-Wandler, einen Typ zu erreichen, die Konvertierung zu und von Strings erlaubt. Sie tun dies, indem sie die Art mit dem Typeconverter Dekoration:

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

Dann als Ableitung von Typeconverter diese Art Konverter Umsetzung:

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

Durch einige bequeme Methoden auf der MyNumberArray Klasse bieten wir weisen Sie dann sicher zu und von List, würde die komplette Klasse in etwa so aussehen:

[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(); } 
} 

schließlich das Sie die oben genannten Klassen ein Add in den Einstellungen zu verwenden, assemblieren und kompilieren In Ihrem Settings.settings-Editor klicken Sie einfach auf die Option "Durchsuchen" und wählen Sie die MyNumberArray-Klasse aus und los gehts.

Auch dies ist viel mehr Code; Es kann jedoch auf viel kompliziertere Datentypen als ein einfaches Array angewendet werden.

+0

Danke das sieht interessant aus. Ich probiere es aus, wenn ich die Chance bekomme. – sidewinderguy

2

Eine einfache Lösung besteht darin, den Standardwert einer Einstellung in der Eigenschaft auf null festzulegen, im Konstruktor jedoch zu überprüfen, ob die Eigenschaft null ist, und in diesem Fall den tatsächlichen Standardwert zu verwenden. Also, wenn Sie eine Reihe von Ints wollte:

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

Es fühlt sich irgendwie hacky, aber es ist sauber und funktioniert wie gewünscht, da die Eigenschaften ihrer letzten initialisiert (oder Standard) Einstellungen, bevor der Konstruktor aufgerufen wird.

+1

Der Designer für Anwendungseinstellungsdateien generiert automatisch den Code, und so eine Änderung wie diese wäre o geschrieben, wann immer jemand den Designer benutzte, sogar aus Versehen. –

1

Verwendet System.Object.

Beispiel:

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

Extrakt:

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

Ich habe versucht, mit System.Objekt, aber die Einstellungen blieben nicht zwischen den Sitzungen bestehen. (Ja, es war ein Release-Build, Stand-Alone-Installation, wie auch immer Sie es nennen möchten, ich debugging nicht mit der IDE) –

0

Einige Funktionen machen, die einen int array in einer Zeichenkette konvertiert, aber zwischen jedem legte ein Zeichen wie "" (Leerzeichen).

Also, wenn das Array {1,34,546,56} die Zeichenfolge wäre „1 34 645 56“

Verwandte Themen