2011年08月25日

アプリケーションの設定情報の扱いについて考えてみる(6)

   このエントリーをはてなブックマークに追加 Clip to Evernote
このシリーズの最後として、構成ファイルに何らかのコレクションを保持させる方法について考えてみたいと思います。
第5回で扱った、ConfigurationSection を使います。
そのほか使うクラスは、

System.Configuration.ConfigurationElementCollection
System.Configuration.ConfigurationElement

の2つのクラスです。
ConfigurationElementCollection クラスは、構成ファイル内の要素のコレクションを表します。
この時のコレクションの要素が、ConfigurationElement クラスとなります。
実際には、これらのクラスから独自のクラスを派生させることになります。

今回は、アプリケーションのどの機能が何時呼び出されたかを構成ファイルに記録するという例を考えます。

まず、コレクションの要素である FunctionInfoクラスから定義します。
このクラスは、ConfigurationElementから派生させます。


Keyには、機能番号を、Valueには、日付時刻を格納することとします。
ConfigurationElement がコレクションの要素の場合には、
要素を一意に特定するキーを示すプロパティには、IsKey=true を指定するようにします。
ここでは、Key, Value という名前を使いましたが、この名前にこだわる必要はありません。
また、ここでは2つのプロパティとしましたが、3つ以上のプロパティでも問題ありません。

つぎに、このFunctionInfo要素を持つ、コレクションクラスを定義します。
このコレクションクラスは、ConfigurationElementCollectionから派生させます。

派生するには、最低限、CreateNewElement、GetElementKey の2つのメソッドをoverrideします。

ただ、これだけだと、コレクションからの要素の取得、追加、削除、列挙などができないので、
必要なメソッドを要求に合わせて作り込みます。


そして、最後に、このコレクションを持つ、ConfigurationSection クラスを実装します。
ここでは、functions という名前のXMLタグの中に、コレクションを保持するようにしました。
前回同様、GetSectionというstaticメソッドと、Saveメソッドを用意しました。

これで、必要なクラスを定義できました。
configファイルは、初期状態として、以下のようなものを用意します。


これで準備完了です。

以下は、使い方の簡単なサンプルです。


実行後のconfigファイルの例です。


  

Posted by gushwell at 22:08Comments(0)TrackBack(0)

2011年08月15日

アプリケーションの設定情報の扱いについて考えてみる(5)

   このエントリーをはてなブックマークに追加 Clip to Evernote
前回説明したように、ApplicationSettingsBase では、
「ユーザ単位ではなく、アプリケーションで一つの設定情報を扱い、かつ、読み書きを可能にしたい」
という要求には独自のプロバイダーを記述する必要があります。
これ結構面倒です。

それならば、ConfigurationSection クラスという別のクラスを利用したほうが
簡単に要求に答えられそうです。

ということで、ConfigurationSection クラスを使い、ウィンドウの位置とサイズを扱うサンプルを
書いてみました。以下にそのコードを示します。


※ System.Configuration を参照に追加します。

クラス WindowInfoは、ConfigurationSection クラスから派生させています。
ApplicationSettingsBase から派生させたクラスと良く似ていますね。
大きく異なる点は、Load staticメソッドがある点です。
このメソッドは、設定ファイルを読み込むメソッドですが、標準の App.configではなく、
別ファイルとして、configファイルを扱えるようにようにしてます。
ここでは、"windowInfo.app.config" としています。

Saveメソッドは、インスタンスメソッドです。configファイルへの保存は、Configurationクラスの
Saveメソッドを呼び出すだけです。自分で保存ロジックを記述する必要はありません。

"windowInfo.app.config"の中身は、以下のようになります。
属性として値が保持されるので、ApplicationSettingsBase よりは、読みやすいですね。

なお、"windowInfo.app.config" は事前に用意しておく必要があります。
windowInfo要素は無くてもかまいません。存在しない場合は、DefaultValueで指定した
値が、セットされます。

最後に、利用する側のコード例を示します。



なお、ApplicationSettingsBaseとは異なり、バージョン管理を行いたいという場合には、 自分ですべて実装する必要があるようです。 一長一短がありますので、要求によって使い分ける必要がありますね。   
Posted by gushwell at 23:00Comments(0)TrackBack(0)

2011年07月26日

アプリケーションの設定情報の扱いについて考えてみる(4)

   このエントリーをはてなブックマークに追加 Clip to Evernote
「アプリケーションの設定情報の扱いについて考えてみる」の4回目です。

■ ApplicationScopedSettingAttribute

