.Net 与 Javascript 混合编程系列(如何穿透.net 和 js 的边界)

来源:互联网 发布:淘宝联盟怎么转淘口令 编辑:程序博客网 时间:2024/04/29 18:59

    上一篇研究了如何做到CS和JS互相透明访问的设想,经过一些实践,这里做出了一个小DEMO。

这里有第一个演示类:

    public class TestCSClass    {        public TestCSClass()        {        }        //如果可被重写则重载        public virtual object Method1()        {            Console.WriteLine("CS CALL!!");            return "Hello CS";        }    }

简单的C#代码,然后有个可重载的方法 Metod1


    [SharpKit.JavaScript.JsType(SharpKit.JavaScript.JsMode.Clr, PreCode = @"try{if (typeof (global.JsTypes) != 'undefined') {    JsTypes = global.JsTypes;}}catch (e) {}"        )]    public class TestJSClass : TestCSClass    {        public string Arg1 { get; set; }        public void FunA(string arg)        {                    }        public TestJSClass()        {        }    }
这是将要生成JS的类,继承与TestCSClass,有个独有的属性,并且多了一个字段,并且重载了一个方法。

然后是代理JS类,用于绑定C#对象并且拥有一些继承类的基础信息

   //C# 代理类    namespace Proxy    {        //JS代理类        [SharpKit.JavaScript.JsType(TargetType = typeof (CsLibForJS.TestCSClass))]        public class TestCSClass        {            public string __BaseTypeName = "CsLibForJS.TestCSClass";            private object _ExtObject = null;            public TestCSClass()            {               _ExtObject = ClrHelper.CallCtor(this);            }            public virtual object Method1()            {               return ClrHelper.CallClr(_ExtObject, "Method1");            }        }            }
当然这个也是C#的,不然你编译不过去。。

CallClr 就是个反射调用(性能啥的以后再说。。)

我们看看2个类生成的JS代码:

/* Generated by SharpKit 5 v5.4.4 */try{if (typeof (global.JsTypes) != 'undefined') {    JsTypes = global.JsTypes;}}catch (e) {}if (typeof(JsTypes) == "undefined")    var JsTypes = [];var CsLibForJS$TestJSClass = {    fullname: "CsLibForJS.TestJSClass",    baseTypeName: "CsLibForJS.TestCSClass",    assemblyName: "CsLibForJS",    Kind: "Class",    definition: {        ctor: function (){            this._Arg1 = null;            CsLibForJS.TestCSClass.ctor.call(this);        },        Arg1$$: "System.String",        get_Arg1: function (){            return this._Arg1;        },        set_Arg1: function (value){            this._Arg1 = value;        },        FunA: function (arg){        }    }};JsTypes.push(CsLibForJS$TestJSClass);var CsLibForJS$Proxy$TestCSClass = {    fullname: "CsLibForJS.Proxy.TestCSClass",    baseTypeName: "System.Object",    assemblyName: "CsLibForJS",    Kind: "Class",    definition: {        ctor: function (){            this.__BaseTypeName = "CsLibForJS.TestCSClass";            this._ExtObject = null;            System.Object.ctor.call(this);            this._ExtObject = CsLibForJS.ClrHelper.CallCtor(this);        },        Method1: function (){            return CsLibForJS.ClrHelper.CallClr(this._ExtObject, "Method1");        }    }};JsTypes.push(CsLibForJS$Proxy$TestCSClass);
为了避免混淆,所以代理类的名字空间带,Proxy,在处理类关系的时候会在jsclr中替换掉。

然后我们开始第一个调用。。

首先从JS开始:

var csobj = new CsLibForJS.TestCSClass.ctor();var jsobj =new CsLibForJS.TestJSClass.ctor();log("JSCALL");log(csobj.Method1());log(jsobj.Method1());

new出一个基础类, new出一个继承类,一个代理类,

而jsobj中是没有 Method1的,执行,输出为:(>>开头为JS输出)

>>JSCALLCS CALL!!>>Hello CSCS CALL!!>>Hello CS

绑定了基础对象后,我们JS类可以直接有个属性指向C#的基础类,所以在调用当前方法的时候可以直接通过反射调用对象类中的方法。

然后我们在把JS类中改成重载方法1:

    public class TestJSClass : TestCSClass    {        public string Arg1 { get; set; }        public void FunA(string arg)        {                    }        public TestJSClass()        {        }        public override object Method1()        {            return "Hello JS";        }    }

再执行:

>>JSCALLCS CALL!!>>Hello CS>>Hello JS
我们已经从JS中覆盖了原有的Method1方法,(废话么- -。。。)

咱继续。。。从CS中调用CS方法,并且重载

新建个JS代理类:

 namespace JSProxy    {        public class TestCSClass : CsLibForJS.TestCSClass        {            public Jint.Native.Object.ObjectInstance __bindJsObject;            public TestCSClass()            {                            }            //重载的方法            public override object Method1()            {                //被重写                if (__bindJsObject.HasProperty("Method1"))                {                    return __bindJsObject.Get("Method1").As<Jint.Native.Function.FunctionInstance>().Call(__bindJsObject,new JsValue[0]);                }                else                {                    return base.Method1();                }            }        }    }

调用过程:

            TestCSClass localclass = new JSProxy.TestCSClass()            {                __bindJsObject =                    engine.Execute("new CsLibForJS.TestJSClass.ctor()")                        .GetCompletionValue()                        .As<Jint.Native.Object.ObjectInstance>()            };            Console.WriteLine("CSCALL:" + localclass.Method1());
执行:

CSCALL:Hello JS

看起来像重载了么,我们直接手改JS

删掉这句:

   public override object Method1()        {            return "Hello JS";        }

执行:

CSCALL:Hello CS

附送个性能测试:

 var sw = new Stopwatch();            sw.Start();            for (int i = 0; i < 10000*10; i++)            {                localclass = new JSProxy.TestCSClass()                {                    __bindJsObject = ctor.Construct(new JsValue[0])                };                localclass.Method1();            }            sw.Stop();            Console.WriteLine("loopTime:" + sw.ElapsedMilliseconds);

loopTime:6219


谢谢观赏~









0 0