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

上一篇研究了如何做到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输出)

>>JSCALL
CS CALL!!
>>Hello CS
CS 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";
        }
    }

再执行:

>>JSCALL
CS 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

谢谢观赏~

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-08 22:38:58

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

.Net 与 Javascript 混合编程系列

之前的文章有提到 edge 和 nodejs 交互,通过node的模块为C# 提供一些扩展,这个还是比较方便.这里说下为什么要使用js. 1.SharpKit是一个用于在编译时将C#语言转换为JavaScript的工具. 从试用上来说还是比较强大的,基本上支持大部分语法. 2.c# 虽然是比较强大的,但是在一些方面还是比较薄弱的,而且在一些平台上还有些限制. 比如 ios 平台上unity3d 不能做到热更新,当然大部分时间都是用不到热更新的.但是如果想用的时候能用还是不错的. 要解决的问题?

ATL - JavaScript混合编程

JavaScript混合编程- ATL 最后更新日期:2014-5-10 环境:Windows8.1 64bit英文版,Visual Studio 2013 Professional Update1英文版 阅读前提:COM的基本概念 内容简介 ATL(ActiveTemplate Library)是微软为了简化COM编程提供的一套C++模板,这里介绍如何用ATL建立一个简单的轻量级COM服务供JavaScript脚本调用,使我们对ATL的使用有个概念. Hello,World 使用Adminis

Javascript模块化编程系列三: CommonJS &amp; AMD 模块化规范描述

CommonJS Module 规范 CommonJS 的模块化规范描述在Modules/1.1.1 中 目前实现此规格的包有: Yabble,CouchDB,Narwhal (0.2), Wakanda, TeaJS (formerly v8cgi), CommonScript, PINF JS Loader, SeaJS, ArangoDB, sorrow.js 注意,这里并没有找到 requireJS,因为它使用的是AMD规范. 此规范定义的具体内容包括: Requirerequire是一

javascript 高级编程系列 - 基本数据类型

javascript中的基本数据类型包括: Undefined, Null, Boolean, Number, String 5种数据类型 1. Undefined 类型 (只有一个值 undefined, 常被用来表示未初始化的变量) 如果一个变量未进行初始化则它的初始值为undefined, 数据类型为Undefined var myVar; myVar === undefined               // return true typeof myVar === 'undefine

javascript 高级编程系列 - 函数

一.函数创建 1. 函数声明 (出现在全局作用域,或局部作用域) function add (a, b) { return a + b; } function add(a, b) { return add1(a,b); function add1(m, n) { return m + n; } }    2. 函数表达式 作为普通变量 var add = function (a, b){ return a + b; }; 作为对象方法 var obj = { value: 0, add: fun

解决问题1:可以从桌面显示到FORM MFC/HALCON混合编程系列一_打开图像_简单处理_

没法爱上新浪  转载:http://blog.sina.com.cn/s/blog_812e326f010110og.html 从图1到图2 图1(在桌面显示了) open_window(0,0, Width/2, Height/2,0,"visible","",&WindowHandle); 更改为: Hlong MainWndID =(Hlong) m_hWnd; open_window(0,0, Width/2, Height/2,MainWndID,

Javascript模块化编程(三):require.js的用法

作者: 阮一峰 日期: 2012年11月 7日 这个系列的第一部分和第二部分,介绍了Javascript模块原型和理论概念,今天介绍如何将它们用于实战. 我采用的是一个非常流行的库require.js. 一.为什么要用require.js? 最早的时候,所有Javascript代码都写在一个文件里面,只要加载这一个文件就够了.后来,代码越来越多,一个文件不够了,必须分成多个文件,依次加载.下面的网页代码,相信很多人都见过. <script src="1.js"></s

Javascript模块化编程(三):require.js的用法(转)

这个系列的第一部分和第二部分,介绍了Javascript模块原型和理论概念,今天介绍如何将它们用于实战. 我采用的是一个非常流行的库require.js. 一.为什么要用require.js? 最早的时候,所有Javascript代码都写在一个文件里面,只要加载这一个文件就够了.后来,代码越来越多,一个文件不够了,必须分成多个文件,依次加载.下面的网页代码,相信很多人都见过. <script src="1.js"></script> <script src

Javascript模块化编程(三):require.js的用法 作者: 阮一峰

声明:转载自阮一峰的网络日志 这个系列的第一部分和第二部分,介绍了Javascript模块原型和理论概念,今天介绍如何将它们用于实战. 我采用的是一个非常流行的库require.js. 一.为什么要用require.js? 最早的时候,所有Javascript代码都写在一个文件里面,只要加载这一个文件就够了.后来,代码越来越多,一个文件不够了,必须分成多个文件,依次加载.下面的网页代码,相信很多人都见过. <script src="1.js"></script>