2016-07-05 11 views
4

Ich habe einen funktionierenden benutzerdefinierten Konfigurationsabschnitt. Es ist jedoch ein Schmerz an meinen Daten über ein ConfigurationElementCollection zu bekommen, aber wenn ich versuche, meine Eigenschaft als IEnumerable zu implementieren, schlägt es mit dem Fehler:Benutzerdefinierter Konfigurationsabschnitt mit Nicht-ConfigurationElement-Eigenschaften

ConfigurationErrorsException was unhandled "Property 'contacts' is not a ConfigurationElement."

Hier wird der Code verursacht den Fehler:

[ConfigurationProperty("contacts", IsDefaultCollection = false)] 
public IEnumerable<string> Contacts 
{ 
    get { return ((ContactCollection)base["contacts"]).Cast<ContactElement>().Select(x => x.Address); } 
} 

Allerdings, wenn ich es so weit ändern:

[ConfigurationProperty("contacts", IsDefaultCollection = false)] 
public ContactCollection Contacts 
{ 
    get { return ((ContactCollection)base["contacts"]); } 
} 

Alles funktioniert gut. This Antwort klingt es wie dies ist nur etwas, das Microsoft entschied, war nicht erlaubt und so kann ich keine Eigenschaften von anderen Typen als ConfigurationElement haben. Ist das wirklich der Fall? Wie kann ich meine Immobilie als IEnumerable<string> implementieren?

Falls es darauf ankommt, versuche ich E-Mails zu speichern, und ich hätte gerne ein Element für jedes, da es eine Anzahl von ihnen gibt, möchten wir vielleicht weitere Informationen zu jedem Kontakt in der Zukunft speichern , und ich denke, eine einzelne, durch Kommas getrennte Liste könnte hässlich werden. Zum Beispiel so etwas wie:

<emergency> 
    <contact address="[email protected]" /> 
    <contact address="[email protected]" /> 
</emergency> 

Oder

<emergency> 
    <contact>[email protected]</contact> 
    <contact>[email protected]</contact> 
</emergency> 

Dank!

+0

Sie haben meine Sympathie. Benutzerdefinierte Konfigurationsabschnitte mit verschachtelten Sammlungen sind ein großer Schmerz. Ich habe viele davon geschrieben und kann mich immer noch nicht an die Syntax erinnern, die klar genug ist, um eine Antwort zu geben. Vielleicht hilft dieser Beitrag: [http://stackoverflow.com/questions/10958054/how-to-create-a-configuration-section-that- contains-a-collection-of-collections](http://stackoverflow. com/questions/10958054/how-to-create-a-configuration-Abschnitt-das-enthält-eine-Sammlung-von-Sammlungen –

+1

Es scheint mir, dass ein Großteil der Komplexität von der Unterstützung für Abschnitte stammt, die programmgesteuert oder aktualisiert werden Überschreiben von untergeordneten Konfigurationsdateien. Das ist wunderbar, aber in der Praxis verwenden wir das kaum. Es könnte sicher sein, dass wir das niemals benutzen. –

Antwort

3

Jeder Schaden in der Bereitstellung von zwei Methoden? Das erste, um die Microsoft-Anforderung zu erfüllen und das zweite, um Ihre eigenen Anforderungen zu erfüllen.

public IEnumerable<string> Contacts 
    { 
     get 
     { 
      return ContactCollection.Cast<ContactElement>().Select(x => x.Address);  
     } 
    } 

    [ConfigurationProperty("contacts", IsDefaultCollection = false)] 
    public ContactCollection ContactCollection 
    { 
     get { return ((ContactCollection)base["contacts"]); } 
    } 
+0

Ich würde gerne vermeiden, dies zu tun, aber ich weiß nicht, warum jemand Sie abgelehnt hat. Wenn dies die einzige Lösung ist, werde ich es in Zukunft akzeptieren. Danke auch für deine erste Antwort nach fünf Jahren hier zu sein! :) – sirdank

+1

Hinweis: Sie können ContactCollection sogar als privat deklarieren, was interessant ist, wenn Sie die Eigenschaft von Callern & Intellisense maskieren wollen. –

+0

L ...meine erste Antwort und ich wurde sofort abgelehnt! Ich war klug, Angst zu haben;) – Will

1

Eine Lösung, wenn Sie eine Liste der Zeichenfolge benötigen, ist eine durch Kommata getrennte (oder jeder Abscheider) Liste von Werten wie folgt zu erklären:

[ConfigurationProperty("contacts")] 
    [TypeConverter(typeof(StringSplitConverter))] 
    public IEnumerable<string> Contacts 
    { 
     get 
     { 
      return (IEnumerable<string>)base["contacts"]; 
     } 
    } 

Mit dieser TypeConverter Klasse:

public class StringSplitConverter : TypeConverter 
{ 
    public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) 
    { 
     return sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); 
    } 

    public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) 
    { 
     return string.Format("{0}", value).Split(','); 
    } 
} 

Ihre CONFIG-Datei würde dann einfach so deklariert werden:

<configuration> 
    ... 
    <mySection contacts="bill,joe" /> 
    ... 
</configuration> 

Beachten Sie, dass dies nicht für Sammlungen funktioniert, wenn Sie eine Eigenschaft wie in Wills Antwort immer explizit deklarieren müssen.