make C#方法等待JS事件发生

时间:2017-06-09 17:03:15

标签: javascript c# cefsharp

简介

我正在编写一个C#和JavaScript代码需要协同工作的项目,因此我决定使用CefSharp,因为它保证了最新的JS功能(与WebView相比)。

目标

现在我需要创建一个异步C#方法,它会调用异步JS函数,然后等待它完成。问题是JavaScript没有await关键字之类的内容,因此所有内容都是根据事件定义的。

这就是Javascript代码的样子:

var name1 = "A";
var name2 = "B";

library.renameObject("A","B");
library.onrename = function(from, to){
  if(from === "A"){
    //let C# know
  }
}

理想情况下,C#代码应该是这样的:

class FooObject
{
  string Name;
  async Task Rename(string newName)
  {
    await mainFrame.EvaluateScriptAsync(@"
      //The JS code
    ");
    Name = newName;
  }
}

问题

起初我以为使用任务/承诺会完成这项工作,但经过一些测试后我发现在JS和C#之间传递对象是不可能的。

这意味着当我尝试将TaskCompletionSource传递给IJavascriptCallback时,我得到了

  

System.NotSupportedException:无法将复杂类型序列化为Cef列表

然后我尝试从JavaScript代码返回Promise,但在C#中我总是得到null

不良解决方案

我知道使用反射,代理和Dictionary<int, WeakRef<object>>我可以提供一个接口,这样就可以从JavaScript中访问任何C#对象,这种方式与使用实际的JS对象无法区分。方法是:

  1. 使用唯一键
  2. 将字典中的C#对象保存(弱化)
  3. 使用Reflection创建方法,将唯一键作为参数,并允许读取字段和调用对象的方法
  4. 使用RegisterJsObject
  5. 将这些方法公开给JavaScript
  6. 创建一个模仿普通JS对象的Proxy,并在后台调用暴露的C#方法。
  7. 这个解决方案的坏消息是,在JavaScript中没有析构函数/终结符,所以我无法控制V8 GC。这意味着C#对象将永远保留在那里(内存泄漏)或过早收集.Net GC(空指针异常)。

0 个答案:

没有答案