问题: HostObjectToScript 在尝试执行传入函数时抛出异常
场景: WPF 应用程序嵌入了一个 WebView2 选项卡,并使用 CoreWebView2.AddHostObjectToScript() 公开了一个用于编写脚本的对象。我可以使用 Javascript 访问这个对象:
window.blah = chrome.webview.hostObjects.sync.blah_blah_external;
并毫无问题地调用函数。一切正常,直到我调用一个创建类并将函数作为参数传递给该类的函数。参数传入就好了,但是当代码尝试调用函数时,它会抛出 System.NotImplementedException 异常。在用 WebView2 替换基于 IE 的浏览器控件之前,这工作得很好,所以我希望这是我所缺少的一些简单的东西。
环境:
Host 对象是这样暴露的:
variablename.CoreWebView2.AddHostObjectToScript("blah_blah_external", new MYTABExternal(_tabHost));
主机对象如下所示:
namespace MYTAB
{
[ClassInterface(ClassInterfaceType.AutoDual)]
[ComVisibleAttribute(true)]
public class MYTABExternal
{
public void createTHING(String user, dynamic onError)
{
CLASSNAME currentCLASSNAME = new CLASSNAME(user, onError);
currentCLASSNAME.create();
}
}
}
抛出错误的类是这样设置的:
namespace MYTAB
{
public class CLASSNAME
{
protected String user;
protected dynamic onError;
public CLASSNAME(String user, dynamic onError)
{
this.user= user;
this.onError = onError;
}
public void create()
{
BackgroundWorker backgroundWorker = new BackgroundWorker();
backgroundWorker.WorkerSupportsCancellation = true;
backgroundWorker.WorkerReportsProgress = true;
backgroundWorker.DoWork -= backgroundWorker_DoWork;
backgroundWorker.DoWork += backgroundWorker_DoWork;
backgroundWorker.RunWorkerCompleted += backgroundWorker_RunWorkerCompleted; //Tell the user how the process went
RequestContext requestContext = EXTERNALLIBRARY.SharedContext.Instance;
backgroundWorker.RunWorkerAsync(requestContext);
}
/// <summary>
/// Fires when the background task is complete
/// </summary>
private void backgroundWorker_RunWorkerCompleted(object sender, System.ComponentModel.RunWorkerCompletedEventArgs e)
{
if (e.Cancelled)
{
this.onError("The creation process was cancelled"); // HERE'S THE EXCEPTION
}
}
...
调用该函数的javascript是:
window.setTimeout(function () {
window.blah.createTHING(btn.attr('data-requestor-user-id'), function (onErrorResponse) {
dialog.$modal.addClass('type-danger');
dialog.setMessage('<p>' + onErrorResponse + '</p>');
spinner.stop();
});
}, 1000);
异常堆栈跟踪是:
Exception thrown: 'System.NotImplementedException' in System.Dynamic.dll
Exception thrown: 'System.NotImplementedException' in System.Dynamic.dll
System.Transactions Critical: 0 : <TraceRecord xmlns="http://schemas.microsoft.com/2004/10/E2ETraceEvent/TraceRecord" Severity="Critical"><TraceIdentifier>http://msdn.microsoft.com/TraceCodes/System/ActivityTracing/2004/07/Reliability/Exception/Unhandled</TraceIdentifier><Description>Unhandled exception</Description><AppDomain>BLAH</AppDomain><Exception><ExceptionType>System.NotImplementedException, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</ExceptionType><Message>The method or operation is not implemented.</Message><StackTrace> at System.Runtime.InteropServices.Marshal.ThrowExceptionForHRInternal(Int32 errorCode, IntPtr errorInfo)
at System.Dynamic.ComRuntimeHelpers.GetITypeInfoFromIDispatch(IDispatch dispatch, Boolean throwIfMissingExpectedTypeInfo)
at System.Dynamic.IDispatchComObject.EnsureScanDefinedMethods()
at System.Dynamic.IDispatchComObject.System.Dynamic.IDynamicMetaObjectProvider.GetMetaObject(Expression parameter)
at System.Dynamic.DynamicMetaObject.Create(Object value, Expression expression)
at System.Dynamic.DynamicMetaObjectBinder.Bind(Object[] args, ReadOnlyCollection`1 parameters, LabelTarget returnLabel)
at System.Runtime.CompilerServices.CallSiteBinder.BindCore[T](CallSite`1 site, Object[] args)
at System.Dynamic.UpdateDelegates.UpdateAndExecute2[T0,T1,TRet](CallSite site, T0 arg0, T1 arg1)
at CallSite.Target(Closure , CallSite , Object , String )
at System.Dynamic.UpdateDelegates.UpdateAndExecuteVoid2[T0,T1](CallSite site, T0 arg0, T1 arg1)
at MyTab.CLASSNAME.backgroundWorker_RunWorkerCompleted(Object sender, RunWorkerCompletedEventArgs e) in C:\CLASSNAME.cs:line 145
at System.ComponentModel.BackgroundWorker.OnRunWorkerCompleted(RunWorkerCompletedEventArgs e)
at System.ComponentModel.BackgroundWorker.AsyncOperationCompleted(Object arg)
at System.Threading.QueueUserWorkItemCallback.WaitCallback_Context(Object state)
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem()
at System.Threading.ThreadPoolWorkQueue.Dispatch()
at System.Threading._ThreadPoolWaitCallback.PerformWaitCallback()</StackTrace><ExceptionString>System.NotImplementedException: The method or operation is not implemented.
at System.Runtime.InteropServices.Marshal.ThrowExceptionForHRInternal(Int32 errorCode, IntPtr errorInfo)
at System.Dynamic.ComRuntimeHelpers.GetITypeInfoFromIDispatch(IDispatch dispatch, Boolean throwIfMissingExpectedTypeInfo)
at System.Dynamic.IDispatchComObject.EnsureScanDefinedMethods()
at System.Dynamic.IDispatchComObject.System.Dynamic.IDynamicMetaObjectProvider.GetMetaObject(Expression parameter)
at System.Dynamic.DynamicMetaObject.Create(Object value, Expression expression)
at System.Dynamic.DynamicMetaObjectBinder.Bind(Object[] args, ReadOnlyCollection`1 parameters, LabelTarget returnLabel)
at System.Runtime.CompilerServices.CallSiteBinder.BindCore[T](CallSite`1 site, Object[] args)
at System.Dynamic.UpdateDelegates.UpdateAndExecute2[T0,T1,TRet](CallSite site, T0 arg0, T1 arg1)
at CallSite.Target(Closure , CallSite , Object , String )
at System.Dynamic.UpdateDelegates.UpdateAndExecuteVoid2[T0,T1](CallSite site, T0 arg0, T1 arg1)
at MyTab.CLASSNAME.backgroundWorker_RunWorkerCompleted(Object sender, RunWorkerCompletedEventArgs e) in C:\\CLASSNAME.cs:line 145
at System.ComponentModel.BackgroundWorker.OnRunWorkerCompleted(RunWorkerCompletedEventArgs e)
at System.ComponentModel.BackgroundWorker.AsyncOperationCompleted(Object arg)
at System.Threading.QueueUserWorkItemCallback.WaitCallback_Context(Object state)
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem()
at System.Threading.ThreadPoolWorkQueue.Dispatch()
at System.Threading._ThreadPoolWaitCallback.PerformWaitCallback()</ExceptionString><DataItems><Data><Key>ApplicationName</Key><Value>BLAH</Value></Data></DataItems></Exception></TraceRecord>