C#< - > JScript:隐形数组?

时间:2013-01-04 14:47:02

标签: c#-4.0 .net-4.5 indexoutofboundsexception managed-jscript

我有一个复杂的程序,它给了我这个明显的幻象错误...
我将开始在这个我操纵的小例子程序的帮助下解释,它可以为任何运行它的人抛出我的美好例外。

<!-- 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

引发的异常是“index out of bounds”,它是从JScript抛出的。问题?这是没有数组!

这段代码正在做什么:首先通过在运行时编译一个“导出”eval的类来初始化JScript解释器(一个可以做一个dll,但在这种情况下我没有)。
然后编译一个C#程序集,一个“导出”一些用户代码的程序集(initCS中的变量_code最初是通过读取文本文件加载的。)
在初始化新编译的类(调用init())之后,我需要两个程序集(JScript和C#)进行交互,所以我需要在它们之间传递数据,我想到了使用AppDomain。 注意:在C#程序集中定义了一个Hashtable2,因为我在其中放入了一个ITEM方法,可以用来代替公共属性this []:这样调试就更容易了(例如,在访问值时显示一个神圣的MessageBox) )。
因此,我将在initCS中实例化的类传递给JScript,JScript读取内部Hashtable(HT)。我需要做的是评估Hashtable中的数据,因为它应该能够动态地改变它自己 如果我评估一个不是从Hashtable中获取的字符串,那么一切正常 - 在我接受Hashtable中的任何内容并将其传递给eval的那一刻,然后异常发生。注意:字符串绝对相同(甚至将它们与Equals进行比较)并且它们起作用,区别仅在于它们来自何处。
当JScript函数edata从Hashtable中删除一个字符串时,JScript会说“索引越界”,但正如我所说的那样:我没有看到任何数组......(也许问题就是那个,dunno) 。
我承认我在JScript中有自己的局限性,所以如果有人可以帮助理解WTF,我会非常高兴。

1 个答案:

答案 0 :(得分: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);

但如果有人真的知道第一个例子中为什么会出错,请解释我!