メタプログラミングツールとしてのIronPython
リフレクションを使えばメタプログラミングが出来ますが、ちょっと面倒です。たとえば、以前やったネタですが、
http://d.hatena.ne.jp/akiramei/20050612/p1
インタフェースの委譲を自動化するだけなのに結構なコード量になっています。リフレクションをやめてソースコードを生成してコンパイルした方が楽だったかもしれませんね。(^^; さて、ソースコードを生成するのなら、IronPythonを使うとevalも使えるのでもっと楽チンです。
using System; using System.Collections.Generic; using System.Text; using IronPython.Hosting; namespace IronTest { public interface ICalc { double Add(double x, double y); double Sub(double x, double y); } public interface ICalcEx { double Mul(double x, double y); double Div(double x, double y); } public class Keisan { public double Tasu(double x, double y) { return x + y; } public double Hiku(double x, double y) { return x - y; } public double Kakeru(double x, double y) { return x * y; } public double Waru(double x, double y) { return x / y; } } class Program { static PythonEngine engine = new PythonEngine(new EngineOptions()); /// <summary> /// 既存クラスを使ってインタフェースを実装する /// </summary> /// <param name="ns">名前空間</param> /// <param name="iname">インタフェース名</param> /// <param name="cname">実装クラス</param> /// <param name="mapping">委譲先のマッピング</param> /// <returns>インタフェースを実装したクラス</returns> static object Impliments(string ns, List<string> iname, string cname, Dictionary<string, string> mapping) { string newclass = String.Join("", iname.ToArray()) + cname; string baseclass = String.Join(",", iname.ToArray()) + "," + cname; StringBuilder sb = new StringBuilder(); sb.AppendFormat("from {0} import *\n", ns); sb.AppendFormat("class {0}({1}):\n", newclass, baseclass); sb.Append(" def __init__(self):\n"); foreach (string key in mapping.Keys) sb.AppendFormat(" self.{0} = super({1}, self).{2}\n", key, newclass, mapping[key]); sb.AppendFormat("_ = {0}()\n", newclass); System.Diagnostics.Debug.Write(sb.ToString()); engine.Execute(sb.ToString()); return engine.Evaluate("_"); } static void Main(string args) { engine.LoadAssembly(System.Reflection.Assembly.GetEntryAssembly()); engine.Import("IronTest"); // メソッドの委譲先 Dictionary<string, string> mapping = new Dictionary<string, string>(); mapping["Add"] = "Tasu"; mapping["Sub"] = "Hiku"; mapping["Mul"] = "Kakeru"; mapping["Div"] = "Waru"; // インタフェースの実装 Object o = Impliments("IronTest", new List<string>( new string { "ICalc", "ICalcEx" }), "Keisan", mapping); ICalc ic = o as ICalc; ICalcEx ix = o as ICalcEx; Console.WriteLine(ic.Add(3, 5)); Console.WriteLine(ic.Sub(3, 5)); Console.WriteLine(ix.Mul(3, 5)); Console.WriteLine(ix.Div(3, 5)); } } } /* 生成したPythonコード from IronTest import * class ICalcICalcExKeisan(ICalc,ICalcEx,Keisan): def __init__(self): self.Add = super(ICalcICalcExKeisan, self).Tasu self.Sub = super(ICalcICalcExKeisan, self).Hiku self.Mul = super(ICalcICalcExKeisan, self).Kakeru self.Div = super(ICalcICalcExKeisan, self).Waru _ = ICalcICalcExKeisan() */ /* 結果 8 -2 15 0.6 */
Pythonのコードは簡潔なので生成するのも楽ですね。ただ、Pythonのメタプログラミングは不慣れなので、もっと良い方法があるかもしれません。(^^;