2008年8月4日月曜日

using System;

using System.Collections.Generic;

using System.ComponentModel;

using System.Diagnostics;

using System.Drawing.Design;

using System.IO;

using System.Reflection;

using System.Reflection.Emit;

using System.Text;

using System.Windows.Forms;

using GeoLibrary;

using GeoLibrary.Design;

using GeoLibrary.Interfaces;

using GeoLibrary.Delegates;

using GeoLibrary.Properties;



namespace GeoLibrary.Components

{

///

/// イベント監視コンポーネントクラス

///


///

///


#if !DEBUG

[DebuggerStepThrough()]

#endif

[Designer(typeof(GuardianComponentDesigner))]

[ProvideProperty("EventList", typeof(Component))]

[ResourceDescription("CTL_DSC_SEASER")]

public class Guardian

: Component, IExtenderProvider

{

///

/// コンポーネント別のイベントリストホルダを保持します

///


private Dictionary m_eventDictionary;



///

/// ログ用ディレクトリ情報オブジェクトを保持します

///


private LogDirectoryInfo m_logDirectoryInfo;



///

/// ログ用ディレクトリ情報オブジェクト設定済フラグを保持します

///


private bool m_setDirectoryFlg;



///

/// コンポーネントプールを保持します

///


private List m_componetPool;



///

/// 同期用オブジェクト

///


private object m_lockObject;



///

/// デザイナオブジェクト用プロパティ

/// コンポーネント別のイベントリストホルダを取得設定します

/// デザイン時のみのプロパティ

///


/// イベントリストホルダディクショナリ

[Browsable(false)]

[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]

public Dictionary EventDictionary

{

set

{

// セットはデザイン時のみです

if (!this.DesignMode)

{

throw new InvalidOperationException(Resources.ERR_MES_INVALID_OPE);

}

// 引数をチェック

else if (value == null)

{

throw new NullReferenceException(Resources.ERR_MES_ARG_NULL);

}



this.m_eventDictionary = value;

}

get

{

return this.m_eventDictionary;

}

}



///

/// デザイナ用メソッド

/// ログ用ディレクトリの変更を検知するために必要です

///


///

private bool ShouldSerializeLogDirectory()

{

return true;

}



///

/// デザイナ用メソッド

/// ログ用ディレクトリを初期化するために必要です

///


private void ResetLogDirectory()

{

this.m_logDirectoryInfo = new LogDirectoryInfo();

}



///

/// ログ用ディレクトリを設定します

///


/// ログ用ディレクトリ

[Category(Grobal.C_CATEGORY)]

[ResourceDescription("PRO_DSC_LOGDIRECTORYINFO")]

[TypeConverter(typeof(LogDirectoryInfoTypeConverter))]

public LogDirectoryInfo LogDirectory

{

set

{

// 引数をチェック

if (value == null)

{

value = new LogDirectoryInfo();

}



this.m_logDirectoryInfo = value;



// デザインモードならここまで

if (this.DesignMode)

{

return;

}



// クリティカルセクション

lock (this.m_lockObject)

{

// フラグをセット

this.m_setDirectoryFlg = true;



// コンポーネントプールをチェック

if (this.m_componetPool != null)

{

foreach (Component component in this.m_componetPool)

{

this.CoreTask(component);

}

}



// コンポーネントプールを削除

this.m_componetPool = null;

}

}

get

{

return this.m_logDirectoryInfo;

}

}



///

/// デザイナ用メソッド

/// コンポーネント別のイベントリストホルダの変更を検知するために必要です

///


///

private bool ShouldSerializeEventList(Component a_component)

{

try

{

if (this.GetEventList(a_component).AddedEventList.Count == 0)

{

return false;

}

return true;

}

catch

{

return true;

}

}



///

/// コンポーネント別のイベントリストホルダを取得します

///


/// コンポーネント

/// イベントリストホルダ

[Category(Grobal.C_CATEGORY)]

[Editor(typeof(EventListHolderValueEditor), typeof(UITypeEditor))]

[ResourceDescription("PRO_DSC_EVENTLISTHOLDER")]

[TypeConverter(typeof(EventListHolderTypeConverter))]

public EventListHolder GetEventList(Component component)

{

// 引数をチェック

if (component == null)

{

throw new NullReferenceException("component が null 参照です");

}



// コンポーネントに対するイベントリストオブジェクトを保持していなければ

if (!this.m_eventDictionary.ContainsKey(component))

{

// 新規に生成する

EventListHolder holder = new EventListHolder();



// 生成したリストホルダにイベントリストを追加

holder.EventList.InsertRange(0, component.GetType().GetEvents());



// ディクショナリに追加

this.m_eventDictionary.Add(component, holder);

}



// 値を返す

return this.m_eventDictionary[component];

}



///

/// コンポーネント別のイベントリストホルダを設定します

///


/// コンポーネント

/// イベントリストホルダ

[Category(Grobal.C_CATEGORY)]

[Editor(typeof(EventListHolderValueEditor), typeof(UITypeEditor))]

[ResourceDescription("PRO_DSC_EVENTLISTHOLDER")]

[TypeConverter(typeof(EventListHolderTypeConverter))]

public void SetEventList(Component component, EventListHolder listHolder)

{

// 引数をチェック

if (component == null)

{

throw new NullReferenceException("component が null 参照です");

}



// コンポーネントに対するイベントリストオブジェクトを保持していなければ

if (!this.m_eventDictionary.ContainsKey(component))

{

// 新規に生成する

this.m_eventDictionary.Add(component, null);

}



// 値をセット

this.m_eventDictionary[component] = listHolder;



// デザインモード、もしくはイベントリストホルダがnull参照ならここまでで終了

if (this.DesignMode || listHolder == null)

{

return;

}



// クリティカルセクション

lock (this.m_lockObject)

{

// ログ用ディレクトリがセットされていれば

if (this.m_setDirectoryFlg)

{

// ハンドラの生成を行う

this.CoreTask(component);

}

// セットされていなければコンポーネントプールに追加

else

{

if (this.m_componetPool == null)

{

this.m_componetPool = new List();

}

this.m_componetPool.Add(component);

}

}

}



///

/// コンストラクタ

///


public Guardian()

: base()

{

this.m_eventDictionary = new Dictionary();

this.m_logDirectoryInfo = new LogDirectoryInfo();

this.m_setDirectoryFlg = false;

this.m_componetPool = null;

this.m_lockObject = new object();

}



///

/// コンストラクタ

///


/// コンテナ

public Guardian(IContainer container)

: this()

{

container.Add(this);

}



///

/// コアタスク

/// 動的ハンドラを生成します

///


///

private void CoreTask(Component component)

{

try

{

// コンポーネントごとに指定されたイベントを全てフックします

if (this.m_eventDictionary.ContainsKey(component))

{

Type type;

MethodInfo addMethod;



// 全イベントのハンドラを動的に生成

List eventList = this.m_eventDictionary[component].AddedEventList;

foreach (EventInfo eventInfo in eventList)

{

try

{

type = eventInfo.EventHandlerType;

if (!GrobalHandlerDictionary.Contains(type, eventInfo.Name))

{

GrobalHandlerDictionary.CreateDynamicHandler(type, eventInfo.Name, this.m_logDirectoryInfo);

}

addMethod = eventInfo.GetAddMethod();

addMethod.Invoke(component, new Object[] { GrobalHandlerDictionary.GetDynamicHandler(type, eventInfo.Name) });

}

catch

{

Grobal.GrobalErrorHandler("Guardian.CoreTask¥r¥n予期せぬ例外", 1, 1);

}

}

}

}

catch

{

Grobal.GrobalErrorHandler("Guardian.CoreTask¥r¥n予期せぬ例外", 1, 1);

}

}



///

/// IExtenderProviderインターフェイス実装

/// コンポーネントに対して拡張プロパティを実装するかどうかの値を取得します

///


/// 対象コンポーネント

///

/// true : 実装する

/// false : 実装しない

///


public virtual bool CanExtend(object extendee)

{

if (extendee is Guardian)

{

return false;

}

return true;

}

}

}
using System;

