故郷を離れて三十数年、関東で暮らす永遠の少年のどーってことない日記
xxSEARCHxx
プロフィール

ST☆FF

Author:ST☆FF
HTTといえばインテルの Hyper-Threading Technology!・・・ではなく、放課後ティータイムのことだと思います。

最近の記事
最近のコメント
最近のトラックバック
月別アーカイブ
カテゴリー
ブロとも申請フォーム
ブログ内検索
RSSフィード
リンク

最近の記事


スポンサーサイト 

--/--/-- --:--/--
上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

CATEGORY:スポンサー広告 | CM(-) | TB(-) |

アプリケーション構成ファイルとの格闘 

2012/03/21 22:49/Wed
バッチ系のアプリケーションでは監視処理というのが結構あるものです。
例えば、NASの特定ディレクトリを数秒間隔で監視して、特定の条件を満たすファイルが到着したら何らかの処理を行う、
といった具合です。或いは、実際の処理は非常に重く複雑なため、専用サーバ上でアプリケーションが稼働しており、
そのサーバの入力ディレクトリへ前処理したファイルを転送する、などという場合もあるでしょう。
さらに、こういった仕組みが各地のセンターに存在し、負荷に応じてセンター毎に異なる台数の複数サーバで分散処理を
行っているとしたら、この監視アプリケーションはどの様にデザインすべきなのでしょう。

・監視ディレクトリ
・転送ディレクトリ
・ソケット通信IPアドレス/ポート番号

たとえば上のような情報が必要だった場合、ただひと組だけの構成なら、シンプルに app.config に各項目を設定しておき、
起動時に読み込んでタイマーイベント内で使用するだけで問題ありません。
ところが、このセットが複数あって、しかも数もまちまちとなると、動的にセット数分のスレッドを作成することが必要に
なってきます。しかもいちいちセンター毎に実行モジュールをビルドする必要が無いように、実行モジュールを環境と切り離す
必要があります。つまり、どのセンターにも同じ実行モジュールを配布するだけで動くようにしたいわけです。
こうなるとやはり、環境定義で対応するしかないようです。しかも環境定義ファイルがこれ以上増えないように、現在使用して
いる app.config でその要件を満たさなければなりません。

実は、最近ちょうどそのような場面に遭遇しましたが、アプリケーション構成ファイルに習熟していなかったので 結構悩みました。
色々調べた結果、ユーザー定義セクションに可変個数のパラメータを列挙する方法が最も整然としていたので作成してみました。

まず app.config はこのようなイメージにしました。

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<!-- このセクションでは、サーバーのフォルダ構成等を定義します。 -->
<section name="MyServerSettings" type="MyRoot.NameSpace.SettingsSection, MyAssemblyName" />
<sectionGroup name="userSettings" type="System.Configuration.UserSettingsGroup, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=****************" >
<section name="MyRoot.NameSpace.My.MySettings" type="System.Configuration.ClientSettingsSection, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=****************" allowExeDefinition="MachineToLocalUser" requirePermission="false" />
</sectionGroup>
</configSections>
<system.diagnostics>
<sources>
<!-- このセクションでは、My.Application.Log のログ構成を定義します。 -->
<source name="DefaultSource" switchName="DefaultSwitch">
<listeners>
<add name="FileLog"/>
<!-- アプリケーション イベント ログに書き込むには、以下のセクションのコメントを解除します -->
<!--<add name="EventLog"/>-->
</listeners>
</source>
</sources>
<switches>
<add name="DefaultSwitch" value="Information" />
</switches>
<sharedListeners>
<add name="FileLog"
type="Microsoft.VisualBasic.Logging.FileLogTraceListener, Microsoft.VisualBasic, Version=8.0.0.0, Culture=neutral, PublicKeyToken=****************, processorArchitecture=MSIL"
initializeData="FileLogWriter"/>
<!-- アプリケーション イベント ログに書き込むには、以下のセクションのコメントを解除して、APPLICATION_NAME をアプリケーション名に置き換えます -->
<!--<add name="EventLog" type="System.Diagnostics.EventLogTraceListener" initializeData="APPLICATION_NAME"/> -->
</sharedListeners>
</system.diagnostics>
<!-- サーバー用設定 -->
<MyServerSettings>
<InputWorkFolder>
<param name="setsubi1" value="\\sv01\shares\nas\Dir1_Income" />
<param name="setsubi2" value="\\sv01\shares\nas\Dir2_Income" />
</InputWorkFolder>
<InputHotFolder>
<param name="setsubi1" value="\\sv02\Dir1_Hot" />
<param name="setsubi2" value="\\sv02\Dir2_Hot" />
</InputHotFolder>
<HostName>
<param name="setsubi1" value="192.168.1.1" />
<param name="setsubi2" value="192.168.1.2" />
</HostName>
<PortNo>
<param name="setsubi1" value="66000" />
<param name="setsubi2" value="67000" />
</PortNo>
</MyServerSettings>
<userSettings>
<MyRoot.NameSpace.My.MySettings>
</MyRoot.NameSpace.My.MySettings>
</userSettings>
</configuration>