[UserScopedSetting] の代わりに、[ApplicationScopedSetting]属性を付加すると、 ユーザ単位ではなく、
アプリケーションでひとつの(つまり、すべてのユーザーに対して共通の) 値を持つことができます。

しかし、この属性を付けた場合は、デフォルトの動作(LocalFileSettingsProviderの動作)では、読み取り専用となります。
値を変更し保存することができません。

この読み取り専用の設定情報は、app.config に記述することになります。
以下に、その例を示します。


なお、これを書きこみ可能とするには、System.Configuration.SettingsProvider を継承した独自のプロバイダークラスを
作成する必要がありますが、この作成方法については、省略します。
興味あるかたは、MSDN等で調べてください。
  
Posted by gushwell at 23:00Comments(0)TrackBack(0)

2011年07月24日

アプリケーションの設定情報の扱いについて考えてみる(3)

   このエントリーをはてなブックマークに追加 Clip to Evernote
「アプリケーションの設定情報の扱いについて考えてみる」 の3回目です。

■ バージョンアップ時に前バージョンの情報を引き継ぐ

アセンブリのバージョンが上がったときは、configファイルの保存場所が変更されることは前回説明しました。
これは何を意味するかというと、そのままでは、前バージョンの設定情報を取得することができないということです。
Windowsのサイズと位置程度ならば、初期状態に戻ってしまってもかまわないかもしれませんが、設定情報を引き継ぎたいということは、良くあることです。
この目的のために、ApplicationSettingsBase には、Upgradeというメソッドが用意されています。

しかし、何を基準にUpgradeを呼び出したら良いのかを判断する方法が用意されていないようです。
※ 調べましたが、見つけることができませんでした。

そのため、自前でバージョンが変更されたかどうかを判断するコードを書く必要があります。

ここでは、IsUpgraded というプロパティを WindowInfoに追加することで対応します。


このプロパティを使った、設定情報の読み込みを以下に示します。


これで、設定情報の引継ぎが可能になります。

2011/8/9 追記
IsUpgradedプロパティのコードが間違っていましたので、訂正しました。
  
Posted by gushwell at 21:00Comments(2)TrackBack(0)

2011年07月18日

アプリケーションの設定情報の扱いについて考えてみる(2)

   このエントリーをはてなブックマークに追加 Clip to Evernote
前回の続き

前回は、ApplicationSettingsBase クラスを継承した簡単なクラス定義例をお見せしました。
今回は、「デフォルト値の設定」と「保存場所とその形式」について簡単に解説します。

■ デフォルト値を設定する。

デフォルト値を設定するには、NullReferenceException 例外をキャッチし、そこで、値を設定する方法と、
属性でデフォルト値を設定する方法の2通りがあります。

属性でデフォルト値を設定するには、DefaultSettingValueAttribute 属性を指定します。

前回示したWindowInfoクラスを例に、そのコードを示します。


このようにすれば、設定ファイルが存在しない場合にも例外は発生しませんので、try-catchは不要になります。


■どこに保存されるのか

exeファイルが存在するフォルダをみても、それらしいファイルは存在していません。
では、どこに保存されているのかというと、Windows7では、


といった場所に保存されます。
アセンブリにCompanyNameが設定されていない場合は、exe名が CompanyNameになります。

1.0.0.0 は、アセンブリのバージョンを示します。
製品バージョンやファイルバージョンではなく、アセンブリのバージョンです。
アセンブリのバージョンが変わると、保存場所も変わります。
ビルド番号やリビジョン番号が変わっても保存場所は変わります。


■ 構成ファイルの形式

構成ファイルのサンプルを示します。

  
Posted by gushwell at 22:30Comments(0)TrackBack(0)

2011年07月10日

アプリケーションの設定情報の扱いについて考えてみる(1)

   このエントリーをはてなブックマークに追加 Clip to Evernote
■はじめに

アプリケーション独自の設定情報を扱いたい、そんな要求に答えるには、太古の昔は、INIファイルが定番でしたが、
いつしか、レジストリが主流になり、そして.NETでは、XML形式のconfigファイルへと移ってきました。

configファイルにアプリケーション独自の情報を設定するのに、もっとも手軽なのが、App.config の
要素を使う方法です。
ただ、これは、
・全てを文字列として扱う必要がある。
・項目を一つ一つ指定してアクセスする必要がある
など、柔軟性に欠ける部分があります。

そして、さらに問題となるのが、書き込みをしたいという要求にうまく対応できないということです。

そこで、数回にわけて、設定ファイルの読み書きについて考えてみます。

