So-net無料ブログ作成

[.NET]カスタマイズした構成情報の利用(.NET1.1以前が対象) [Programming .NET Tips]

[ポイント]
(1)カスタム構成セクションとは?
  通常、アプリケーションの構成情報は、appSettingsノード配下の
  addノード(key属性とvalue属性)に記述するルールですが、
  独自のルール(独自のXMLタグ)で定義することもできます。
  この独自のXMLタグで定義された構成情報を、「カスタム構成セクション」と呼びます。
  「カスタム構成セクション」にアクセスする為には、
  プログラム上で「カスタム構成セクションハンドラ」クラスを実装し、
  構成ファイルに「カスタム構成セクションハンドラ」を追加する必要があります。
(2)カスタム構成セクションハンドラとは?
  カスタム構成セクションにアクセスする為には、
  その独自のXMLタグを解析する必要があります。
  その独自のXMLタグを解析するクラスを、「カスタム構成セクションハンドラ」と呼びます。
  カスタム構成セクションハンドラは、以下の(a)(b)の条件に従って実装する必要があります。
   (a)System.Configuration.IConfigurationSectionHandlerインタフェースを実装する。
   (b)IConfigurationSectionHandlerインタフェースのCreateメソッドに、
     カスタム構成セクションを解析する処理を実装する。
(3)カスタム構成セクションハンドラが、カスタム構成セクションにアクセスするには?
  カスタム構成セクションハンドラがカスタムセクションにアクセスする為には、
  構成ファイルに、構成セクションハンドラを追加する必要があります。
  追加することにより、カスタム構成セクションハンドラとカスタムセクションの対応付けを
  定義したことになります。
(4)利用可能な.NET Frameworkのバージョンは?
  本記事のサンプルは、.NET1.1以前で主流だった方法です。
  .NET2.0以降では、「ConfigurationSection」クラスを使用する方法が
  推奨されています。(.NET2.0以降でも使用可能)
(5))参考文献
  ・『MSDN Library for VisualStudio2008日本語版』
  ・『MCTSスキルチェック問題集70-536 .NET Framework2.0アプリケーション構築基礎』

カスタム構成セクションにアクセスする例を、以下の(1)~(4)に分けて示します。
(1)カスタム構成セクションの定義
  例として、日本の地域と県、県と県庁所在地の対応を定義しています。
[ソース]
<configuration>
  <myCustomGroup>
    <Country Name="Japan">
      <Area Name="Kanto">
        <Prefecture Name="Tokyo" MajorCity="Tokyo"/>
        <Prefecture Name="Kanagawa" MajorCity="Yokohama"/>
        <Prefecture Name="Ibaragi" MajorCity="Mito"/>
      </Area>
      <Area Name="Chubu">
        <Prefecture Name="Aichi" MajorCity="Nagoya"/>
        <Prefecture Name="Gifu" MajorCity="Gifu"/>
        <Prefecture Name="Mie" MajorCity="Tsu"/>
      </Area>
    </Country>
  </myCustomGroup>
        (以下省略)
          :
例:カスタム構成セクションの定義

(2)カスタム構成セクションハンドラの実装
  System.Configuration.IConfigurationSectionHandlerインタフェースを
  実装したクラスを定義します。
  System.Configuration.IConfigurationSectionHandlerインタフェースの
  Createメソッドに、カスタム構成セクションのアクセス処理を実装します。
  この例では、カスタム構成セクションから、県と県庁所在地の一覧を取得し、
  HashTableに格納しています。
[ソース]
''' <summary>
''' カスタム構成セクションハンドラ
''' ※.NET1.1以前で使用可能。
'''  .NET2.0以降ではSystem.Configuration.ConfigurationSectionクラスを推奨
''' </summary>
''' <remarks></remarks>
Public Class MyCustomConfigHandler1_1
    Implements System.Configuration.IConfigurationSectionHandler

    ''' <summary>
    ''' 構成セクションハンドラを作成する。
    ''' </summary>
    ''' <param name="parent">親オブジェクト</param>
    ''' <param name="configContext">構成コンテキストオブジェクト</param>
    ''' <param name="section">セクションXMLノード</param>
    ''' <returns>作成されたセクションハンドラオブジェクト</returns>
    ''' <remarks></remarks>
    Public Function Create( _
        ByVal parent As Object, _
        ByVal configContext As Object, _
        ByVal section As System.Xml.XmlNode) As Object _
        Implements _
        System.Configuration.IConfigurationSectionHandler.Create

        Dim configTable As New Hashtable()

        For Each areaNode As XmlNode In section.ChildNodes
            For Each prefNode As XmlNode In areaNode.ChildNodes
                configTable.Add( _
                    prefNode.Attributes("Name").Value, _
                    prefNode.Attributes("MajorCity").Value)
            Next
        Next

        Return configTable

    End Function
End Class
[VB.NET]例:カスタム構成セクションハンドラの実装

(3)構成ファイルにカスタム構成セクションハンドラの追加
  「myCustomGroup」、「Country」の対応付けを定義し、
  更に「Country」のセクションハンドラを定義しています。
  type属性には、カスタム構成セクションハンドラのアセンブリ修飾名を指定します。
  アセンブリ修飾名については、
  MessageBox.Show( _
   New MyCustomConfigHandler1_1().GetType().AssemblyQualifiedName)
  で確認できます。
