Python の文字列フォーマット操作では
sql = "SELECT %(name)s FROM %(table)s WHERE 10 < %(code)s" % \ {"name":"C2", "table":"TBL1", "code":"C1" }
という風に、名前で変換する項目を指定出来ます。この方法、どんな値に置換されるか分りやすいので便利。
C# でも Python みたいに名前で指定したい!
そう思ったので、名前埋め込み型のフォーマット操作ができるメソッドをこしらえてみました。
public static class StringUtility { // 辞書を渡す public static string NamedFormat(string format, IDictionary<string, object> args) { var sb = new StringBuilder(format); // 括弧をエスケープ sb.Replace("{{", "{{_"); sb.Replace("}}", "_}}"); // string.Format に渡すフォーマット作成 // ついでに string.Format に渡す配列も作成 var values = args.Select((pair, index) => { sb.Replace("{" + pair.Key + "}", "{" + index + "}"); return pair.Value; }).ToArray(); // エスケープしたものを戻す sb.Replace("{{_", "{{"); sb.Replace("_}}", "}}"); // 整形は string.Format にまかせる return string.Format(sb.ToString(), values); } // 匿名クラスのインスタンスを渡す public static string NamedFormat(string format, object obj) { if (string.IsNullOrEmpty(format) || obj == null) { return string.Format(format, obj); } // { プロパティ名, プロパティ値 } の辞書を作って渡す return NamedFormat(format, obj.GetType().GetProperties() .ToDictionary(p => p.Name, p => p.GetValue(obj, null))); } }
使い方は次の通りです
class Program { static void Main(string[] args) { // 辞書で指定 var query1 = StringUtility.NamedFormat(@" SELECT {code}, {name} FROM {tableName} WHERE {createdAt} = @createdAt ORDER BY {code}", new Dictionary<string, object>() { { "tableName", "TBL1" }, { "code", "C1" }, { "name", "C2" }, { "createdAt", "C3" } }); Console.WriteLine(query1); // 匿名クラスで指定 var query2 = StringUtility.NamedFormat(@" SELECT {code}, {name} FROM {tableName} WHERE {createdAt} = @createdAt ORDER BY {code}", new { tableName = "TBL1", code = "C1", name = "C2", createdAt = "C3" }); Console.WriteLine(query2); // 匿名クラスで指定(プロパティ名=変数名) string tableName = "TBL1"; string code = "C1"; string name = "C2"; string createdAt = "C3"; var query3 = StringUtility.NamedFormat(@" SELECT {code}, {name} FROM {tableName} WHERE {createdAt} = @createdAt ORDER BY {code}", new { tableName, code, name, createdAt }); Console.WriteLine(query3); Console.ReadLine(); } }
3番目の例は、Ruby の変数評価文字列に似てる気がします。