admin管理员组文章数量:1208155
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.
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:
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
}
}
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#?
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 ) }' )
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.
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.
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.
Any Ideas?
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.
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.
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:
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
}
}
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#?
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 ) }' )
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.
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.
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.
Any Ideas?
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.
Share Improve this question asked Jan 15, 2014 at 13:30 MrSlippersMrSlippers 4651 gold badge6 silver badges14 bronze badges 1 |2 Answers
Reset to default 17You can use Reflection for that:
[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);
}
}
[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) })
As @Frogmouth
noted here already you can pass callback function name to the LongRunningProcedure
:
function onComplete( result )
{
alert( result );
}
function start()
{
window.external.LongRunningProcess( 'data', 'onComplete' );
}
and when LongRunningProcedure
completes use .InvokeScript
as the following:
public void LongRunningProcess(string data, string callbackFunctionName)
{
// do work, call the callback
string codeStrig = string.Format("{0}('{1}')", callbackFunctionName, "{{ Your result value here}}");
webBrowser1.Document.InvokeScript("eval", new [] { codeStrig});
}
本文标签: How can I execute Javascript callback function from C host applicationStack Overflow
版权声明:本文标题:How can I execute Javascript callback function from C# host application - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1738755377a2110639.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
callback
like stringwindow.external.LongRunningProcess( 'data', 'onComplete');
and in c# you can create a fucntion with this name and perform it like a callback without use JS function in C# (but using a native C# function)... if comment isn't help you i'm sorry for loss time – Frogmouth Commented Jan 15, 2014 at 13:56