2009-11-19 31 views
79

Sto creando un'applicazione Windows Forms semplice utilizzando C# express 2008. Sono uno sviluppatore C++ esperto, ma sono praticamente nuovo di zecca in C# e .NET.Come memorizzare int [] array nell'applicazione Impostazioni

Attualmente sto memorizzare alcuni dei miei semplici impostazioni dell'applicazione utilizzando il designer impostazioni e il codice come questo:

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

Ora vorrei per memorizzare sia un array di int (int[]), o forse un Elenco di ints (List<int>), come impostazione. Tuttavia, non riesco a capire come farlo. Ho cercato la documentazione, StackOverflow e Google, e non riesco a trovare una spiegazione decente su come farlo.

La mia impressione basata sugli esempi sparsi che ho trovato è che devo creare una classe serializzabile che avvolge il mio array o List, e quindi potrò usare quel tipo nella finestra di progettazione delle impostazioni. Tuttavia, non sono sicuro di come farlo.

Grazie in anticipo per il vostro aiuto!

+7

Sono anche nuovo di zecca per StackOverflow (che è dolce btw), quindi per favore non fiammeggiante se io hai violato regole o linee guida. :-) – sidewinderguy

+3

Benvenuto! Siamo qui per aiutarti (e puoi farlo anche tu, se vuoi) – Abel

+1

+1 per essere un novizio;) –

risposta

118

C'è anche un'altra soluzione: richiede un po 'di modifica manuale del file delle impostazioni, ma in seguito funziona bene nell'ambiente VS e nel codice. E non richiede funzioni aggiuntive o wrapper.

Il fatto è che VS consente di serializzare il tipo int[] per impostazione predefinita nel file delle impostazioni - semplicemente non consente di selezionarlo per impostazione predefinita. Quindi, creare un'impostazione con il nome desiderato (ad esempio SomeTestSetting) e renderla di qualsiasi tipo (ad esempio, string per impostazione predefinita). Salva le modifiche.

Ora vai nella cartella del progetto e apri il file "Proprietà \ Impostazioni.settings" con l'editor di testo (Blocco note, ad esempio) Oppure puoi aprirlo in VS facendo clic con il tasto destro in Esplora soluzioni su "-> Proprietà - > Settings.settings ", selezionare" Apri con ... "e quindi scegliere" XML Editor "o" Source Code (Text) Editor ". Nelle impostazioni XML aperti trovare l'impostazione (che sarà simile a questo):

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

Cambiare il "Tipo" param System.String-System.Int32[]. Ora questa sezione sarà simile a questa:

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

Ora salva le modifiche e riapri le impostazioni del progetto - voilà! - Abbiamo l'impostazione SomeTestSetting con tipo System.Int32[] a cui è possibile accedere e modificare tramite VS Settings Designer (anche valori), nonché nel codice.

+5

Fantastico . Per inserire qualcosa nell'impostazione usando l'editor in Visual Studio, dovresti incollare qualcosa come questo, questo è per un array di stringhe, che era quello di cui avevo bisogno < ArrayOfString xmlns: xsi = "http://www.w3.org/2001/XMLSchema-instance" xmlns: xsd = "http://www.w3.org/2001/XMLSchema"> String1 String2 Karsten

+9

+1 .. non capisco perché questa risposta non è stata accettata .. nessun codice aggiuntivo richiesto (basta modificare una riga di xml esistente) e si ottiene sicurezza del tipo e pieno supporto progettista vs! – Chris

+1

Chris, grazie :) Il fatto è che ho aggiunto la mia risposta molto più tardi della risposta originariamente accettata (circa un anno dopo, in realtà :)). Basta condividere l'esperienza :) –

38

per memorizzare:

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

Per ricreare:

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

Edit: Abel suggerimento!

+2

e io ;-). Suggerimento "è possibile rimuovere' ToCharArray() ', e usare' value.Split (',') ', che è un po 'più leggibile – Abel

+0

Ok, quindi sembra che si stiano serializzando manualmente i dati in una stringa, e vice - Credo che questo funzionerebbe, potrei semplicemente memorizzare i dati come impostazione di una stringa, ho pensato di fare qualcosa di simile, ma stavo cercando qualcosa di più "pulito" o "standard" o solo più .NETish. Tienilo a mente, se non succede niente di meglio, grazie – sidewinderguy

+0

Ciao, vorrei andare con McKay's Avenue quindi! (Sezione config/sezione gruppo) –

0

Penso che tu abbia ragione sulla serializzazione delle tue impostazioni. Vedere la mia risposta a questa domanda per un campione:

Techniques for sharing a config between two apps?

si avrebbe una proprietà che è un array, in questo modo:

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

specificare l'impostazione come System.Collections.ArrayList e quindi:

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

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

C'è un altro modo per ottenere questo risultato che è molto più pulito nell'utilizzo ma richiede più codice. La mia attuando un tipo personalizzato e il tipo di convertitore il seguente codice è possibile:

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

per raggiungere questo obiettivo è necessario un tipo con un convertitore di tipi che permette la conversione da e per le stringhe. A tale scopo, decorando il tipo con la TypeConverterAttribute:

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

Poi attuazione di questo convertitore di tipo come una derivazione di 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); 
    } 
} 

Fornendo alcuni metodi di convenienza sulla classe MyNumberArray possiamo quindi assegnare in modo sicuro da e per List, la classe completa sarebbe simile:

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

Infine, per utilizzare questo nelle impostazioni si aggiungono le classi di cui sopra per un assemblaggio e compilazione. Nell'editor Settings.settings è sufficiente fare clic sull'opzione "Sfoglia" e selezionare la classe MyNumberArray e il gioco è fatto.

Ancora una volta questo è molto più codice; tuttavia, può essere applicato a tipi di dati molto più complicati di un semplice array.

+0

Grazie, sembra interessante. Lo proverò quando ne avrò l'occasione. – sidewinderguy

2

Una soluzione semplice consiste nell'impostare il valore predefinito di un'impostazione su null nella proprietà, ma nel costruttore verificare se la proprietà è nullo e, in tal caso, impostarla sul valore predefinito effettivo. Quindi, se si voleva un array di interi:

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

Ci si sente tipo di hacky, ma è pulito e funziona come desiderato dal momento che le proprietà vengono inizializzate al loro ultimo (o di default) le impostazioni prima che il costruttore viene chiamato.

+1

il designer per i file impostazione dell'applicazione genera automaticamente il codice, e quindi un cambiamento come questo sarebbe o verwritten ogni volta che qualcuno ha usato il designer, anche accidentalmente. –

1

Utilizzato System.Object.

Esempio:

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

Estratto:

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

Ho provato a utilizzare System.Oggetto, ma le impostazioni non persistevano tra una sessione e l'altra. (Sì, si trattava di una versione di rilascio, installazione stand-alone, qualsiasi cosa tu voglia chiamarla, non stavo eseguendo il debug usando l'IDE) –

0

fare alcune funzioni che convertono un array di int in una stringa, ma tra ogni mettere un personaggio come "" (spazio).

Quindi, se la matrice è {} 1,34,546,56 la stringa sarebbe "1 34 645 56"

Problemi correlati