作者: 牛A与牛C之间 时间: 2013-12-12 分类: 技术文章 | 2条评论 | 编辑文章

主页 » 技术文章 » 第7篇:Xilium CefGlue 关于 CLR Object 与 JS 交互类库封装报告:全自动注册与反射方法分析

第6篇:Xilium CefGlue 关于 CLR Object 与 JS 交互类库封装报告:自动注册JS脚本+自动反射方法分析

本文转自“吾乐吧软件站”,原文链接:http://www.wuleba.com/?p=23624

感兴趣的,可以加入:WebKit/Blink 内核浏览器开发 QQ交流群:244840771

开发语言为:.NET/C++ 方向

5、 第五种方法,全自动注册与反射方法分析

5.1 实现过程:

(1)、定义一个DemoRenderProcessHandler,继承自CefRenderProcessHandler

(2)、重写DemoRenderProcessHandler里的OnWebKitInitialized ( )事件

(3)、定义一个BindingHandler,继承自CefV8Handler,核心代码

(4)、定义一个UnmanagedWrapper,继承自CefUserData,用来保存操作的对象object、对象属性、对象方法 等信息

(5)、定义一个PropertyAccessor,继承自CefV8Accessor,可通过PropertyAccessor的Get ()、Set ( )方法可以进行存取操作。当前操作的是哪个对象,就可以从这里获取

(6)、定义一个TypeUtil操作类,实现CefV8Value与object类型的相互转换

(7)、定义一个普通的类ExampleObject(这个类跟ExampleBv8Handler一样,只是不再需要继承CefV8Handle)

(8)、在BindingHandler里的Execute ( )事件中,通过反射,自动选择最合适的方法,进行调用,不再需要人工去写,几乎实现全自动

(9)、在OnWebKitInitialized ( )事件里面,调用自己封装的类库,直接访问CefRuntimeEx.RegisterJsObject ( )方法就可以自动注册,并且自动响应操作。

(10)、在 OnContextCreated ( ) 事件里面,进行数据绑定操作,这样,BindingHandler里的Execute ( )事件,才能知道是哪个对象调用的。

(11)、写一个网页,去前台通过JS调用

5.2 核心代码:

这个方法,是完成了前面四种方法后,外加死啃1天CEF的C++代码,发现了原生的JS注册机制,然后重写的,核心思想,依然是采用反射,但这次不需要生成对应的JS脚本代码,只需要直接注册属性、方法(具体注册逻辑,CEF会自动完成,所以不需要考虑,但本质上,CEF实现方式和之前的生成JS脚本是一样的),然后通过反射自动选择最合适的操作方法调用,为了减小文章篇幅,仅列出部分代码。

/// <summary>

/// DemoRenderProcessHandler.cs

/// </summary>

protected override void OnWebKitInitialized()

{

#region 调用自己封装的JS类库

CefRuntimeEx.RegisterJsObject(“exampleObject”, new ExampleObject());

#endregion 调用自己封装的JS类库

base.OnWebKitInitialized();

}

protected override void OnContextCreated(CefBrowser browser, CefFrame frame, CefV8Context context)

{

foreach (var kvp in CefRuntimeEx.GetObjects())

{

BindingHandler.Bind(kvp.Key, kvp.Value, context.GetGlobal()); //绑定方式一

//BindingHandler.Bind(kvp.Key, kvp.Value, context.GetGlobal(), false); //绑定方式二

}

base.OnContextCreated(browser, frame, context);

}

/// <summary>

/// BindingHandler.cs

/// </summary>

/// <summary>

/// 绑定数据并注册对象

/// 说明:已经过滤特殊名称,即不含系统自动生成的属性、方法

/// </summary>

/// <param name=”name”>对象名称</param>

/// <param name=”obj”>需要绑定的对象</param>

/// <param name=”window”>用于注册的V8 JS引擎对象,类似于整个程序的窗口句柄</param>

public static void Bind(string name, object obj, CefV8Value window)

{

var unmanagedWrapper = new UnmanagedWrapper(obj);

var propertyAccessor = new PropertyAccessor();

CefV8Value javascriptWrapper = CefV8Value.CreateObject(propertyAccessor);

javascriptWrapper.SetUserData(unmanagedWrapper);

var handler = new BindingHandler();

unmanagedWrapper.Properties = GetProperties(obj.GetType());

CreateJavascriptProperties(handler, javascriptWrapper, unmanagedWrapper.Properties);

HashSet<string> methodNames = GetMethodNames(obj.GetType());

CreateJavascriptMethods(handler, javascriptWrapper, methodNames);

window.SetValue(name, javascriptWrapper, CefV8PropertyAttribute.None);

}

