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()),需要两个程序集(JScript和C#)交互,所以需要在它们之间传递数据,想到了使用AppDomain。
注意:在 C# 程序集中定义了一个 Hashtable2,因为我在其中放入了一个 ITEM 方法,可以用来替代公共属性 this[]: 以这种方式调试更容易(例如,在访问值时显示一个神圣的 MessageBox )。
因此,我将 initCS 中实例化的类传递给 JScript,而 JScript 读取内部 Hashtable (HT)。我需要做的是评估 Hashtable 中的数据,因为它应该能够动态地改变自己。
如果我 eval 不是从 Hashtable 中获取的字符串,一切正常——在我获取 Hashtable 中的任何内容并将其传递给 eval 的那一刻,就会发生异常。注意:字符串是完全相同的(即使将它们与 Equals 进行比较)并且它们有效,不同之处仅在于它们来自哪里。
当 JScript 函数 edata 对取自 Hashtable 的字符串进行求值时,JScript 会说“索引超出范围”,但正如我所说:我在那里看不到任何数组......(也许问题正是如此,不知道) .
我承认我在 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 回答