MonoでSeasar.NETを動かす

ここ最近、MonoでS2.NETを動かそうと色々やってきましたが、やっと出来ました。結局、S2.NETソースコードを書き換えてしまいました。(^^;
Monoの実装が出来ていないので、JScriptを使うのは諦め、IronPythonを使うことにしました。

IronPythonUtil.cs

namespace Seasar.Framework.Util
{
    using System;
    using System.Collections;
    using System.Reflection;
    using System.CodeDom.Compiler;
    using Seasar.Framework.Exceptions;
    using System.Configuration;
    using IronPython.Hosting;

    public sealed class IronPythonUtil
    {
        static PythonEngine engine;

        private IronPythonUtil()
        {           
        }

        static IronPythonUtil()
        {
            EngineOptions options = new EngineOptions();
            options.ShowClrExceptions = true;
            options.ClrDebuggingEnabled = true;
            engine = new PythonEngine(options);

            Initialize();
        }

        static void Register(Assembly asm)
        {
            // 動的に作成されたアセンブリは除く
            if (!(asm is System.Reflection.Emit.AssemblyBuilder))
            {
                engine.LoadAssembly(asm);
                foreach (Type t in asm.GetTypes())
                    if (t.IsPublic && t.Namespace != null)
                        engine.Import(t.Namespace);
            }
        }

        static void Initialize()
        {
            EngineOptions options = new EngineOptions();
            options.ShowClrExceptions = true;
            engine = new PythonEngine(options);

            foreach (Assembly asm in AppDomain.CurrentDomain.GetAssemblies())
                Register(asm);
        }

        public static object Evaluate(string exp,Hashtable ctx, object root)
        {
            try
            {
                engine.Globals["self"] = ctx["self"];
                engine.Globals["out"] = ctx["out"];
                engine.Globals["err"] = ctx["err"];
                engine.Globals["appSettings"] = root;
                return engine.Evaluate(exp);
            }
            catch (Exception ex)
            {
                throw new IronPythonEvaluateRuntimeException(exp, ex);
            }
        }

        public static object Evaluate(string exp, object root)
        {
            return Evaluate(exp, new Hashtable(), root);
        }
    }
}


namespace Seasar.Framework.Exceptions
{
    using System;
    using System.Runtime.Serialization;
    /// <summary>
    /// IronPython.Hosting.PythonEngine.Evalueで発生する実行時例外です。
    /// </summary>
    [Serializable]
        public sealed class IronPythonEvaluateRuntimeException : SRuntimeException
        {
            private string expression_;

            public IronPythonEvaluateRuntimeException(string expression,Exception cause)
                : base("ESSR0073",new object[] {expression,cause},cause)
                {
                    expression_ = expression;
                }

            public IronPythonEvaluateRuntimeException(SerializationInfo info, StreamingContext context) 
                : base( info, context )
                {
                    this.expression_ = info.GetString("expression_");
                }

            public override void GetObjectData( SerializationInfo info,
                    StreamingContext context )
            {
                info.AddValue("expression_", this.expression_, typeof(String));

                base.GetObjectData(info, context);
            }

            public string Expression
            {
                get { return expression_; }
            }
        }
}

上記のソースをS2.NETのプロジェクトに追加して、JScriptUtilの部分をIronPythonUtilに置換すればOK。S2.NETS2Dao.NETを使ってOracleにアクセスするサンプルがMono上で動作しました。MonoでS2.NETを動かしたい方は、自由に使ってください。