如何从C#主机应用程序执行JavaScript回调函数 [英] How can I execute Javascript callback function from C# host application

查看:448
本文介绍了如何从C#主机应用程序执行JavaScript回调函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我要创建在C#托管自定义网页的大部分GUI的应用。作为东道主,我想提供一个JavaScript API,以便嵌入网页可以访问某些主机应用程序提供的服务。

I'm creating an application in C# that hosts custom web pages for most of the GUI. As the host, I'd like to provide a javascript API so that the embedded web pages can access some of the services provided by the host application.

我已经能够得到使用WebBrowser.ObjectForScripting财产和执行脚本类此工作的简单情况。这个伟大的工程同步的JavaScript调用。然而,一些主机提供的操作是长时间运行,我想提供的JavaScript的能力,在操作完成时要叫回来。而这正是我遇到麻烦了。

I've been able to get the simple case for this working using the WebBrowser.ObjectForScripting property and implementing a scripting class. This works great for synchronous javascript calls. However, some of the operations that the host provides are long running and I'd like to provide the ability for the javascript to be called back when the operation completes. And this is where I'm running into trouble.

使用Javascript:

Javascript:

function onComplete( result )
{
    alert( result );
}

function start()
{
    window.external.LongRunningProcess( 'data', onComplete );
}

C#:

[ComVisible(true)]
public class ScriptObject
{
    public void LongRunningProcess( string data, <???> callback )
    {
        // do work, call the callback
    }
}

在JavaScript中的开始功能踢这整个过程了。我遇到的问题是,什么是回调的类型?我应该怎么称呼它从C#?

The 'start' function in javascript kicks this whole process off. The problem I'm having is, What is the type for the callback? And how should I call it from C#?

如果我使用的回调字符串类型,它编译和运行,但是从内LongRunningProcess方法回调实际上包含的onComplete功能的全部内容(即功能的onComplete(结果){警报(结果)}')

If I use the string type for callback, it compiles and runs, but from within the LongRunningProcess method callback actually contains the full contents of the onComplete function ( i.e. 'function onComplete( result ) { alert( result ) }' )

如果我用的对象类型,它回来作为一个COM对象。使用方法Microsoft.VisualBasic.Information.TypeName,则返回JScriptTypeInfo。但据我可以告诉大家,这不是一个真正的类型,也没有它的任何真正提到通过所有MSDN的。

If I use the object type, it comes back as a COM object. Using the Microsoft.VisualBasic.Information.TypeName method, it returns 'JScriptTypeInfo'. But as far as I can tell, that's not a real type, nor is there any real mention of it through all of MSDN.

如果我使用IReflect接口,它运行没有错误,但没有任何成员,字段,或者说我可以找到对象的属性。

If I use the IReflect interface, it runs without error, but there are no members, fields, or properties on the object that I can find.

一个变通是通过回调函数而不是函数本身的字符串名称(即window.external.LongRunningProcess('数据','的onComplete');)。我不知道如何按名称执行JavaScript的功能,但我宁愿没有在网页中所需的语法,它也不会与在JavaScript内联回调定义工作。

A work around would be to pass the string name of the callback function instead of the function itself ( i.e. window.external.LongRunningProcess( 'data', 'onComplete' ); ). I do know how to execute the javascript function by name, but I'd rather not have that syntax be required in the web pages, it also would not work with inline callback definitions in the javascript.

任何想法?

有关它的价值,我已经有了这个系统与嵌入式铬框架内工作,但我的工作,以港口code到WebBrowser控件,以避免重新分配铬的巨额大小。然而,正在开发的HTML页面最终将在Linux / Mac OSX上铬的地方仍然可能会被用来运行。

For what it's worth, I've already got this system working with the Chromium Embedded framework, but I'm working to port the code over to the WebBrowser control to avoid the hefty size of redistributing Chromium. However, the HTML pages being developed will eventually be run on Linux/Mac OSX where Chromium will probably still be used.

推荐答案

您可以使用反射为:

[ComVisible(true)]
public class ScriptObject
{
    public void LongRunningProcess(string data, object callback)
    {
        string result = String.Empty;

        // do work, call the callback

        callback.GetType().InvokeMember(
            name: "[DispID=0]",
            invokeAttr: BindingFlags.Instance | BindingFlags.InvokeMethod,
            binder: null,
            target: callback,
            args: new Object[] { result });
    }
}

您也可以尝试动态办法。这将会是它是否工作更优雅,但我还没有证实此事:

You could also try dynamic approach. It'd be more elegant if it works, but I haven't verified it:

[ComVisible(true)]
public class ScriptObject
{
    public void LongRunningProcess(string data, object callback)
    {
        string result = String.Empty;

        // do work, call the callback

        dynamic callbackFunc = callback;
        callbackFunc(result);
    }
}

[更新] 动态方法确实伟大工程,而且很可能是从C#回调的JavaScript的最简单的方法,当你有一个JavaScript函数对象。反射和动态允许调用一个匿名的JavaScript函数,以及。例如:

[UPDATE] The dynamic method indeed works great, and probably is the easiest way of calling back JavaScript from C#, when you have a JavaScript function object. Both Reflection and dynamic allow to call an anonymous JavaScript function, as well. Example:

C#:

public void CallbackTest(object callback)
{
    dynamic callbackFunc = callback;
    callbackFunc("Hello!");
}

的JavaScript

window.external.CallbackTest(function(msg) { alert(msg) })

这篇关于如何从C#主机应用程序执行JavaScript回调函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