Det hænder til tider at man har brug for en samling af strenge, tal eller andet som man ønsker at definere i sin app.config. Dette er fx også tilfældet i dette StackOverflow post som inspirerede mig til at smide dette kodestykke live.

Mange af de løsninger jeg ser til at løse lignende problematikker, gør det ved at definere en semikolon (eller lignende) separeret liste på et enkelt key i app.config. Det er en fin løsning, og den kan bruges, men det er ikke en særligt pæn løsning, og den stiller lidt flere krav til de steder hvor den definerede liste skal bruges.

Min løsning

I dette tilfælde ønsker jeg at oprette en velkomst widget som har brug for at vide hvilke muligheder den har for at sige “hej” til brugeren.

Eksempel på den XML kode vi ender med at kunne indsætte i app.config

<?xml version="1.0" encoding="utf-8" ?<
<configuration>
 <widgets>
  <greetingWidget>
   <add greeting="Hej" />
   <add greeting="Goddag" />
   <add greeting="Hello" />
   ...
   <add greeting="Konnichiwa" />
   <add greeting="Namaskaar" />
  </greetingWidget>
 </widgets>
</configuration>

Først starter jeg med at oprette det egentlige greeting-element

Det er vigtigt at vi får nedarvet fra ConfigurationElement da vi bruger den programmatiske tilgang til at implementere vores ConfigurationElementCollection senere.

public interface IGreeting
{
    string Greeting { get; set; }
}


public class GreetingElement : ConfigurationElement, IGreeting
{
    [ConfigurationProperty("greeting", IsRequired = true)]
    public string Greeting
    {
        get { return (string)this["greeting"]; }
        set { this["greeting"] = value; }
    }
}

Derefter opretter jeg min samling som skal håndtere de forskellige hilsner.

public class GreetingElementsCollection : System.Configuration.ConfigurationElementCollection
{
    public List<IGreeting> All { 
        get { return this.Cast<IGreeting>().ToList(); }
    }

    public GreetingElement this[int index]
    {
        get
        {
            return base.BaseGet(index) as GreetingElement;
        }
        set
        {
            if (base.BaseGet(index) != null)
            {
                base.BaseRemoveAt(index);
            }
            this.BaseAdd(index, value);
        }
    }

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

    protected override object GetElementKey(ConfigurationElement element)
    {
        return ((GreetingElement)element).Greeting;
    }
}

Vi har også brug for en greetingWidget property så vores app.config forstår den nyoprettede samling

public class Widgets : System.Configuration.ConfigurationSection
{
    public static Widgets Widget => ConfigurationManager.GetSection("greetingWidget") as Widgets;

    [ConfigurationProperty("greetingWidget", IsRequired = true)]
    public GreetingElementsCollection GreetingWidget
    {
        get { return (GreetingElementsCollection)this["greetingWidget"]; }
        set { this["greetingWidget"] = value; }
    }
}

Når vi skal have fat i data fra vores config gør vi det således

List<GreetingElement> greetings = Widgets.Widget.GreetingWidget.All;