次にユーザー定義セクション読込クラスです。

Imports System.Configuration

''' <summary>
''' CustomSettingsSection.vb
''' .configファイルのユーザー定義セクション読込み
''' </summary>
''' <remarks>
''' <remarks></remarks>
Public Class SettingsSection
Inherits ConfigurationSection

''' <summary>
''' InputWorkFolder要素を取得
''' </summary>
''' <value></value>
''' <returns></returns>
''' <remarks></remarks>
<ConfigurationProperty("InputWorkFolder")> _
Public Overridable ReadOnly Property InputWorkFolder() As CommonParamElement
Get
Return CType(Me("InputWorkFolder"), CommonParamElement)
End Get
End Property

''' <summary>
''' InputHotFolder要素を取得
''' </summary>
''' <value></value>
''' <returns></returns>
''' <remarks></remarks>
<ConfigurationProperty("InputHotFolder")> _
Public Overridable ReadOnly Property InputHotFolder() As CommonParamElement
Get
Return CType(Me("InputHotFolder"), CommonParamElement)
End Get
End Property

''' <summary>
''' HostName要素を取得
''' </summary>
''' <value></value>
''' <returns></returns>
''' <remarks></remarks>
<ConfigurationProperty("HostName")> _
Public Overridable ReadOnly Property HostName() As CommonParamElement
Get
Return CType(Me("HostName"), CommonParamElement)
End Get
End Property

''' <summary>
''' PortNo要素を取得
''' </summary>
''' <value></value>
''' <returns></returns>
''' <remarks></remarks>
<ConfigurationProperty("PortNo")> _
Public Overridable ReadOnly Property PortNo() As CommonParamElement
Get
Return CType(Me("PortNo"), CommonParamElement)
End Get
End Property
End Class

そして、ユーザー定義エレメント読込クラスです。

Imports System.Configuration

''' <summary>
''' ParamElementCollection.vb
''' .configファイルのユーザー定義エレメント読込み
''' </summary>
''' <remarks>
''' <remarks></remarks>
Public Class ParamElement
Inherits ConfigurationElement

''' <summary>
''' name属性を取得
''' </summary>
''' <value></value>
''' <returns></returns>
''' <remarks></remarks>
<ConfigurationProperty("name", IsKey:=True, IsRequired:=True)> _
Public Overridable ReadOnly Property Name() As String
Get
Return CType(Me("name"), String)
End Get
End Property

''' <summary>
''' value属性を取得
''' </summary>
''' <value></value>
''' <returns></returns>
''' <remarks></remarks>
<ConfigurationProperty("value", IsRequired:=True)> _
Public Overridable ReadOnly Property Value() As String
Get
Return CType(Me("value"), String)
End Get
End Property
End Class

Public Class ParamElementCollection
Inherits ConfigurationElementCollection

''' <summary>
''' コンストラクタ
''' </summary>
''' <remarks></remarks>
Public Sub New()
AddElementName = "param"
End Sub

''' <summary>
''' 指定したインデックスの要素を取得
''' </summary>
''' <param name="index"></param>
''' <value></value>
''' <returns></returns>
''' <remarks></remarks>
Public ReadOnly Property getElement(ByVal index As Integer) As ParamElement
Get
Return CType(BaseGet(index), ParamElement)
End Get
End Property

''' <summary>
''' 指定したnameの要素を取得
''' </summary>
''' <param name="name"></param>
''' <value></value>
''' <returns></returns>
''' <remarks></remarks>
Public ReadOnly Property getElement(ByVal name As String) As ParamElement
Get
Return CType(BaseGet(name), ParamElement)
End Get
End Property
''' <summary>
''' 指定したnameに一致する要素の有無を取得
''' </summary>
''' <param name="name"></param>
''' <returns></returns>
''' <remarks></remarks>
Public Function Contains(ByVal name As String) As Boolean
Return BaseGet(name) IsNot Nothing
End Function

