0

私はこの明らかに幻想的なエラーを私に与えている少し複雑なプログラムを持っています...
私はそれを実行する人に私の美しい例外を投げることができる私が装備したこの小さなサンプルプログラムの助けを借りて説明を始めます。

<!-- language: c# -->
using System;
using System.Collections.Generic;
using System.Threading.Tasks;

namespace so_redux {
    static class Program {
        [STAThread]
        static void Main(){
            CS2JS _class=new CS2JS();
        }
    }//class Program

    class CS2JS{
        public CS2JS(){
            Func<String,Object> js_eval=initJS();
            Object cs_ic=initCS();

            string xc;
            object res;

            cs_ic.GetType().GetMethod("init").Invoke(cs_ic,null);
            AppDomain.CurrentDomain.SetData("trespasser",cs_ic);

            xc=@"function edata(fieldname:String,ival:String):Object{
                    var sob=System.AppDomain.CurrentDomain.GetData('trespasser');
                    var v1=sob.GetType().GetField(fieldname).GetValue(sob);

                    function HASH(s1:String,s2:String):Object{
                        var q1=sob.GetType().GetField(s1).GetValue(sob);
                        return q1.ITEM(s2);
                    }

                    var v2=v1.ITEM(ival);
                    return eval(v2);
                }
                edata('HT','foo');";
            res=js_eval(xc);
            // var xx;xx=new Hashtable();xx['sda']='1';eval(xx['sda']); OK            
        }

        Func<String,Object> initJS(){
            System.CodeDom.Compiler.CodeDomProvider jcc;
            System.CodeDom.Compiler.CompilerParameters jcp;
            System.CodeDom.Compiler.CompilerResults jcr;
            System.Reflection.Assembly jas;
            object jis;
            string code;
            Type t_ii;

            code=@"@set @debug(off)
                import System;
                import System.Collections;
                import System.Collections.Generic;
                package internal_namespace{class internal_class{
                    public function internal_method(_code:String):Object{
                        return eval(_code);
                    }
                }
            }";

            jcc=Microsoft.JScript.JScriptCodeProvider.CreateProvider("JScript");
            jcp=new System.CodeDom.Compiler.CompilerParameters();
            jcp.CompilerOptions="/fast-";
            jcp.GenerateExecutable=false;
            jcp.GenerateInMemory=true;
            jcp.IncludeDebugInformation=false;
            jcp.ReferencedAssemblies.Add("System.dll");
            jcp.ReferencedAssemblies.Add("System.Core.dll");
            jcp.WarningLevel=4;
            jcr=jcc.CompileAssemblyFromSource(jcp,code);
            jas=jcr.CompiledAssembly;
            jis=jas.CreateInstance("internal_namespace.internal_class");

            t_ii=jas.GetType("internal_namespace.internal_class");
            return (s1)=>t_ii.InvokeMember("internal_method",System.Reflection.BindingFlags.InvokeMethod,null,jis,new object[]{s1});
        }//initJS

        Object initCS(){
            var v1= Microsoft.CSharp.CSharpCodeProvider.CreateProvider("CSharp");
            System.CodeDom.Compiler.CompilerParameters v2=new System.CodeDom.Compiler.CompilerParameters();
            v2.GenerateExecutable=false;
            v2.GenerateInMemory=true;
            v2.IncludeDebugInformation=false;
            v2.WarningLevel=4;
            v2.ReferencedAssemblies.Add("System.dll");
            v2.ReferencedAssemblies.Add("System.Core.dll");

            string _code="public Hashtable2 HT;"+
                "public void init(){"+
                    "HT=new Hashtable2();"+
                    "HT[\"foo\"]=\"1\";"+
                    "HT[\"bar\"]=\"HASH('HT','foo')\";"+
                "}";

            var v3="using System;using System.Collections;using System.Collections.Generic;"+
                    "namespace internal_namespace{public class Hashtable2:Hashtable{"+
                        "public Hashtable2():base(){} public Hashtable2(int N):base(N){}"+
                        "public Object ITEM(Object K){return this[K];} }"+
                    "[Serializable]public class internal_class{"+
                        "public internal_class(){}"+
                        _code+
                        "\n}}";

            var v4=v1.CompileAssemblyFromSource(v2,v3);
            var v5=v4.CompiledAssembly;
            var v6=v5.GetType("internal_namespace.internal_class");
            var v7=v5.CreateInstance("internal_namespace.internal_class");

            return v7;
        }//initCS
    }//class CS2JS
}//namespace so_redux

スローされる例外は「範囲外のインデックス」であり、JScriptからスローされます。問題?配列がないということです!

このコードの機能:最初に、実行時にevalを「エクスポート」するクラスをコンパイルすることによってJScriptインタープリターが初期化されます(dllを実行できますが、この場合は実行しませんでした)。
次に、C#アセンブリがコンパイルされます。これは、一部のユーザーコードを「エクスポート」するアセンブリです(initCSの変数_codeは、元々テキストファイルを読み取ることによってロードされます)。
新しくコンパイルされたクラスの初期化(init()の呼び出し)の後、相互作用する2つのアセンブリ(JScriptとC#)が必要なので、それらの間でデータを渡す必要があり、AppDomainを使用することを考えました。
注:C#アセンブリでは、Hashtable2が定義されています。これは、共通プロパティthis []の代わりに使用できるITEMメソッドをそこに配置したためです。このようにして、デバッグが容易になります(たとえば、値にアクセスするときに聖なるMessageBoxを表示することによって) )。
そこで、initCSでインスタンス化されたクラスをJScriptに渡し、JScriptが内部ハッシュテーブル(HT)を読み取ります。私がする必要があるのは、ハッシュテーブル内のデータを評価することです。これは、データが動的に変更できるはずだからです。
ハッシュテーブルから取得されていない文字列を評価すると、すべてが正常に機能します。ハッシュテーブルにあるものをすべて取得してevalに渡すと、例外が発生します。注意:文字列は完全に同じであり(Equalsと比較しても)、機能します。違いは、文字列がどこから来たのかだけです。
JScript関数edataがハッシュテーブルから取得した文字列を評価するとき、JScriptは「範囲外のインデックス」と言いますが、私が言っていたように、そこには配列がありません...(そしておそらく問題はまさにそれです、dunno) 。
私はJScriptに制限があることを認めているので、誰かがWTFが進行中であることを理解するのを手伝ってくれるなら、私は本当に幸せです。

4

1 に答える 1

0

JScript 関数を分割する一時的な解決策/回避策:

    xc=@"function odata(fieldname:String,ival:String):Object{
            var sob=System.AppDomain.CurrentDomain.GetData('trespasser');
            var v1=sob.GetType().GetField(fieldname).GetValue(sob);

            return v1.ITEM(ival);
        }
        odata('HT','bar');";
    res=js_eval(xc);

    xc=@"function HASH(s1:String,s2:String):Object{
            var sob=System.AppDomain.CurrentDomain.GetData('trespasser');
            var q1=sob.GetType().GetField(s1).GetValue(sob);
            return q1.ITEM(s2);
        }
        eval("+res.ToString()+");";
    res=js_eval(xc);

しかし、誰かが最初の例でなぜ間違っているのか本当にわかっているなら、私に説明してください!

于 2013-01-04T22:02:44.523 に答える