object FuncCallJs(params object[] objs) { object toNativeObject(object obj) { if (obj == null) { return(obj); } var nobj = obj as NativeObjectInfo; if (nobj == null) { return(obj); } var r = WebBrowserInfo.GetNativeObject(nobj.Id, false); if (r == null) { throw new Exception($"本机对象不存在{nobj.Id}"); } return(r); } var browser = objs[0] as IWebBrowser; var script = objs[1].ToString(); var args = new string[objs.Length - 2]; for (var i = 0; i < args.Length; i++) { args[i] = NativeToJsValue(objs[i + 2]); } var toRun = $"return Tnelab.OnCallJs(({script})({string.Join(",", args)}))"; var result = browser.RunJs(toRun); var robj = JsonConvert.DeserializeObject <OnCallJsInfo>(result); if (!robj.Status) { throw new Exception(robj.Data.ToString()); } return(toNativeObject(robj.Data)); }
public (Type, object) JsValueInfoToNative(MapDataInfo dataInfo) { //处理范型Action和func //(Type, bool) IsAction(string nativeTypePath) //{ // Type r_nativeType = GetTypeByString(nativeTypePath); // bool lisAction = false; // if (nativeTypePath.IndexOf("System.Action<") >= 0) // { // lisAction = true; // //isFunc = false; // } // else if (nativeTypePath.IndexOf("Func<") >= 0) // { // lisAction = false; // //isFunc = true; // } // return (lnativeType, lisAction); //} //(Type, bool) NativeTypePathNotNull() //{ // Type lnativeType = null; // bool lisAction = false; // var ntPath = dataInfo.NativeTypePath; // var sIdx = ntPath.IndexOf("<"); // if (sIdx > 0) // { // var (nt, ia) = IsFx(ntPath, sIdx); // lnativeType = nt; // lisAction = ia; // } // else // { // lnativeType = Type.GetType(dataInfo.NativeTypePath); // lisAction = lnativeType == typeof(Action); // } // return (lnativeType, lisAction); //} object IsFunctionId(Type theNativeType, IWebBrowser theBrowser, string script) { var delegateInfo = theNativeType.GetMethod("Invoke"); bool theIsAction = delegateInfo.ReturnType == typeof(void); var paramTypes = delegateInfo.GetParameters().Select(it => it.ParameterType).ToArray(); List <ParameterExpression> paramExps = new List <ParameterExpression>(); List <Expression> vParamExps = new List <Expression>() { Expression.Convert(Expression.Constant(theBrowser), typeof(object)), Expression.Convert(Expression.Constant(script), typeof(object)) }; var len = paramTypes.Length; if (!theIsAction) { len -= 1; } for (var i = 0; i < len; i++) { var pt = paramTypes[i]; var pEx = Expression.Parameter(pt); paramExps.Add(pEx); vParamExps.Add(Expression.Convert(pEx, typeof(object))); } var arrayExp = Expression.NewArrayInit(typeof(object), vParamExps); LambdaExpression lambdaExpr; if (theIsAction) { var method = typeof(JsNativeInvokeContext).GetMethod("ActionCallJs", BindingFlags.NonPublic | BindingFlags.Instance); lambdaExpr = Expression.Lambda(theNativeType, Expression.Call(Expression.Constant(this), method, arrayExp), paramExps); } else { var method = typeof(JsNativeInvokeContext).GetMethod("FuncCallJs", BindingFlags.NonPublic | BindingFlags.Instance); lambdaExpr = Expression.Lambda(theNativeType, Expression.Convert(Expression.Call(Expression.Constant(this), method, arrayExp), paramTypes[paramTypes.Length - 1]), paramExps); } return(lambdaExpr.Compile()); } var tobj = WebBrowserInfo.GetNativeObject(MapInfo.Id, false) as TneForm; var browser = tobj == null?WebBrowserInfo.WebBrowser:tobj.WebBrowser; Type nativeType = null; object obj = null; //bool isFunc = false; //if (dataInfo.NativeTypePath != null) //{ // var (nt, ia) = NativeTypePathNotNull(); // nativeType = nt; // isAction = ia; //} if (dataInfo.DataType == MapDataType.NativeObjectId) { dynamic dobj = dataInfo.Value; long hcode = dobj.Id; var nobj = WebBrowserInfo.GetNativeObject(hcode, false); if (nobj == null) { throw new Exception($"本机对象不存在{hcode}"); } nativeType = nobj.GetType(); obj = new Tuple <long, object>(hcode, nobj); } else if (dataInfo.DataType == MapDataType.FunctionId) { nativeType = GetTypeByString(dataInfo.NativeTypePath); bool isAction = nativeType.FullName.StartsWith("System.Action"); bool isFunction = nativeType.FullName.StartsWith("System.Func"); obj = IsFunctionId(nativeType, browser, dataInfo.Value.ToString()); } else { nativeType = GetTypeByString(dataInfo.NativeTypePath); obj = dataInfo.Value; if (nativeType != null) { if (typeof(Enum).IsAssignableFrom(nativeType)) { obj = Enum.Parse(nativeType, dataInfo.Value.ToString()); } else if (nativeType == typeof(IntPtr)) { obj = JsonConvert.DeserializeObject(dataInfo.Value.ToString(), nativeType); } else { obj = Convert.ChangeType(dataInfo.Value, nativeType); } } } if (nativeType == null) { nativeType = obj.GetType(); } return(nativeType, obj); }
public string NativeToJsValue(object nVal) { string getJvByTypeName(string tName, object val) { string gv = null; switch (tName) { case "System.Char": case "System.String": gv = $"\"{val.ToString()}\""; break; case "System.Int16": case "System.UInt16": case "System.Int32": case "System.UInt32": case "System.Int64": case "System.UInt64": case "System.Double": case "System.Decimal": case "System.Single": case "System.Boolean": case "System.Byte": case "System.SByte": gv = val.ToString(); break; } return(gv); } string getJvByTuple(long id, string type_name, string genericInfo) { var jsTypeName = GetJsTypeName(type_name); var b = jsTypeName.IndexOf("<"); if (b != -1) { jsTypeName = jsTypeName.Substring(0, b); } var strBuilder = new StringBuilder(); strBuilder.Append("(async function(){") .AppendLine("let no=new Tnelab.NativeObjectInfo();") .AppendLine($"no.Id = {id};") .AppendLine($"no.GenericInfo = \"{genericInfo}\";") .AppendLine($"let ro=new {jsTypeName}(no);") .AppendLine($"let r=await ro.Ready();") .AppendLine($"r.TneMapGcObject_ = Tnelab.OnGetGC(r.TneMapNativeObjectId);") .AppendLine($"return r;") .Append("})()"); return(strBuilder.ToString()); } string getJvByMaped(string type_name, object val, string genericInfo) { var id = WebBrowserInfo.AddNativeObject(val, genericInfo); var jsTypeName = GetJsTypeName(type_name); var b = jsTypeName.IndexOf("<"); if (b != -1) { jsTypeName = jsTypeName.Substring(0, b); } var strBuilder = new StringBuilder(); strBuilder.Append("(async function(){") .AppendLine("let no=new Tnelab.NativeObjectInfo();") .AppendLine($"no.Id = {id};") .AppendLine($"no.GenericInfo = \"{genericInfo}\";") .AppendLine($"let ro=new {jsTypeName}(no);") .AppendLine($"let r=await ro.Ready();") .AppendLine($"r.TneMapGcObject_ = Tnelab.OnGetGC(r.TneMapNativeObjectId);") .AppendLine($"return r;") .Append("})()"); return(strBuilder.ToString()); } string getJv(string type_name, object val, string genericInfo) { string gv; gv = getJvByTypeName(type_name, val); if (gv != null) { return(gv); } var tVal = val as Tuple <long, object>;//是否一个已存在的js同步对象 var id = WebBrowserInfo.GetNativeObjectId(val); if (val == null) { gv = "undefined"; } else if (tVal != null)//是否一个已存在的js同步对象 { var tmpNO = WebBrowserInfo.GetNativeObject(id, true); gv = getJvByTuple(tVal.Item1, type_name, genericInfo); } else if (id != -1)//是否一个已存在的js同步对象 { var tmpNO = WebBrowserInfo.GetNativeObject(id, true); gv = getJvByTuple(id, type_name, genericInfo); } else if (GetJsTypeName(type_name) != null)//一个已经映射的js类型,但是未存在的js对象 { gv = getJvByMaped(type_name, val, genericInfo); } else//其他,直接序列 { var json = JsonConvert.SerializeObject(val); gv = $"{json}"; } return(gv); } var browser = this.WebBrowserInfo.WebBrowser; var type = nVal.GetType(); var typeName = $"{type.Namespace}.{type.Name}"; if (type.IsGenericType) { typeName = $"{typeName}`{type.GenericTypeArguments.Length}"; } var rv = getJv(typeName, nVal, GetGenericInfo(type)); return(rv); }