Ich versuche, einen benutzerdefinierten Konfigurationsabschnitt in einem Projekt zu implementieren, und stoße immer wieder auf Ausnahmen, die ich nicht verstehe. Ich hoffe, dass hier jemand die Lücken füllen kann.
Ich habe App.config
das sieht so aus:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="ServicesSection" type="RT.Core.Config.ServicesConfigurationSectionHandler, RT.Core"/>
</configSections>
<ServicesSection type="RT.Core.Config.ServicesSection, RT.Core">
<Services>
<AddService Port="6996" ReportType="File" />
<AddService Port="7001" ReportType="Other" />
</Services>
</ServicesSection>
</configuration>
Ich habe ein ServiceConfig
Element wie folgt definiert:
public class ServiceConfig : ConfigurationElement
{
public ServiceConfig() {}
public ServiceConfig(int port, string reportType)
{
Port = port;
ReportType = reportType;
}
[ConfigurationProperty("Port", DefaultValue = 0, IsRequired = true, IsKey = true)]
public int Port
{
get { return (int) this["Port"]; }
set { this["Port"] = value; }
}
[ConfigurationProperty("ReportType", DefaultValue = "File", IsRequired = true, IsKey = false)]
public string ReportType
{
get { return (string) this["ReportType"]; }
set { this["ReportType"] = value; }
}
}
Und ich habe so ServiceCollection
definiert:
public class ServiceCollection : ConfigurationElementCollection
{
public ServiceCollection()
{
Console.WriteLine("ServiceCollection Constructor");
}
public ServiceConfig this[int index]
{
get { return (ServiceConfig)BaseGet(index); }
set
{
if (BaseGet(index) != null)
{
BaseRemoveAt(index);
}
BaseAdd(index, value);
}
}
public void Add(ServiceConfig serviceConfig)
{
BaseAdd(serviceConfig);
}
public void Clear()
{
BaseClear();
}
protected override ConfigurationElement CreateNewElement()
{
return new ServiceConfig();
}
protected override object GetElementKey(ConfigurationElement element)
{
return ((ServiceConfig) element).Port;
}
public void Remove(ServiceConfig serviceConfig)
{
BaseRemove(serviceConfig.Port);
}
public void RemoveAt(int index)
{
BaseRemoveAt(index);
}
public void Remove(string name)
{
BaseRemove(name);
}
}
Der Teil, den ich vermisse, ist, was für den Handler zu tun ist. Ursprünglich habe ich versucht, ein zu implementieren, IConfigurationSectionHandler
aber zwei Dinge gefunden:
- es hat nicht funktioniert
- es ist veraltet.
Ich bin jetzt völlig verloren, was ich tun soll, damit ich meine Daten aus der Konfiguration lesen kann. Jede Hilfe bitte!
c#
configuration
app-config
configuration-files
Chris Holmes
quelle
quelle
Antworten:
Die vorherige Antwort ist richtig, aber ich gebe Ihnen auch den gesamten Code.
Ihre app.config sollte folgendermaßen aussehen:
Ihre
ServiceConfig
undServiceCollection
Klassen bleiben unverändert.Du brauchst eine neue Klasse:
Und das sollte den Trick machen. Um es zu konsumieren, können Sie verwenden:
quelle
[Add|Remove|Clear]ItemName
Eigenschaften desConfigurationCollection
Attributs sind in diesem Fall nicht wirklich erforderlich, da "add" / "clear" / "remove" bereits die Standardnamen der XML-Elemente sind.Wenn Sie nach einem benutzerdefinierten Konfigurationsabschnitt wie dem folgenden suchen
Dann können Sie meinen Abschnitt zur Implementierung der Konfiguration verwenden, um loszulegen
System.Configuration
Assemblyverweis auf Ihr ProjektSchauen Sie sich die einzelnen verschachtelten Elemente an, die ich verwendet habe. Das erste sind Anmeldeinformationen mit zwei Attributen. Fügen Sie sie also zuerst hinzu
Anmeldeinformationen Element
PrimaryAgent und SecondaryAgent
Beide haben dieselben Attribute und scheinen eine Adresse für eine Reihe von Servern für ein primäres und ein Failover zu sein. Sie müssen also nur eine Elementklasse für beide erstellen, wie die folgenden
Ich werde später in diesem Beitrag erklären, wie zwei verschiedene Elemente mit einer Klasse verwendet werden. Lassen Sie uns die SiteId überspringen, da es keinen Unterschied gibt. Sie müssen nur eine Klasse wie oben mit nur einer Eigenschaft erstellen. Lassen Sie uns sehen, wie die Lanes-Sammlung implementiert wird
Es ist in zwei Teile geteilt. Zuerst müssen Sie eine Elementimplementierungsklasse erstellen, dann müssen Sie eine Sammlungselementklasse erstellen
LaneConfigElement
Sie können feststellen, dass ein Attribut von
LanElement
eine Aufzählung ist. Wenn Sie versuchen, einen anderen Wert in der Konfiguration zu verwenden, der nicht in der Aufzählungsanwendung definiert ist, wirdSystem.Configuration.ConfigurationErrorsException
beim Start ein Wert ausgelöst. Ok, fahren wir mit der Sammlungsdefinition fortSie können feststellen, dass ich festgelegt habe, dass
AddItemName = "Lane"
Sie für Ihr Sammlungseintragselement auswählen können, was Sie möchten. Ich bevorzuge die Verwendung des Standardelements "Hinzufügen", aber ich habe es nur für diesen Beitrag geändert.Jetzt sind alle unsere verschachtelten Elemente implementiert. Jetzt sollten wir alle Elemente in einer Klasse zusammenfassen, die implementiert werden muss
System.Configuration.ConfigurationSection
CustomApplicationConfigSection
Jetzt können Sie sehen, dass wir zwei Eigenschaften mit Namen
PrimaryAgent
und habenSecondaryAgent
beide denselben Typ haben. Jetzt können Sie leicht verstehen, warum wir nur eine Implementierungsklasse für diese beiden Elemente hatten.Bevor Sie diesen neu erfundenen Konfigurationsabschnitt in Ihrer app.config (oder web.config) verwenden können, müssen Sie Ihrer Anwendung nur mitteilen, dass Sie Ihren eigenen Konfigurationsabschnitt erfunden haben, und ihm etwas Respekt geben. Dazu müssen Sie die folgenden Zeilen hinzufügen in app.config (möglicherweise direkt nach dem Start des Root-Tags).
HINWEIS : MyAssemblyName sollte ohne DLL sein. Wenn der Name Ihrer Assemblydatei beispielsweise myDll.dll lautet, verwenden Sie myDll anstelle von myDll.dll
Um diese Konfiguration abzurufen, verwenden Sie die folgende Codezeile an einer beliebigen Stelle in Ihrer Anwendung
Ich hoffe, der obige Beitrag würde Ihnen helfen, mit etwas komplizierten benutzerdefinierten Konfigurationsabschnitten zu beginnen.
Viel Spaß beim Codieren :)
**** Bearbeiten **** Um LINQ zu aktivieren
LaneConfigCollection
, müssen Sie implementierenIEnumerable<LaneConfigElement>
Und nach folgender Implementierung von hinzufügen
GetEnumerator
Für die Leute, die immer noch verwirrt sind, wie Ertrag wirklich funktioniert, lesen Sie diesen schönen Artikel
Zwei wichtige Punkte aus dem obigen Artikel sind
quelle
Dies ist generischer Code für die Konfigurationssammlung:
Nachdem Sie dies getan haben
GenericConfigurationElementCollection
, können Sie es einfach im Konfigurationsabschnitt verwenden (dies ist ein Beispiel aus meinem Dispatcher):Das Konfigurationselement ist config Here:
Die Konfigurationsdatei würde folgendermaßen aussehen:
Hoffe es hilft!
quelle
Eine einfachere Alternative für diejenigen, die es vorziehen, das gesamte Konfigurations-Boilerplate nicht manuell zu schreiben ...
1) Installieren Sie Nerdle.AutoConfig von NuGet
2) Definieren Sie Ihren ServiceConfig-Typ (entweder eine konkrete Klasse oder nur eine Schnittstelle).
3) Sie benötigen einen Typ, um die Sammlung zu speichern, z
4) Fügen Sie den Konfigurationsabschnitt wie folgt hinzu (beachten Sie die Benennung von camelCase).
5) Karte mit AutoConfig
quelle
Versuchen Sie, von ConfigurationSection zu erben . Dieser Blog-Beitrag von Phil Haack hat ein Beispiel.
Bestätigt gemäß der Dokumentation für IConfigurationSectionHandler :
quelle