''' <summary>
''' (新たに生成したParamElementオブジェクトを返す)
''' </summary>
''' <returns></returns>
''' <remarks></remarks>
Protected Overloads Overrides Function CreateNewElement() As System.Configuration.ConfigurationElement
Return New ParamElement()
End Function

''' <summary>
''' (要素決定となるkey値を返す)
''' </summary>
''' <param name="element"></param>
''' <returns></returns>
''' <remarks></remarks>
Protected Overrides Function GetElementKey(ByVal element As System.Configuration.ConfigurationElement) As Object
Return (CType(element, ParamElement)).Name
End Function
End Class

最後に、エレメント内の要素読込クラスです。

Imports System.Configuration

''' <summary>
''' CustomSettingsParamElement.vb
''' .configファイルのユーザー定義セクション読込み
''' </summary>
''' <remarks></remarks>
Public Class CommonParamElement
Inherits ConfigurationElement

''' <summary>
''' param要素(複数存在)を取得(共通)
''' </summary>
''' <value></value>
''' <returns></returns>
''' <remarks></remarks>
<ConfigurationProperty("", IsDefaultCollection:=True)> _
Public Overridable ReadOnly Property ParamCollection() As ParamElementCollection
Get
Return CType(Me(""), ParamElementCollection)
End Get
End Property
End Class

実際の読み出し方は次のようになります。

Imports System.Configuration

Public Class Form1
''' <summary>
''' サーバー情報セット
''' </summary>
''' <remarks></remarks>
Public Structure ServerInfo
Dim InputWorkFolder As String
Dim InputHotFolder As String
Dim HostName As String
Dim PortNo As String

''' <summary>
''' コンストラクタ
''' </summary>
''' <param name="argWork"></param>
''' <param name="argHot"></param>
''' <param name="argHost"></param>
''' <param name="argPort"></param>
''' <remarks></remarks>
Public Sub New(ByVal argWork As String, _
ByVal argHot As String, _
ByVal argHost As String, _
ByVal argPort As String)
InputWorkFolder = argWork
InputHotFolder = argHot
HostName = argHost
PortNo = argPort
End Sub
End Structure

''' <summary>
''' アプリケーション構成ファイルの
''' ユーザ定義セクションを参照するサンプル
''' </summary>
''' <param name="sender"></param>
''' <param name="e"></param>
''' <remarks></remarks>
Private Sub Button1_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button1.Click

' 実行体ファイル名を取得
Dim exeFileName As String = _
System.Reflection.Assembly.GetExecutingAssembly().Location
exeFileName = System.IO.Path.GetFileName(exeFileName)

' アプリケーション構成ファイルをマッピング
Dim filemap As ExeConfigurationFileMap = New ExeConfigurationFileMap()
filemap.ExeConfigFilename = _
IO.Path.Combine(System.IO.Directory.GetCurrentDirectory(), exeFileName + ".config")

' MyServerSettingsセクションにアクセス
Dim config As Configuration = _
ConfigurationManager.OpenMappedExeConfiguration(filemap, ConfigurationUserLevel.None)
Dim settings As SettingsSection = CType(config.GetSection("MyServerSettings"), SettingsSection)

' リストに格納
Dim siList As New Generic.List(Of ServerInfo)
For i As Integer = 0 To settings.InputWorkFolder.ParamCollection.Count - 1
siList.Add(New ServerInfo( _
settings.InputWorkFolder.ParamCollection.getElement(i).Value, _
settings.InputHotFolder.ParamCollection.getElement(i).Value, _
settings.HostName.ParamCollection.getElement(i).Value, _
settings.PortNo.ParamCollection.getElement(i).Value))
Next
・・・

アプリケーション構成ファイルとの格闘2
スポンサーサイト

CATEGORY:仕事関係 | CM(0) | TB(0) |
xx HOME xx
トラックバックURL
→http://3335.blog106.fc2.com/tb.php/165-dfc51f90

コメントの投稿














xx HOME xx

上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。