[ソース]
<configuration>
  <configSections>
    <sectionGroup name="myCustomGroup" >
      <section 
        name="Country" 
        type="CustomConfig.MyCustomConfigHandler1_1, 
              CustomConfig, 
              Version=1.0.0.0, 
              Culture=neutral, 
              PublicKeyToken=null"/>
    </sectionGroup>
  </configSections>
        (以下省略)
          :
例:カスタム構成セクションハンドラの追加

(4)構成情報の取得
  以下に、カスタム構成セクションハンドラを使用して構成情報を取得する例を示します。
  取得には、System.Configuration.ConfigurationSettingsクラスの
  GetConfigメソッドを使用します。(※.NET2.0以降では警告がでます。)
  GetConfigの引数には、起点となるカスタム構成セクションのノード名を指定します。
[ソース]
Private Sub Button1_Click(ByVal sender As System.ObjectByVal e As System.EventArgs) Handles Button1.Click

    Dim rtn As Object = Nothing
    Dim configTable As Hashtable = Nothing

    '「myCustomGroup/Country」のXMLノードを起点とし、
    '構成情報を取得する。
    rtn = System.Configuration.ConfigurationSettings.GetConfig( _
        "myCustomGroup/Country")
    configTable = CType(rtn, Hashtable)

    '取得した構成情報をメッセージボックスに表示
    Dim sb As New StringBuilder()
    For Each k As String In configTable.Keys
        sb.Append(k & ":" & configTable(k).ToString() & vbCrLf)
    Next
    MessageBox.Show(sb.ToString())

End Sub
[VB.NET]例:カスタム構成セクションハンドラを使用して構成情報を取得する

[Algo]組合せの数(nCm)の算出 [Programming Algorithm]

[はじめに]
・n個の中からm個を選ぶ組合せの数(nm)を算出するプログラムです。
 例:a、b、cの3個の中から2個を選ぶ組合せは、
   ab、ac、bcの3通りであり、その数を数学的表記で『32』と表現します。
 .NETのクラスライブラリには算出するメソッドがないようなので作ってみました。
nmを算出する公式はいくつかありますが、
 代表的な公式と各々の特徴について、以下にまとめます。
・参考文献
 『Javaによるはじめてのアルゴリズム入門』

以下に、算出方法に対するプログラム例を示します。
(1)階乗による算出
 公式nm=n!/{m!×(n-m)!}
/// <summary>
/// 異なるn個のものからm個を選ぶ
/// 組み合わせの総数 nCmを取得する。
/// </summary>
/// <param name="n">n</param>
/// <param name="m">m</param>
/// <returns>nCm</returns>
public static decimal CalcComb01(decimal n, decimal m)
{
    //nCm = nCm-1 ×(n-m+1)/ m 
    return CalcFact(n) / (CalcFact(m) * CalcFact(n - m));
}

/// <summary>
/// 階乗を計算する。
/// </summary>
/// <param name="n">n</param>
/// <returns>nの階乗(n!)</returns>
public static decimal CalcFact(decimal n)
{
    if (n <= 0m) {
        return 1m;
    }
        
    return n * CalcFact(n - 1);
}
[C#][階乗による算出]
異なるn個のものからm個を選ぶ組み合わせの総数nmを取得する。

(2)漸化式による算出
 一般的に、漸化式の計算は再帰処理で実装できます。
 公式
 (i)m=0の場合
  nm=1
 (ii)m>0の場合
  nmnm-1×(n-m+1)/m
/// <summary>
/// 異なるn個のものからm個を選ぶ
/// 組み合わせの総数 nCmを取得する。
/// </summary>
/// <param name="n">n</param>
/// <param name="m">m</param>
/// <returns>nCm</returns>
public static decimal CalcComb02(decimal n, decimal m)
{
    //以下の漸化式に従って、再帰により算出する。

    //(1)m=0の場合、
    //      nCm = 1
    if (m == 0)
    {
        return 1;
    }

    //(2)m≠0の場合、
    //      nCm = nCm-1 ×(n-m+1)/ m 
    return CalcComb02(n, m - 1) * (n - m + 1) / m;

}
[C#][漸化式による算出]
異なるn個のものからm個を選ぶ組み合わせの総数nmを取得する。

(3)Π(パイ)による算出
 「(2)漸化式による算出」の公式は、
 総乗(掛け算を集約したもの)と解釈できるので、
 以下の公式でも表現できます。
 公式nm=Π{(n-k+1)/k} (※1≦k≦M)
/// <summary>
/// 異なるn個のものからm個を選ぶ
/// 組み合わせの総数 nCmを取得する。
/// </summary>
/// <param name="n">n</param>
/// <param name="m">m</param>
/// <returns>nCm</returns>
public static decimal CalcComb03(decimal n, decimal m)
{
    //組合せ(nCm)を、
    //以下の公式に従って、ループにより算出する。
    //         m
    // nCm = Π {(n-k+1)/ k }
    //         k=1

    decimal product = 1;

    for(decimal k = 1 ; k <= m ; k++)
    {
        product = product * (n - k + 1) / k;
    }

    return product;

}
[C#][Π(パイ)による算出]
異なるn個のものからm個を選ぶ組み合わせの総数nmを取得する。