/// <summary>

/// 创建JavaScript方法

/// </summary>

/// <param name=”handler”>处理程序</param>

/// <param name=”javascriptObject”>经过V8 JS引擎处理后的对象</param>

/// <param name=”methodNames”>方法键值对集合</param>

public static void CreateJavascriptMethods(CefV8Handler handler, CefV8Value javascriptObject, IEnumerable<String> methodNames)

{

var unmanagedWrapper = (UnmanagedWrapper) (javascriptObject.GetUserData());

foreach (string methodName in methodNames)

{

string jsMethodName = StringUtil.LowercaseFirst(methodName);

unmanagedWrapper.AddMethodMapping(methodName, jsMethodName);

string nameStr = jsMethodName;

javascriptObject.SetValue(nameStr, CefV8Value.CreateFunction(nameStr, handler), CefV8PropertyAttribute.None);

}

}

由于这部分代码较多,实现过程相当复杂,所以阐述下具体的实现流程,代码就不贴出来了,感兴趣的可以加入QQ群一起讨论!流程如下:

(1)、新建了一个BindingHandler.cs,这是整个封装的核心代码,继承自CefV8Handler

(2)、新建UnmanagedWrapper、PropertyAccessor、TypeUtil,各种协调操作

(3)、通过反射,找到对应的对象,并提取他的所有属性、方法

(4)、调用自己封装的方法,基于原生方法注册JS属性、方法。CEF提供的原生注册方式,就是这个方法CefV8Value.CreateFunction(nameStr, handler)

(5)、当我网页的上下文对象被创建时OnContextCreated ( ),则会重新触发Bind ( )方法

(6)、当网页的JS访问后台数据时,在BindingHandler里的Execute ( )事件中,通过反射,自动选择最合适的方法,进行调用。

5.3 评价总结:

优势:

(1)、自动注册JS对象

(2)、自动反射调用方法

(3)、彻底解决方法一、方法二、方法三残留的弊端问题

(4)、知道方法来源,所有操作“一对一”,不用担心重复问题

弊端:

(1)、由于C#、Javascript、CefV8Value,三者之间的数据类型存在较大跨度,会导致部分数据类型不工作,所以如果遇到特殊数据,尽可能使用string来操作。

(2)、由于是个人封装,可能存在一些没有考虑到的情况,如有问题,后期再完善。

备忘说明:

(1)、项目里面的代码,只保留了最新的那个第5种方法,不想有太多的“干扰代码,所以其他的“阶段性”成果代码已经被注释起来(公司项目,不提供代码);

(2)、这次封装,已经基本达到预期效果,接下来还要做其他的一些功能进行处理。

(3)、用户计算机必须安装Adobe Flash组件才能播放动画,关于这点,找到3个解决方案:

方法一:安装NPAPI版本的Flash组件(非IE版)之后,才能播放动画。访问 http://get.adobe.com/cn/flashplayer/otherversions/ 选择“Flash Player 11 for Other Browsers”。

方法二:如果想要直接集成到浏览器里去,程序目录下,创建一个“Plugins”文件夹,把“C:\Windows\SysWOW64\Macromed\Flash\NPSWF32_XXX.dll”,把这个DLL放到“Plugins”文件夹里去,就可以了。

方法三:直接注册PPAPI版本的Flash组件,注册语法如下:

“E:\XiliumCefGlueDemo\Bin\Xilium.CefGlue.Demo.WinForms.exe” –ppapi-out-of-process –register-pepper-plugins=”E:\XiliumCefGlueDemo\Bin\PepperFlash\pepflashplayer.dll;application/x-shockwave-flash”

from:http://www.wuleba.com/23626.html

