次のようなカスタム構成セクションを探している場合
<CustomApplicationConfig>
<Credentials Username="itsme" Password="mypassword"/>
<PrimaryAgent Address="10.5.64.26" Port="3560"/>
<SecondaryAgent Address="10.5.64.7" Port="3570"/>
<Site Id="123" />
<Lanes>
<Lane Id="1" PointId="north" Direction="Entry"/>
<Lane Id="2" PointId="south" Direction="Exit"/>
</Lanes>
</CustomApplicationConfig>
次に、私の構成セクションの実装を使用して、追加を開始できます System.Configuration
アセンブリ参照をプロジェクトにします。
私が使用した各ネストされた要素を見て、最初の要素は2つの属性を持つ資格情報なので、最初に追加しましょう
資格情報要素
public class CredentialsConfigElement : System.Configuration.ConfigurationElement
{
[ConfigurationProperty("Username")]
public string Username
{
get
{
return base["Username"] as string;
}
}
[ConfigurationProperty("Password")]
public string Password
{
get
{
return base["Password"] as string;
}
}
}
PrimaryAgentおよびSecondaryAgent
どちらも同じ属性を持ち、プライマリサーバーとフェイルオーバーのサーバーセットへのアドレスのように見えるため、次のように両方に対して1つの要素クラスを作成するだけで済みます。
public class ServerInfoConfigElement : ConfigurationElement
{
[ConfigurationProperty("Address")]
public string Address
{
get
{
return base["Address"] as string;
}
}
[ConfigurationProperty("Port")]
public int? Port
{
get
{
return base["Port"] as int?;
}
}
}
この投稿の後半で、1つのクラスで2つの異なる要素を使用する方法について説明します。SiteIdには違いがないため、スキップします。上記と同じ1つのクラスを1つのプロパティのみで作成する必要があります。レーンコレクションを実装する方法を見てみましょう
最初に要素実装クラスを作成する必要があり、次にコレクション要素クラスを作成する必要があります。
LaneConfigElement
public class LaneConfigElement : ConfigurationElement
{
[ConfigurationProperty("Id")]
public string Id
{
get
{
return base["Id"] as string;
}
}
[ConfigurationProperty("PointId")]
public string PointId
{
get
{
return base["PointId"] as string;
}
}
[ConfigurationProperty("Direction")]
public Direction? Direction
{
get
{
return base["Direction"] as Direction?;
}
}
}
public enum Direction
{
Entry,
Exit
}
の1つの属性がLanElement
列挙型であることがわかりますSystem.Configuration.ConfigurationErrorsException
。列挙型アプリケーションで定義されていない構成で他の値を使用しようとすると、起動時にがスローされます。では、コレクションの定義に移りましょう
[ConfigurationCollection(typeof(LaneConfigElement), AddItemName = "Lane", CollectionType = ConfigurationElementCollectionType.BasicMap)]
public class LaneConfigCollection : ConfigurationElementCollection
{
public LaneConfigElement this[int index]
{
get { return (LaneConfigElement)BaseGet(index); }
set
{
if (BaseGet(index) != null)
{
BaseRemoveAt(index);
}
BaseAdd(index, value);
}
}
public void Add(LaneConfigElement serviceConfig)
{
BaseAdd(serviceConfig);
}
public void Clear()
{
BaseClear();
}
protected override ConfigurationElement CreateNewElement()
{
return new LaneConfigElement();
}
protected override object GetElementKey(ConfigurationElement element)
{
return ((LaneConfigElement)element).Id;
}
public void Remove(LaneConfigElement serviceConfig)
{
BaseRemove(serviceConfig.Id);
}
public void RemoveAt(int index)
{
BaseRemoveAt(index);
}
public void Remove(String name)
{
BaseRemove(name);
}
}
あなたは私が設定したことに気づくことができます AddItemName = "Lane"
コレクションエントリアイテムには、好きなように選択できるように。デフォルトの「add」を使用したいのですが、この投稿のために変更しました。
ネストされたすべての要素が実装されたので、実装する必要があるクラスの要素をすべて集約する必要があります System.Configuration.ConfigurationSection
CustomApplicationConfigSection
public class CustomApplicationConfigSection : System.Configuration.ConfigurationSection
{
private static readonly ILog log = LogManager.GetLogger(typeof(CustomApplicationConfigSection));
public const string SECTION_NAME = "CustomApplicationConfig";
[ConfigurationProperty("Credentials")]
public CredentialsConfigElement Credentials
{
get
{
return base["Credentials"] as CredentialsConfigElement;
}
}
[ConfigurationProperty("PrimaryAgent")]
public ServerInfoConfigElement PrimaryAgent
{
get
{
return base["PrimaryAgent"] as ServerInfoConfigElement;
}
}
[ConfigurationProperty("SecondaryAgent")]
public ServerInfoConfigElement SecondaryAgent
{
get
{
return base["SecondaryAgent"] as ServerInfoConfigElement;
}
}
[ConfigurationProperty("Site")]
public SiteConfigElement Site
{
get
{
return base["Site"] as SiteConfigElement;
}
}
[ConfigurationProperty("Lanes")]
public LaneConfigCollection Lanes
{
get { return base["Lanes"] as LaneConfigCollection; }
}
}
これで、名前PrimaryAgent
とSecondaryAgent
どちらも同じ型であることがわかります。これで、これらの2つの要素に対して実装クラスが1つしかなかった理由を簡単に理解できます。
app.config(またはweb.config)でこの新しく発明された構成セクションを使用する前に、独自の構成セクションを発明したことをアプリケーションに通知し、それを尊重する必要があります。そのためには、次の行を追加する必要があります。 app.config内(ルートタグの開始直後)
<configSections>
<section name="CustomApplicationConfig" type="MyNameSpace.CustomApplicationConfigSection, MyAssemblyName" />
</configSections>
注意: MyAssemblyNameには.dllを含めないでください。たとえば、アセンブリファイル名がmyDll.dllの場合、myDll.dllではなくmyDllを使用します。
この構成を取得するには、次のコード行をアプリケーションの任意の場所で使用します
CustomApplicationConfigSection config = System.Configuration.ConfigurationManager.GetSection(CustomApplicationConfigSection.SECTION_NAME) as CustomApplicationConfigSection;
上記の投稿が、少し複雑な種類のカスタム構成セクションから始めるのに役立つことを願っています。
ハッピーコーディング:)
****編集**** LINQを有効にLaneConfigCollection
するには、実装する必要がありますIEnumerable<LaneConfigElement>
次の実装を追加します GetEnumerator
public new IEnumerator<LaneConfigElement> GetEnumerator()
{
int count = base.Count;
for (int i = 0; i < count; i++)
{
yield return base.BaseGet(i) as LaneConfigElement;
}
}
収量が実際にどのように機能するかについてまだ混乱している人のために、この素晴らしい記事を読んでください
上記の記事から取られた2つの重要なポイントは
メソッドの実行が実際に終了するわけではありません。yield returnはメソッドの実行を一時停止し、次に(次の列挙値に対して)呼び出したときに、メソッドは最後のyield return呼び出しから実行を継続します。少しわかりにくいかもしれませんが…かもしれ(Shay Friedman)
Yieldは.Netランタイムの機能ではありません。これは、C#コンパイラによって単純なILコードにコンパイルされる単なるC#言語機能です。(ラースコーネリアッセン)