技術情報

IT技術情報をここにメモします。有用な情報を迅速に記録し、どこからでも引き出し、広く一般に共有することを目的とする。ソースコードも出し惜しみしないで無償公開します。

Viva オープンソース!

Amebaでブログを始めよう!

C#最速スタート (2)統一されたメッセージボックス

■概要

メッセージボックスは頻繁に用いられます。しかしメッセージボックスを表示するたびに、

プログラマーに「タイトル」や「アイコン」の選択をまかせていては、

メッセージボックスの外観を統一することができません。

また、メッセージボックスの外観をプログラマの資質に依存したくはありません。


そこでMessageBoxのShowメソッドをラップするメソッドを実装したクラスを作ります。

これによりログレベルや出力内容に応じた外観のメッセージボックスを強制的に出力させ、

メッセージボックスの外観をプログラム内で統一します。


■注意事項

(1)namespaceの「Sample」を適宜置換すること。

(2)log4netを事前に実装すること。

(3)"PROJECT"にプロジェクト名を設定すること。


■使い方

下記のソースをプロジェクト内に「MessageBoxUtil.cs」として保存してください。

定義されたStaticメソッドを使用できます。


■備考

メッセージボックスの出力レベル

(1)FATAL

致命的エラーが発生し、プログラムの続行が不可能な場合に表示する。

例:設定ファイルが読めない、DBにアクセスできない、など


(2)Error

通常のエラー。何らかの異常が発生しているが、プログラムの続行は可能。

例:一部の機能に制限がかかる、など


(3)Warn

警告。異常ではないが、プログラムが正常とは異なる動きを示し、

ユーザにそれを通知する必要がある場合。

例:ファイル容量が満杯に近づいている、など


(4)Info

ただの情報。異常は発生していない。プログラムは正常に動作している。

その上でユーザに何か情報を伝えたい場合。

例:データベースにデータをセーブする処理が完了した、など



■ソースコード


using System;
using System.Windows.Forms;
using log4net;

//----------------------------------------------------------------------------80

