2010-04-23 6 views
14

Existe-t-il un moyen pour moi d'inclure un simple tableau de chaînes, ou Liste < chaîne > sur ma sous-classe personnalisée de ConfigurationSection? (Ou un tableau ou une liste générique d'objets de données simples, d'ailleurs?)Comment inclure des collections simples dans ConfigurationSection

Je commence à me familiariser avec les nouvelles classes ConfigurationSection, ConfigurationElement et ConfigurationElementCollection (et très verbeuses), mais je ne suis en aucun cas un expert pour le moment.

Il semble que ConfigurationSection doive gérer seul des collections/listes simples, sans avoir à créer une sous-classe ConfigurationElementCollection personnalisée pour chacune d'entre elles. Mais je n'ai trouvé aucune référence à cette capacité en ligne.

Editer: Accepter la réponse de Dan comme réponse, puisque c'est probablement la chose la plus proche que je vais obtenir pour le "style ancien" configSections. J'ai toujours trouvé facile, flexible et élégant que n'importe quel objet XmlSerializable pourrait facilement devenir une configSection. Je suis sûr que le nouveau cadre est plus puissant; Cependant, il est triste que cela soit si compliqué pour des configurations simples, que nous soyons réduits à revenir à String.Split().

Répondre

8

OK, vous avez demandé simple. Eh bien, le moyen le plus simple de stocker une série de chaînes serait d'utiliser une liste délimitée (disons, séparées par des virgules). De cette façon, vous pouvez le stocker dans un seul élément (disons dans appSettings). Bien entendu, ceci présente des inconvénients mais, dans la plupart des cas, fonctionne bien pour une liste simple. Vous pouvez ensuite utiliser String.Split() pour le convertir en tableau/liste. Sinon, vous revenez aux éléments de ConfigurationSection qui, je suis d'accord, sont très verbeux et maladroits avec lesquels travailler. Mais je ne connais pas d'autre moyen, j'ai peur (mais je suis heureux d'avoir tort!).

+0

Dan D - merci, mais vous avez raison, je ne cherchais pas quelque chose d'aussi simple que cela! :) J'ai utilisé des listes délimitées et String.Split avant, et je suis sûr que je vais l'utiliser à nouveau. Mais j'espérais quelque chose d'un peu plus élégant. Peut-être que quelqu'un d'autre répondra avec quelque chose que nous avons manqué. – mikemanne

+0

Je ne le pensais pas, mais parfois les développeurs oublient l'évidence. C'est dans notre nature! –

19

Voici un exemple simple.

//START CODE 


//MyCompany.MyProject.csproj which results in MyCompany.MyProject.dll 
//Add a Folder called "Configuration" 

namespace MyCompany.MyProject.Configuration 
{ 
    using System; 
    using System.Collections.Generic; 
    using System.Linq; 
    using System.Text; 

    using System.Configuration; 


    public class TransformationToDirectoryMapping : ConfigurationElement 
    { 

     private const string FRIENDLY_NAME = "FriendlyName"; 
     private const string PICKUP_FOLDER = "PickupFolder"; 

     [ConfigurationProperty(FRIENDLY_NAME, DefaultValue = "", IsKey = false, IsRequired = true)] 
     public string FriendlyName 
     { 
      get 
      { 
       return ((string)(base[FRIENDLY_NAME])); 
      } 
      set 
      { 
       base[FRIENDLY_NAME] = value; 
      } 
     } 

     [ConfigurationProperty(PICKUP_FOLDER, DefaultValue = "", IsKey = true, IsRequired = true)] 
     public string PickupFolder 
     { 
      get 
      { 
       return ((string)(base[PICKUP_FOLDER])); 
      } 
      set 
      { 
       base[PICKUP_FOLDER] = value; 
      } 
     } 



    } 

    //----------------------------------------------------------------------- 

    //----------------------------------------------------------------------- 

    [ConfigurationCollection(typeof(TransformationToDirectoryMapping))] 
    public class TransformationToDirectoryMappingCollection : ConfigurationElementCollection 
    { 

     protected override ConfigurationElement CreateNewElement() 
     { 
      return new TransformationToDirectoryMapping(); 
     } 

     protected override object GetElementKey(ConfigurationElement element) 
     { 
      return ((TransformationToDirectoryMapping)(element)).PickupFolder; 
     } 


     public TransformationToDirectoryMapping this[int idx] 
     { 
      get 
      { 
       return (TransformationToDirectoryMapping)BaseGet(idx); 
      } 
     } 

     new public TransformationToDirectoryMapping this[string key] 
     { 
      get 
      { 
       return (TransformationToDirectoryMapping)BaseGet(key); 
      } 
     } 
    } 

    //----------------------------------------------------------------------- 

    //----------------------------------------------------------------------- 

    public class TransformationToDirectoryMappingConfigSection : ConfigurationSection 
    { 
     private const string TRANSFORMATION_TO_DIRECTORY_MAPPINGS = "TransformationToDirectoryMappings"; 

     [ConfigurationProperty(TRANSFORMATION_TO_DIRECTORY_MAPPINGS)] 
     public TransformationToDirectoryMappingCollection TransformationToDirectoryMappingItems 
     { 
      get { return ((TransformationToDirectoryMappingCollection)(base[TRANSFORMATION_TO_DIRECTORY_MAPPINGS])); } 
     } 
    } 

    //----------------------------------------------------------------------- 

    //----------------------------------------------------------------------- 

    public static class MyRetriever 
    { 
     public const string MAPPINGS_CONFIGURATION_SECTION_NAME = "TransformationToDirectoryMappingsSection"; 

     public static TransformationToDirectoryMappingCollection GetTheCollection() 
     { 
      TransformationToDirectoryMappingConfigSection mappingsSection = (TransformationToDirectoryMappingConfigSection)ConfigurationManager.GetSection(MAPPINGS_CONFIGURATION_SECTION_NAME); 
      if (mappingsSection != null) 
      { 
       return mappingsSection.TransformationToDirectoryMappingItems; 
      } 
      return null; // OOPS! 

     } 
    } 

} 

// XML pour le fichier de configuration:

<?xml version="1.0" encoding="utf-8"?> 
<configuration> 
    <configSections> 
    <section name="TransformationToDirectoryMappingsSection" type="MyCompany.MyProject.Configuration.TransformationToDirectoryMappingConfigSection, MyCompany.MyProject"/> 
    </configSections> 

    <TransformationToDirectoryMappingsSection> 
    <TransformationToDirectoryMappings> 
     <add FriendlyName="Hello" PickupFolder="C:\WUWUTemp\pickups\pickup11\" /> 
     <add FriendlyName="GoodBye" PickupFolder="C:\WUWUTemp\pickups\pickup12\" /> 
    </TransformationToDirectoryMappings> 
    </TransformationToDirectoryMappingsSection> 
</configuration> 
+0

Merci pour la réponse - en particulier à une question relativement ancienne. :) Malheureusement, ce n'est toujours pas ce que je cherche. Vous avez un tableau d'objets de première classe, chacun contenant quelques chaînes. Tout ce que je veux, c'est un tableau de chaînes. En utilisant des sections de configuration "à l'ancienne", j'ai pu le faire sans créer d'objet personnalisé. J'espérais qu'il y ait un moyen de faire cela dans le nouveau cadre de configuration, sans nécessiter la création d'un objet pour envelopper essentiellement une liste . – mikemanne