using System.Reflection;

using System.Collections.Generic;

using System.Reflection.Emit;

using System.Diagnostics;

using System.IO;

using System.Threading;

using System.ComponentModel;

using System.Windows.Forms;

using GeoLibrary.Interfaces;

using GeoLibrary.Properties;



namespace GeoLibrary

{

///

/// グローバルハンドラディクショナリクラス

///

/// イベントログ用に生成した動的ハンドラを管理します

///


///

///


#if !DEBUG

[DebuggerStepThrough()]

#endif

public static class GrobalHandlerDictionary

{

///

/// 動的メソッドディクショナリを保持します

///


private static Dictionary> s_dynamicMethodDictionary;



///

/// 同期用オブジェクト

///


private static object s_lockObject;



///

/// 静的コンストラクタ

///


static GrobalHandlerDictionary()

{

GrobalHandlerDictionary.s_dynamicMethodDictionary = new Dictionary>();

GrobalHandlerDictionary.s_lockObject = new object();

}



///

/// 動的ハンドラ取得メソッド

/// ハンドラタイプ、イベント名、片方でも存在しない場合は例外が発生します

///


/// ハンドラタイプ

/// イベント名

/// 動的ハンドラ

public static Delegate GetDynamicHandler(Type type, string eventName)

{

return GrobalHandlerDictionary.s_dynamicMethodDictionary[type][eventName];

}



///

/// 動的ハンドラ生成メソッド

///

/// 引数のイベント情報オブジェクトからイベントハンドラの型を抽出し

/// その型の動的ハンドラを作成します

///

/// 第2引数のログ用ディレクトリ情報オブジェクトの指すディレクトリパスは

/// 動的ハンドラ内で呼び出されるログアウトメソッドに引数として渡されます

///


/// イベントハンドラタイプ

/// イベント名

/// ログ用ディレクトリ情報

public static void CreateDynamicHandler(Type type, string eventName, LogDirectoryInfo logDirectoryInfo)

{

const string C_INVOKE = "Invoke";

const string C_LOGOUTMETHOE = "LogOut";



lock (GrobalHandlerDictionary.s_lockObject)

{

// イベントタイプをチェック

if (type.BaseType != typeof(MulticastDelegate))

{

throw new ArgumentException(Resources.ERR_MES_TYPEOBJECT);

}



// さらにチェック

MethodInfo invoke = type.GetMethod(C_INVOKE);

if (invoke == null)

{

throw new ArgumentException(Resources.ERR_MES_TYPEOBJECT);

}



// 登録されていなければハンドラを生成

if (!GrobalHandlerDictionary.s_dynamicMethodDictionary.ContainsKey(type) ||

GrobalHandlerDictionary.s_dynamicMethodDictionary[type] == null ||

!GrobalHandlerDictionary.s_dynamicMethodDictionary[type].ContainsKey(eventName))

{

// イベントデリゲートの全パラメータを取得

ParameterInfo[] parameters = invoke.GetParameters();

Type[] typeParameters = new Type[parameters.Length];

for (int i = 0; i < dynamicmethod =" new" logoutparameters =" new" logoutmethod =" typeof(GrobalHandlerDictionary).GetMethod(C_LOGOUTMETHOE," path =" logDirectoryInfo.FullName;" ilgenerator =" dynamicMethod.GetILGenerator();">());

}

GrobalHandlerDictionary.s_dynamicMethodDictionary[type].Add(eventName, dynamicMethod.CreateDelegate(type));

}

}

}



///

/// 動的ハンドラ検索メソッド

///


/// ハンドラタイプ

/// ログ用イベント名

///

/// true : 動的ハンドラあり

/// false : 動的ハンドラなし

///


public static bool Contains(Type type, string eventName)

{

if (GrobalHandlerDictionary.s_dynamicMethodDictionary.ContainsKey(type))

{

if (GrobalHandlerDictionary.s_dynamicMethodDictionary[type] != null)

{

if (GrobalHandlerDictionary.s_dynamicMethodDictionary[type].ContainsKey(eventName))

{

if (GrobalHandlerDictionary.s_dynamicMethodDictionary[type][eventName] != null)

{

return true;

}

}

}

}

return false;

}



///

/// ログアウトメソッド

///

/// イベントログを対象にしています

/// 第3・4引数にはイベントハンドラ用の引数をそのまま渡してください

///


/// イベント名

/// ログ用ディレクトリパス

/// sender

/// e

public static void LogOut(string eventName, string directoryPath, object sender, EventArgs e)

{

try

{

string log;

if (e is ILogHolder)

{

log = (e as ILogHolder).Log;

}

else if (sender is Control)

{

log = (sender as Control).Name;



if (sender is CheckBox)

{

log += " " + ((sender as CheckBox).Checked ? "Checked" : "Unchecked");

}

else if (sender is ComboBox)

{

log += "¥nText=¥"" + (sender as ComboBox).Text + "¥" SelectedIndex=" + (sender as ComboBox).SelectedIndex.ToString();

}

else if (sender is TextBox)

{

log += " ¥"" + (sender as TextBox).Text + "¥"";

}

else if (sender is RichTextBox)

{

log += "¥n¥"" + (sender as RichTextBox).Text.TrimEnd(new char[] { '¥r', '¥n' }) + "¥"";

}

else if (sender is System.Windows.Forms.Label)

{

log += " ¥"" + (sender as System.Windows.Forms.Label).Text + "¥"";

}

}

else if (sender != null)

{

log = sender.ToString();

}

else

{

log = "null";

}



// ログをイベントログライタオブジェクトに渡す

XmlEventLogWriter.GetXmlLogWriter(directoryPath).LogWrite(eventName, log);

}

catch

{

Grobal.GrobalErrorHandler(Resources.ERR_MES_LOGOUT, 1, 1);

}

}

}

}