namespace DBAccess
{
/// <summary>
/// 各種メッセージボックスを表示する。
/// </summary>
public class MessageBoxUtil
{
/// <summary>
/// ログ出力用インスタンスを作成する。
/// </summary>
private static readonly log4net.ILog logger
= log4net.LogManager.GetLogger(
System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);

/// <summary>
/// メッセージボックスに表示するプロジェクト名。
/// </summary>
private static readonly string PROJECT = "プロジェクト名";

/// <summary>
/// コンストラクタ
/// </summary>
public MessageBoxUtil()
{
}

/// <summary>
/// アプリケーションエラーのエラーメッセージを表示する。
/// </summary>
/// <param name="ex">エラーオブジェクト</param>
public static void Fatal(Exception ex)
{
string method = System.Reflection.MethodBase.GetCurrentMethod().Name;
logger.Debug("Entering");

MessageBox.Show(ex.Message, PROJECT + " アプリケーションエラー"
, MessageBoxButtons.OK
, MessageBoxIcon.Error);
logger.Fatal("「" + ex.Message + "」を表示しました。");

logger.Debug("Exiting");
}

/// <summary>
/// アプリケーションエラーのエラーメッセージを表示する。
/// </summary>
/// <param name="message">ユーザ指定のメッセージ</param>
public static void Fatal(string message)
{
string method = System.Reflection.MethodBase.GetCurrentMethod().Name;
logger.Debug("Entering");

MessageBox.Show(message, PROJECT + " アプリケーションエラー"
, MessageBoxButtons.OK
, MessageBoxIcon.Error);
logger.Fatal("「" + message + "」を表示しました。");

logger.Debug("Exiting");
}

/// <summary>
/// 通常のエラーメッセージを表示する。
/// </summary>
/// <param name="message">ユーザ指定のメッセージ</param>
public static void Error(string message)
{
string method = System.Reflection.MethodBase.GetCurrentMethod().Name;
logger.Debug("Entering");

MessageBox.Show(message, PROJECT + " エラー", MessageBoxButtons.OK
, MessageBoxIcon.Error);
logger.Error("「" + message + "」を表示しました。");

logger.Debug("Exiting");
}

/// <summary>
/// 警告メッセージを表示する。
/// </summary>
/// <param name="message">ユーザ指定のメッセージ</param>
public static void Warn(string message)
{
string method = System.Reflection.MethodBase.GetCurrentMethod().Name;
logger.Debug("Entering");

MessageBox.Show(message, PROJECT + " 警告", MessageBoxButtons.OK
, MessageBoxIcon.Exclamation);
logger.Warn("「" + message + "」を表示しました。");

logger.Debug("Exiting");
}

/// <summary>
/// 情報メッセージを表示する。
/// </summary>
/// <param name="message">ユーザ指定のメッセージ</param>
public static void Info(string message)
{
string method = System.Reflection.MethodBase.GetCurrentMethod().Name;
logger.Debug("Entering");

MessageBox.Show(message, PROJECT + " 情報", MessageBoxButtons.OK
,MessageBoxIcon.Information);
logger.Info("「" + message + "」を表示しました。");

logger.Debug("Exiting");
}

/// <summary>
/// 「はい」「いいえ」を選択するメッセージを表示する。
/// </summary>
/// <param name="message">ユーザ指定のメッセージ</param>
/// <returns>クリックされたボタンの種類</returns>
public static DialogResult YesNo(string message)
{
string method = System.Reflection.MethodBase.GetCurrentMethod().Name;
logger.Debug("Entering");

DialogResult result = DialogResult.No;

result = MessageBox.Show(message,"サンプルシステム",
MessageBoxButtons.YesNo,MessageBoxIcon.Question);
logger.Info("「" + message + "」を表示しました。");
logger.Info(result.ToString() + "がクリックされました。");

logger.Debug("Exiting");
return result;
}

/// <summary>
/// 「はい」「いいえ」を選択するメッセージを表示する。
/// </summary>
/// <param name="message">ユーザ指定のメッセージ</param>
/// <param name="title">ユーザ指定のタイトル</param>
/// <returns>クリックされたボタンの種類</returns>
public static DialogResult YesNo(string message, string title)
{
string method = System.Reflection.MethodBase.GetCurrentMethod().Name;
logger.Debug("Entering");

DialogResult result = DialogResult.No;

result = MessageBox.Show(message, title,
MessageBoxButtons.YesNo,MessageBoxIcon.Question);
logger.Info("「" + message + "」を表示しました。");
logger.Info(result.ToString() + "がクリックされました。");

logger.Debug("Exiting");
return result;
}

/// <summary>
/// 「はい」「いいえ」を選択するメッセージを表示する。
/// </summary>
/// <param name="message">ユーザ指定のメッセージ</param>
/// <param name="title">ユーザ指定のタイトル</param>
/// <param name="cursor">既定のボタンを何番目にするか</param>
/// <returns>クリックされたボタンの種類</returns>
public static DialogResult YesNo(string message, string title
, MessageBoxDefaultButton cursor)
{
string method = System.Reflection.MethodBase.GetCurrentMethod().Name;
logger.Debug("Entering");

DialogResult result = DialogResult.No;

result = MessageBox.Show(message, title,
MessageBoxButtons.YesNo,MessageBoxIcon.Question, cursor);

logger.Info("「" + message + "」を表示しました。");
logger.Info(result.ToString() + "がクリックされました。");

logger.Debug("Exiting");
return result;
}

/// <summary>
/// 「OK」「Cancel」を選択するメッセージを表示する。
/// </summary>
/// <param name="message">ユーザ指定のメッセージ</param>
/// <returns>クリックされたボタンの種類</returns>
public static DialogResult OKCancel(string message)
{
string method = System.Reflection.MethodBase.GetCurrentMethod().Name;
logger.Debug("Entering");

DialogResult result = DialogResult.No;

result = MessageBox.Show(message,"サンプルシステム",
MessageBoxButtons.OKCancel,MessageBoxIcon.Question);
logger.Info("「" + message + "」を表示しました。");
logger.Info(result.ToString() + "がクリックされました。");

logger.Debug("Exiting");
return result;
}


/// <summary>
/// 「OK」「Cancel」を選択するメッセージを表示する。
/// </summary>
/// <param name="message">ユーザ指定のメッセージ</param>
/// <param name="title">ユーザ指定のタイトル</param>
/// <returns>クリックされたボタンの種類</returns>
public static DialogResult OKCancel(string message, string title)
{
string method = System.Reflection.MethodBase.GetCurrentMethod().Name;
logger.Debug("Entering");

DialogResult result = DialogResult.No;

result = MessageBox.Show(message, title,
MessageBoxButtons.OKCancel,MessageBoxIcon.Question);
logger.Info("「" + message + "」を表示しました。");
logger.Info(result.ToString() + "がクリックされました。");

logger.Debug("Exiting");
return result;
}


}
}

