基于JSBinding+SharpKit如何分析Delegate
这篇文章给大家介绍基于JSBinding+SharpKit如何分析Delegate,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。
以 NGUI 的 UIEventListener 为例:
有一个类:
using SharpKit.JavaScript; using UnityEngine; using System.Collections; [JsType(JsMode.Clr,"../StreamingAssets/JavaScript/SharpKitGenerated/z_temp/test0610.javascript")] public class test0610 : MonoBehaviour { public UIButton btn; void Start () { // 在此注册回调 UIEventListener.Get(btn.gameObject).onClick = this.OnClick; // (*) } void OnClick(GameObject go) { Debug.Log("onclick "); }}
这个类有一个 public UIButton btn; 变量,可以在 Inspector 里赋值。我们用这个类来响应 btn 的点击事件。重点就是第12行。
生成的JS如下:
1 if (typeof(JsTypes) == "undefined") 2 var JsTypes = []; 3 var test0610 = { 4 fullname: "test0610", 5 baseTypeName: "UnityEngine.MonoBehaviour", 6 assemblyName: "SharpKitProj", 7 Kind: "Class", 8 definition: { 9 ctor: function (){10 this.btn = null;11 UnityEngine.MonoBehaviour.ctor.call(this);12 },13 Start: function (){14 UIEventListener.Get(this.btn.get_gameObject()).onClick = $CreateDelegate(this, this.OnClick); // (*)15 },16 Update: function (){17 },18 OnClick: function (go){19 UnityEngine.Debug.Log$$Object("onclick ");20 }21 }22 };23 JsTypes.push(test0610);
看 JS代码 第14行,将 onClick 赋值为 $CreateDelegate 的返回值
$CreateDelegate 的作用是返回一个函数,具体可以看 jsclr.javascript 文件里这个函数的定义。这里不讨论这个函数的实现细节,只要知道他返回一个函数就可以了。这个函数传到 C# 后就变成一个ID。
当然,如果要让这段JS可以正常执行,当然要将 UIEventListener 配置到 JSBindingSettings.classes 数组让他导出,来看一下 onClick 这个字段的C#代码:
1 public static UIEventListener.VoidDelegate UIEventListener_onClick_GetDelegate_member2_arg0(CSRepresentedObject objFunction) 2 { 3 if (objFunction == null || objFunction.jsObjID == 0) 4 { 5 return null; 6 } 7 UIEventListener.VoidDelegate action = (go) => 8 { 9 JSMgr.vCall.CallJSFunctionValue(0, objFunction.jsObjID, go);10 };11 return action;12 }13 static void UIEventListener_onClick(JSVCall vc)14 {15 if (vc.bGet) {16 UIEventListener _this = (UIEventListener)vc.csObj;17 var result = _this.onClick;18 JSMgr.vCall.datax.setObject((int)JSApi.SetType.Rval, result);19 }20 else {21 UIEventListener _this = (UIEventListener)vc.csObj;22 _this.onClick = JSDataExchangeMgr.GetJSArg(()=>{23 if (JSApi.isFunctionS((int)JSApi.GetType.Arg))24 return UIEventListener_onClick_GetDelegate_member2_arg0(JSApi.getFunctionS((int)JSApi.GetType.Arg));25 else26 return (UIEventListener.VoidDelegate)vc.datax.getObject((int)JSApi.GetType.Arg);27 })28 ;29 }30 }
第22行在赋值 onClick 字段。因为 onClick 是 Delegate,所以赋值也要给他一个 Delegate,这个 Delegate 是由函数 UIEventListener_onClick_GetDelegate_member2_arg0 返回的(第1行)。
第24行首先调用 JSApi.getFunctionS(..) 获取 JS 函数 ID。CSRepresentedObject 只是对 JS 对象的一个封装而已。UIEventListener_onClick_GetDelegate_member2_arg0 拿到这个函数ID后,
构造了一个 UIEventListener.VoidDelegate 类型的 Delegate ,最终赋值给了 UIEventListener.onClick。
以上是比较简单的情况:将 JS 函数存储在 C#。
再来看一种情况,将 C# 函数存储在 JS。
// C#
1 TweenEasingCallback func = TweenEasingFunctions.GetFunction(this.EaseType );2 3 transform.TweenPosition()4 .SetEndValue( transform.position + ( Vector3.right * 9f ) )5 .SetDelay( 0.5f, false )6 .SetDuration( 1.33f )7 .SetEasing( func )8 .SetLoopType( TweenLoopType.Loop )9 .Play();
// JS代码
1 var func = DaikonForge.Tween.TweenEasingFunctions.GetFunction(this.EaseType); // get a delegate from C# (1)2 TweenTransformExtensions.TweenPosition$$Transform(this.get_transform())3 .SetEndValue(UnityEngine.Vector3.op_Addition(this.get_transform().get_position(), (UnityEngine.Vector3.op_Multiply$$Vector3$$Single(UnityEngine.Vector3.get_right(), 9))))4 .SetDelay$$Single$$Boolean(0.5, false)5 .SetDuration(1.33)6 .SetEasing(func) // give back to C# (2)7 .SetLoopType(1)8 .Play();
这种情况下也是要事先将 TweenEasingFunctions 配置到 JSBindingSettings.classes,让他导出,JS才可以使用。
// TweenEasingFunctions.GetFunction 的绑定代码:
1 static bool TweenEasingFunctions_GetFunction__EasingType(JSVCall vc, int argc) 2 { 3 int len = argc; 4 if (len == 1) 5 { 6 DaikonForge.Tween.EasingType arg0 = (DaikonForge.Tween.EasingType)JSApi.getEnum((int)JSApi.GetType.Arg); 7 JSMgr.vCall.datax.setObject((int)JSApi.SetType.Rval, DaikonForge.Tween.TweenEasingFunctions.GetFunction(arg0)); 8 } 9 10 return true;11 }
可以看到,当 JS 从 C# 获得一个 delegate 时,会调用 JSDataExchange.setObject 函数。
这里不贴出 setObject 的具体代码,请查看源代码。
在 setObject 函数中,会判断,如果这个对象是个 delegate,那么就创建一个 JSRepresentedObject 对象返回给 JS,同时保存这2者的对应关系。
JSRepresentedObject 的定义在 StreamingAssets/JavaScript/SharpKit/myclrhandler.javascript 最前面。
那么,JS拿到这个对象后,是无法使用的。因为他是C#这边的函数。他只能把这个东西再还给C#。请看上面JS代码标记 (2) 那一句。当他返回给C#时,C#可以根据之前存储的对应关系找到 Delegate。
关于基于JSBinding+SharpKit如何分析Delegate就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。