【转】第7篇:Xilium CefGlue 关于 CLR Object 与 JS 交互类库封装报告:全自动注册与反射方法分析的更多相关文章

  1. 【转】第6篇:Xilium CefGlue 关于 CLR Object 与 JS 交互类库封装报告:自动注册JS脚本+自动反射方法分析

    作者: 牛A与牛C之间 时间: 2013-11-21 分类: 技术文章 | 暂无评论 | 编辑文章 主页 » 技术文章 » 第6篇:Xilium CefGlue 关于 CLR Object 与 JS ...

  2. 【转】第5篇:Xilium CefGlue 关于 CLR Object 与 JS 交互类库封装报告:自动注册JS脚本+委托回调方法分析

    作者: 牛A与牛C之间 时间: 2013-11-19 分类: 技术文章 | 暂无评论 | 编辑文章 主页 » 技术文章 » 第5篇:Xilium CefGlue 关于 CLR Object 与 JS ...

  3. 【转】第4篇:Xilium CefGlue 关于 CLR Object 与 JS 交互类库封装报告:委托回调方法分析

    作者: 牛A与牛C之间 时间: 2013-11-18 分类: 技术文章 | 暂无评论 | 编辑文章 主页 » 技术文章 » 第4篇:Xilium CefGlue 关于 CLR Object 与 JS ...

  4. 【转】3篇:Xilium CefGlue 关于 CLR Object 与 JS 交互类库封装报告:官方原生方法分析

    作者: 牛A与牛C之间 时间: 2013-11-17 分类: 技术文章 | 暂无评论 | 编辑文章 主页 » 技术文章 » 第3篇:Xilium CefGlue 关于 CLR Object 与 JS ...

  5. Xilium.CefGlue怎么使用Js调用C#方法

    第1篇:.NET多种WebKit内核/Blink内核浏览器初步测评报告http://www.wuleba.com/?p=23590 第2篇:Xilium CefGlue 关于 CLR Object 与 ...

  6. xilium CefGlue集成包

    最近很苦B的要做一个C#的HTM5项目,build了一下xilium CefGlue包,提供下载地址,供那些无法下载的同学们使用. http://yun.baidu.com/s/1slEdNEt

  7. Xilium.CefGlue利用XHR实现Js调用c#方法

    防外链 博客园原文地址在这里http://www.cnblogs.com/shen6041/p/3442499.html 引 Xilium CefGlue是个不错的cef扩展工程,托管地址在这里 ht ...

  8. CEF Xilium.CefGlue 在当前窗体中打开全部链接(防止弹窗)

    我们在使用Xilium.CefGlue编写浏览器应用程序时.对于嵌入的网页假设有链接会在新窗体打开.这种用户体验会非常差.因此我们须要改动程序,使全部链接都在当前窗体中打开. 首先引用Xilium.C ...

  9. 一步步学习javascript基础篇(3):Object、Function等引用类型

    我们在<一步步学习javascript基础篇(1):基本概念>中简单的介绍了五种基本数据类型Undefined.Null.Boolean.Number和String.今天我们主要介绍下复杂 ...

随机推荐

  1. 作业1-我的第一个博客&GuiHub简单练习

    自我介绍                   姓名:苗中峰(不要问有什么含义,翻着字典取的名,翻到什么字就取了什么字)                               性别:男(不解释) ...

  2. WebRTC学习资料大全

    在学习WebRTC,找了些资料,记录一下,供以后查询. 有些需要FQ才能看 WebRTC 介绍 官网在这里:https://webrtc.org/.然后这里有一个官方的Getting Started: ...

  3. Unity3D 创建动态的立方体图系统

    Unity3D 创建动态的立方体图系统 这一篇主要是利用上一篇的Shader,通过脚本来完成一个动态的立方体图变化系统. 准备工作如下: 创建一个新的场景.一个球体.提供给场景一个平行光,准备2个立方 ...

  4. android studio 中怎么使用adb无线调试

    之前再eclipse下进行安卓开发,但谷歌却抛弃了eclipse而力挺android studio开发环境,没办法只好跟着走. 在eclipse下开发时调试用adb无线方式特别方便,但是在androi ...

  5. dedecms 列表页调用自定义字段

    在列表附加字段中添加自己定义的字段 如: lwulr调用:{dede:list addfields="lwurl" channelid="1"}[field:l ...

  6. ZOJ Problem Set - 3640 Help Me Escape

    题目大意: 有n条路,选每条路的概率相等,初始能力值为f,每条路通过的难度值为ci,当能力值大于某条路A的难度值b时,能够成功逃离,花费时间ti,小于等于时,不能逃离,天数加一天,但能力值增加b. 给 ...

  7. CentOS6 Squid代理服务器的安装与配置

    代理服务器英文全称是Proxy Server,其功能就是代理网络用户去取得网络信息.Squid是一个缓存Internet 数据的软件,其接收用户的下载申请,并自动处理所下载的数据.当一个用户想要下载一 ...

  8. php 函数积累

    array_slice()<?php $a=array("red","green","blue","yellow" ...

  9. Codeforces Round #372 (Div. 2) A B C 水 暴力/模拟 构造

    A. Crazy Computer time limit per test 2 seconds memory limit per test 256 megabytes input standard i ...

  10. linux笔记_磁盘分区

    一.分区的意义 1.不同操作系统往往不可以同时装载在同一个分区,分区解决了不同操作系统装载在同一个物理硬盘的兼容性问题 2.机械硬盘盘片外圈读写速度相对内圈要快,分区可以把常用数据限制在读写速度较快的 ...