C#最速スタート (1)log4netの導入

C#のプロジェクトを作成し、最も初めにやるべき事はログ出力の
仕組みを整えることである。
全てのプログラムにおいてログ出力は基本である。
正しいログの出ていないプログラムで異常が発生した場合に、その
原因の解析が恐ろしくやっかいになってしまう事がある。
ログをおろそかにしてはならない。


ログ出力機能を自作するのも良いが、その実装に手間を取られる
のは本プロジェクトの趣旨に反する(それよりもビジネスロジック
のコーディングに注力したい)そこでApache Software FoundationのJavaロギ
ングサービス"log4j"の姉妹品である"log4net"を使用し、有用で簡単なログ出力機能を実現する。
http://logging.apache.org/log4net/


■概要

・LogManagerクラスを利用してユーザアプリケーションからLoggerモジュールを取得

 インスタンス生成

・Loggerモジュールを利用してユーザアプリケーションからログ出力

 指定された複数のAppenderが実行される

○テキストファイルへのログ出力

 ○メールでのログ送信

 ○DBへのログ出力


■利用のながれ


log4netインストール

構成ファイル(App.config)の定義

アセンブリファイル(AssemblyInfo.cs)の編集

ログ出力



~以下詳細~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
■入手
以下のサイトからlog4netをダウンロードする。

http://sourceforge.net/project/showfiles.php?group_id=31983&release_id=171808



■準備

(1)DLLの参照設定

ソリューションエクスプローラの[参照設定]
で[参照の追加]から[log4net.dll]を追加する。

※同じ名前のDLLが複数存在するが、
本サンプルではlog4netのnet-1.1-releaseの下にあるlog4net.dll
を使用している。

※参照設定時に「ローカルコピー」オプションをTrueにしておかないと
エラーになる
log4netのDLLがbinの下にコピーされないとlog4netが実行できない?


(2)構成ファイル AssemblyInfoに以下を追加


//_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
// log4net用定義
//_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
//
// ▼log4netが参照する設定ファイルの定義
//
// 設定ファイルの指定方法として(1)~(3)のどれかを選択。
// 「Watch=true」はアプリケーション実行中に設定ファイルを変更した場合に反映が
// 有効。
//
//
// (1) 設定ファイルの名前が「アセンブリ名+.config」の場合(VisualStudio上では
// 「App.config」)
//[assembly: log4net.Config.DOMConfigurator(Watch=true)]

//▲log4netのバージョンによってはDOMConfiguratorは推奨されない
[assembly: log4net.Config.XmlConfigurator(Watch=true)]

//
// (2) 設定ファイルの名前が「アセンブリ名+.独自の拡張子(この例では+.log4net
// )」の場合
//[assembly: log4net.Config.DOMConfigurator(ConfigFileExtension="log4net",
// Watch=true)]
//
// (3) 設定ファイルの「ファイル名」を直接指定する場合
//[assembly: log4net.Config.DOMConfigurator(ConfigFile="../../log4net.xml",
// Watch=true)]
//
//_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/



(3)アセンブリファイルの追加、編集

