ASP.NET MVCで独自のログクラスを実装しています。
いままで呼び出し元のコンストラクタでコントローラー名やアクション名をセットしていたのですが、いちいち引数を記述するのが面倒だったのでクラス内部で自動的に取得、セットするようにしました。
コントローラー以外(Global.asax)などから呼ばれた場合は、呼び出し元のクラス名、メソッド名をスタックフレームからセットするようにしています。平凡なネタですいません。
Logger.cs
using System.Collections.Specialized;
using System.Diagnostics;
using System.Linq;
using System.Web;
namespace Implem.Sample
{
public class Logger
{
public HttpContext HttpContext;
public NameValueCollection Form { get { return HttpContext.Request.Form; } }
// 呼び出し元コントローラー名(クラス名)
public string ClassName;
// 呼び出し元アクション名(メソッド名)
public string MethodName;
// 引数無しで初期化
public Logger()
{
if (HttpContext.Current != null && HttpContext.Current.Session != null)
{
HttpContext = HttpContext.Current;
// Controller以外(Global.asax等)からアクセスされた場合
// コンテキストからコントローラー名、アクション名をセット
SetCallerDataByContext();
}
else
{
// Controller以外(Global.asax等)からアクセスされた場合
// スタックフレームからクラス名、メソッド名をセット
SetCallerDataByStackFrame();
}
}
private void SetCallerDataByContext()
{
// コンテキスト内のルートデータから取得
var routeData = System.Web.Routing.RouteTable.Routes
.GetRouteData(new System.Web.HttpContextWrapper(HttpContext));
ClassName = routeData.Values["controller"].ToString();
MethodName = routeData.Values["action"].ToString();
}
private void SetCallerDataByStackFrame()
{
// コンストラクタ .ctor を除く最新のスタックフレームから取得
var method = new StackTrace(1, false).GetFrames()
.Select(o => o.GetMethod()).Where(o => o.Name != ".ctor").First();
ClassName = method.ReflectedType.Name;
MethodName = method.Name;
}
}
}