適当コード
GDNJ 『Exceptionのメッセージの英語化』にて私が使用しているもの。
適当に機能がほしくなったら追加してただけなものにコメントとエラーチェックをちょっと足してみたけど、リージョン折りたたんでない状態だと、ちょっと長いね。
#region *** (C) Lady.BUG (K.Takaoka)
using System;
using System.Threading;
using System.Collections;
using System.Collections.Specialized;
using System.Globalization;
using System.Text;
using System.Text.RegularExpressions;
using System.CodeDom.Compiler;
#endregion
/// <summary>
/// 指定した文字列で表現されるオブジェクトの ToString() を呼び出す
/// </summary>
public class ToStr
{
#region 定数
/// <summary>自動生成するクラスの名前</summary>
private const string @class = "_o_target_obj_provider";
/// <summary>自動生成するメソッドの名前</summary>
private const string @method = "_o_get_object";
/// <summary>
/// C# 版ソースコード
/// </summary>
private const string csharp_template = @"// generated {0}
{1}
public class {2}
{{
public static object {3}()
{{
return {4};
}}
}}
";
/// <summary>
/// VB.NET 版ソースコード
/// </summary>
private const string vb_template = @"' generated {0}
{1}
Public Class {2}
Public Shared Function {3}() As System.Object
Return {4}
End Function
End Class
";
/// <summary>コマンドラインオプション</summary>
private const string opts = @"dump|code|w|warn|warning|lang|ui|lib|use|using|import|throw";
/// <summary>コマンドラインオプション解析用</summary>
private const string opts_regex = @"[-+/](" + opts + @")[:=]([^ ]*)";
#endregion
#region 初期化
private static ListDictionary template;
private static ListDictionary refer_fmt;
private static ArrayList libs;
private static ArrayList uses;
static ToStr()
{
// ソースコード
template = new ListDictionary();
template["cs"] = csharp_template;
template["vb"] = vb_template;
// ネームスペースを省略する書式
refer_fmt = new ListDictionary();
refer_fmt["cs"] = "using {0};";
refer_fmt["vb"] = "Imports {0}";
//参照設定に追加するアセンブリ
libs = new ArrayList(new string[]
{
// 標準で参照設定に追加するアセンブリ
"System.dll",
"System.Data.dll",
"System.Drawing.dll",
"System.XML.dll",
"System.Windows.Forms.dll",
});
// インポートするネームスペース
uses = new ArrayList(new string[]
{
"System",
});
}
#endregion
/// <summary>プログラム エントリポイント</summary>
public static void Main()
{
// Main(string[] args) にはロングファイル名などの都合で余計な加工が加わるので利用しない
string args = System.Environment.CommandLine;
// 動作モード
bool dump = false; // true: 実行せずソースを吐く, false: 実行結果を吐く
bool warn = false; // true: コンパイル時の警告文を出力する
bool throwing = false; // true: 実行時例外を再生成する
string lang = "cs"; // 使用言語
// コマンドライン解析
int pos = args.ToLower().IndexOf("tostring");
pos = args.IndexOf(' ', pos) + 1; // FIXME:
Regex regex = new Regex(opts_regex, RegexOptions.IgnoreCase|RegexOptions.Singleline);
while (regex.IsMatch(args, pos))
{
Match m = regex.Match(args, pos);
if (pos != m.Index) break; // FIXME:
#region switch (m.Groups[1].Value.ToLower())
switch (m.Groups[1].Value.ToLower())
{
case "dump":
// ソースコードを出力して終了する
dump = !dump;
break;
case "code":
// 使用言語を変更する
if (template.Contains(m.Groups[2].Value))
lang = m.Groups[2].Value;
else
goto default;
break;
case "w":
case "warn":
case "warning":
// 警告を表示する
warn = !warn;
break;
case "throw":
// 例外を再生する
throwing = !throwing;
break;
case "lang":
// CurrentCulture を設定
try
{
Thread.CurrentThread.CurrentCulture =
CultureInfo.CreateSpecificCulture(m.Groups[2].Value);
}
catch (ArgumentException )
{
goto default;
}
break;
case "ui":
// CurrentUICulture を設定
try
{
Thread.CurrentThread.CurrentUICulture =
CultureInfo.CreateSpecificCulture(m.Groups[2].Value);
}
catch (ArgumentException )
{
goto default;
}
break;
case "lib":
// アセンブリ参照を追加
libs.Add(m.Groups[2].Value);
break;
case "use":
case "using":
// using を追加
uses.Add(m.Groups[2].Value);
break;
default:
// aye?
Console.WriteLine("Parameter Error: {0} = {1}",
m.Groups[1].Value, m.Groups[2].Value);
break;
}
#endregion
pos += m.Length + 1; // FIXME:
}
// ネームスペース省略用のソースコード生成
StringBuilder imp = new StringBuilder(uses.Count * 100);
foreach (string ns in uses)
{
imp.Append(string.Format(refer_fmt[lang] as string, ns))
.Append("\n");
}
// ソースコード生成
string src = string.Format(template[lang] as string, DateTime.Now, imp, @class, @method, args.Substring(pos));
if (dump)
{
Console.WriteLine(src);
return;
}
// コンパイラ生成
ICodeCompiler cc;
switch (lang)
{
case "cs":
cc = new Microsoft.CSharp.CSharpCodeProvider().CreateCompiler();
break;
case "vb":
cc = new Microsoft.VisualBasic.VBCodeProvider().CreateCompiler();
break;
default:
Console.WriteLine("Parameter Error: code = " + lang);
return;
}
// コンパイルオプション設定
CompilerParameters param = new CompilerParameters();
param.GenerateInMemory = true;
foreach (string asm in libs) param.ReferencedAssemblies.Add(asm);
// コンパイル
CompilerResults rs = cc.CompileAssemblyFromSource(param, src);
if ((rs.Errors.Count > 0) && (warn || rs.Errors.HasErrors))
{
foreach (CompilerError err in rs.Errors)
{
Console.WriteLine("{0} {1}: {2}",
err.IsWarning ? "warning" : "error",
err.ErrorNumber,
err.ErrorText);
}
if (rs.Errors.HasErrors) return;
}
try
{
// 実行
Console.WriteLine(
rs.CompiledAssembly
.GetType(@class)
.GetMethod(@method)
.Invoke(null, null)
.ToString());
}
catch (Exception e)
{
Exception ex = e;
while (ex != null)
{
// 例外が...
Console.WriteLine(ex.Message);
ex = ex.InnerException;
}
if (throwing) throw e;
}
}
}いや、日記のネタに欠乏していただけですが(笑)
色づけするの難しいのであきらめ。