ソリューションエクスプローラより、新しい項目の追加で

「アプリケーション構成ファイル(App.config)」を追加する。

(2)の設定でビルドして実行するとbinの下に自動的にアセンブリ名+configという名称の
ファイルが作成される。


App.configの中身は以下である


<?xml version="1.0" encoding="utf-8" ?>
<!-- ======================================================================= -->
<configuration>
<!-- ===================================================================== -->
<!-- 構成ファイルの設定 -->
<!-- ===================================================================== -->

<!-- log4netセクションのハンドラ設定 -->
<configSections>
<section name="log4net" type="System.Configuration.IgnoreSectionHandler" />
</configSections>
<appSettings>
<!-- log4net内部のデバッグメッセージを出力する場合、trueに設定 -->
<add key="log4net.Internal.Debug" value="true"/>
</appSettings>

<log4net>

<!-- =================================================================== -->
<!-- ログ出力先の設定(appenderの設定) -->
<!-- =================================================================== -->

<!-- ▼コンソール出力用[ConsoleAppender] -->
<appender name="ConsoleAppender" type="log4net.Appender.ConsoleAppender">
<layout type="log4net.Layout.PatternLayout">
<param name="ConversionPattern" value="%d [%t][%-5p]%c %M - %m%n" />
</layout>
</appender>

<!-- ▼ファイル出力用[RollingFileAppender]
(サイズの制約に基づいたログファイルの生成) -->
<appender name="RollingFileAppender_Size"
type="log4net.Appender.RollingFileAppender">
<!-- ログレベルで出力をフィルタリング -->
<filter type="log4net.Filter.LevelRangeFilter">
<param name="LevelMin" value="DEBUG" />
<param name="LevelMax" value="FATAL" />
</filter>
<!-- ファイル名 -->
<param name="File" value="FreeGIS.log" />
<!-- 追記する場合true/上書きする場合false -->
<param name="AppendToFile" value="true" />
<!-- ファイルサイズの制約によるログファイルの切替 -->
<param name="RollingStyle" value="Size" />
<!-- サイズの制約によるログファイルの切替(デフォルトは10M) -->
<!-- <param name="MaximumFileSize" value="5KB" /> -->
<!-- <param name="MaximumFileSize" value="500KB" /> -->
<param name="MaximumFileSize" value="1MB" />
<!-- <param name="MaximumFileSize" value="1GB" /> -->
<!-- 保存するファイル数(数を超えた場合は古いものから削除) -->
<param name="MaxSizeRollBackups" value="3" />
<param name="StaticLogFileName" value="true" />
<layout type="log4net.Layout.PatternLayout">
<param name="ConversionPattern" value="%d{yyyy/MM/dd HH:mm:ss,fff} [%-5p] %c %M %m%n" />
</layout>
</appender>

<!-- =================================================================== -->
<!-- ログ出力の対象レベルと出力先の設定 -->
<!-- =================================================================== -->
<!-- =================================================================== -->
<!-- ▼Rootの設定 -->
<!-- ※デフォルトとなるログ出力設定 -->
<!-- =================================================================== -->
<root>
<!-- RootはDEBUG以上を出力 -->
<level value="DEBUG" />
<!-- コンソール出力 -->
<appender-ref ref="ConsoleAppender" />

<!-- ログファイル出力 -->
<appender-ref ref="RollingFileAppender_Size" />

</root>

</log4net>
</configuration>



■実装

loggerと呼ばれるログ出力用インスタンスをnewする
ログ出力したいクラスの先頭に以下の一文を追加する


private static readonly log4net.ILog logger =
log4net.LogManager.GetLogger(
System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);


■動作確認


参考

http://www.archway.co.jp/file/log4net.pdf  NAgile開発 log4netによるログ出力


SMTPAppenderの実装方法
http://www.isla-plata.org/wiki/pukiwiki.php?%B3%AB%C8%AF%A5%EA%A5%BD%A1%BC%A5%B9%2F.Net%2Flog4net%A4%CE%BB%C8%A4%A4%CA%FD