まずは、.NET Frameworkでそのために用意されていると思われるApplicationSettingsBaseクラス を使い、
アプリケーション独自の設定情報の読み書きについて考えてみます。

■ApplicationSettingsBaseクラスを利用した設定ファイルの読み書き

例えば、ウインドウのサイズと位置を保存しておきたいとしましょう。
当然、これらの値はひとつのクラスとして扱いたいですね。
例えば、


というクラスを考えてみます。
このクラスを 設定ファイルに保存できるようにするには、ApplicationSettingsBase から継承し、
以下のように書き換えてやる必要があります。


随分コードが増えてしまいましたが、パターン化されていますので、 機械的にコーディングできると思います。

このクラス定義ができれば、あとは読み書きのコードを書くだけです。


読み込みは、WindowInfo のオブジェクトを生成し、プロパティにアクセスするだけです。
なお、このプログラムを最初に起動した場合は、値を読み込むことが出来ないために、
NullReferenceException 例外が発生します。この例外が出たときには、何もせずにデザイン時の値を
そのまま使います。
書き込みは、WindowsInfoの各プロパティに値を設定し、Saveメソッドを呼び出します。

なお、WindowsFormsでは、フォームデザイナーのプロパティ画面で、(ApplicationSettings) で
保存したいプロパティを設定すれば、いちいち上記のようなコードを書く必要はありません。
あくまでも、サンプルとして見てください。

実際、自動生成される Settings.Designer.cs を見てみると、ApplicationSettingsBase クラスを継承したクラスが
定義されています。

もちろん、フォームやGUIコントロールのプロパティ以外の値を設定するには、デザイナーでのサポートは
ありませんので、ApplicationSettingsBaseクラスを利用するなら、ここに書いた方法で値を設定することになります。

(続く...)

追記 (2011/07/11)
最後の文は、ちょっと語弊がある文章でした。
C#プロジェクトの Properties フォルダの、Settings.settingsを開いて表示されるデザイナー(これもデザイナー
の一種ですね)で独自の情報を格納することができます。

ただ、このシリーズでは、Settings.settingsを開いて表示される設定デザイナーを利用する方法については、割愛します。

ApplicationSettingsBase を直接使ってみることで、Settings.settingsで作成する 設定ファイルクラスを
より理解できるようになります。

  
Posted by gushwell at 22:38Comments(0)TrackBack(0)

2007年03月01日

OpenMappedExeConfiguration

   このエントリーをはてなブックマークに追加 Clip to Evernote
先日、C#で、ConfigurationManager.OpenExeConfiguration を使い、デフォルト以外の構成ファイルを見に行く方法について書いたが、ConfigurationManager.OpenMappedExeConfiguration を使う方法もある。

ExeConfigurationFileMap map = new ExeConfigurationFileMap();
map.ExeConfigFilename = @"C:\Gushwell\sample.dll.config";
Configuration config = ConfigurationManager.OpenMappedExeConfiguration(map,
ConfigurationUserLevel.None);

とすれば、直接、構成ファイルを指定できる。
これを使えば、拡張子 .config に限定されないので、.xml といったファイルも扱える。
でも、わざわざ拡張子を .config 以外にする理由は思いつかないけどね。  
Posted by gushwell at 21:31Comments(0)TrackBack(0)

2007年02月27日

ConfigurationManagerクラスのOpenExeConfigurationでの間違い

   このエントリーをはてなブックマークに追加 Clip to Evernote
C#で、デフォルトの exe.config とは異なる構成ファイルをオープンしようと思い、

System.Configuration.Configuration config = 
ConfigurationManager.OpenExeConfiguration(@"C:\Gushwell\sample.dll.config");

target = config.GetSection(sectionName) as MySection;

と書いてみたら、target が nullになってしまう。
configインスタンスは生成されているのに、おかしいなと思って、調べてみたら、config.FilePath プロパティが、@"C:\Gushwell\sample.dll.config.config" だった。

なんで、勝手に .config を付加するんだ! と思ったが、まあ、名前が、OpenExeConfiguration だから、しかたないか。

これは、単に、
@"C:\Gushwell\sample.dll"
とすればいいみたいだ。

ちなみに、おぎわら さんのページ
http://blogs.wankuma.com/ogiogi/archive/2006/07/28/34042.aspx
でも、おなじようなことが書いてあった...

ただ、現象的に異なるのは、おぎわらさんのページによると、
ConfigurationManager.OpenExeConfiguration()
の戻り値が null になっているということ。これは、おぎわらさんの勘違いだと思うけど...
  
Posted by gushwell at 23:15Comments(0)TrackBack(0)