+0

Je l'ai utilisé. M'a sauvé énormément de temps. Un tweak: chaîne statique publique en lecture seule MAPPINGS_CONFIGURATION_SECTION_NAME = "TransformationToDirectoryMappingsSection"; devrait être public const chaîne MAPPINGS_CONFIGURATION_SECTION_NAME = "TransformationToDirectoryMappingsSection"; –

+0

Le prix de la minutie des yeux d'aigle va à __JDN_____! Ha ha, tu m'as eu. Je l'ai changé. Content que cela ait aidé. – granadaCoder

10

Paramètres de l'application de l'Architecture

http://msdn.microsoft.com/en-us/library/8eyb2ct1.aspx

Ok, un ancien poste, mais je me suis souvenu quand je suis tombé sur un situation similaire:

...

Si vous allez dans Propriétés du projet/projet (dans VS2008 ou VS2010). Il y a un onglet "Paramètres".

Si vous ajoutez une nouvelle valeur ....

Un des types est appelé: System.Collections.Specialized.StringCollection

Donnez-lui un nom ("je FavoriteColors").

Définissez le type (comme indiqué ci-dessus).

Définissez la (les) valeur (s).L'éditeur de collection de chaînes indique «Entrez les chaînes de la collection (une par ligne)».

je suis entré:

Rouge

jaune

Noir

Blanc

Ceci ajoutera xml à votre fichier app.config.

<setting name="FavoriteColors" serializeAs="Xml"> 
     <value> 
      <ArrayOfString xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
       xmlns:xsd="http://www.w3.org/2001/XMLSchema"> 
       <string>red</string> 
       <string>yellow</string> 
       <string>black</string> 
       <string>white</string> 
      </ArrayOfString> 
     </value> 
    </setting> 

(Vous serez mieux passer par les étapes plutôt que de coller le code XML ci-dessus, parce que (par souci de concision) Je n'ai pas ajouté tout le xml à ce poste qui est généré.

Vous devriez être en mesure de « atteindre » les valeurs par code comme ceci:

private void ShowMyFavoriteColors() 
{ 
      Properties.Settings.Default.FavoriteColors.Cast<string>().ToList().ForEach(myfavcolor => 
      { 
       string temp = myfavcolor; 
      }); 
} 

Remarque, les étapes ci-dessus produisent le dessous du code C# (code automatique créé pour vous .... il est pas code créer) mais le code regarde s comme ceci:

 [global::System.Configuration.ApplicationScopedSettingAttribute()] 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 
     [global::System.Configuration.DefaultSettingValueAttribute(@"<?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""> 
    <string>red</string> 
    <string>yellow</string> 
    <string>black</string> 
    <string>white</string> 
</ArrayOfString>")] 
     public global::System.Collections.Specialized.StringCollection FavoriteColors { 
      get { 
       return ((global::System.Collections.Specialized.StringCollection)(this["FavoriteColors"])); 
      } 
     } 
    } 
} 
+0

merci pour la réponse - c'est en effet un ancien poste! Je ne suis plus sur le projet qui l'a inspiré. :) Au moment où j'ai écrit cette question, j'étais au courant de la technique que vous décrivez ici, donc il devait y avoir une raison pour laquelle je ne l'utilisais pas. Mais pour la vie de moi, je ne me souviens pas pourquoi. Quand j'aurai l'occasion de jouer, je jouerai avec un peu plus, et soit je marquerai votre réponse, soit je fournirai plus d'informations sur les raisons pour lesquelles cela ne correspond pas à mes besoins. Merci encore! – mikemanne

+0

Oops - vient de réaliser que j'ai déjà marqué une réponse à cela, et je ne veux pas le révoquer. Mais je vais certainement upvote votre réponse. :) – mikemanne

2

Je sais que la question a été répondu depuis longtemps ... mais dans mes classes « ConfigurationElement », pour la collecte des cordes, je fais habituellement les suivantes:

[ConfigurationProperty("myStringCollectionProperty", DefaultValue = "")] 
[TypeConverter(typeof(CommaDelimitedStringCollectionConverter))] 
public StringCollection MyStringCollectionProperty 
{ 
    get { return (StringCollection)this["myStringCollectionProperty"]; } 
    set { this["myStringCollectionProperty"] = value; } 
} 

Et vous pouvez obtenir une liste de chaînes de cette propriété avec

List<string> myStrings = config.MyStringCollectionProperty.Cast<string>.ToList() 
Questions connexes