我的问题的基本概要显示在下面的代码中。我在表单中托管了一个WebBrowser控件,并为ObjectForScripting
提供了两种方法:GiveMeAGizmo
和GiveMeAGizmoUser
。两种方法都返回相应的类实例:
[ComVisible]
public class Gizmo
{
public string name { get; set; }
}
[ComVisible]
public class GizmoUser
{
public void doSomethingWith(object oGizmo)
{
Gizmo g = (Gizmo) oGizmo;
System.Diagnostics.Debug.WriteLine(g.name);
}
}
在JavaScript中,我创建了两个类的实例,但我需要将第一个实例传递给第二个实例上的方法。 JS代码看起来有点像这样:
var
// Returns a Gizmo instance
gizmo = window.external.GiveMeAGizmo(),
// Returns a GizmoUser instance
gUser = window.external.GiveMeAGizmoUser();
gizmo.name = 'hello';
// Passes Gizmo instance back to C# code
gUser.doSomethingWith(gizmo);
这是我撞墙的地方。我的C#方法GizmoUser.doSomethingWith()
无法将对象强制转换为Gizmo类型。它会引发以下错误:
无法将'System .__ ComObject'类型的COM对象转换为接口类型'Gizmo'
不确定如何继续,我尝试了其他一些事情:
Gizmo g = oGizmo as Gizmo;
(g
为null
)IDispatch
并调用InvokeMember
,explained here。成员“名称”为null
。我需要这个以使用低于4.0的.NET框架版本,所以我不能使用dynamic
。有谁知道我怎么能这样工作?
答案 0 :(得分:4)
多么有趣。当我们收到oGizmo
中的doSomethingWith
对象时,它的类型为Windows Runtime Object
。这种行为在JavaScript和VBScript之间是一致的。
现在,如果我们在MarshalAs(UnmanagedType.IUnknown)
方法的返回值上明确指定 GiveMeAGizmo()
,一切正常,则可以投射对象回到Gizmo
内的doSomethingWith
:
[ComVisible(true), ClassInterface(ClassInterfaceType.AutoDispatch)]
public class ObjectForScripting
{
[return: MarshalAs(UnmanagedType.IUnknown)]
public object GiveMeAGizmo()
{
return new Gizmo();
}
public object GiveMeAGizmoUser()
{
return new GizmoUser();
}
}
但是,如果我们指定UnmanagedType.IDispatch
或UnmanagedType.Struct
(将对象编组为COM VARIANT
的默认值),则问题又回来了。
因此,到目前为止,有一种解决方法,但对此类COM互操作行为没有合理的解释。
[更新] 下面还有一些实验。请注意获取gizmo1
成功的方式,而gizmo2
不是:
<强> C#强>:
// pass a Gizmo object to JavaScript
this.webBrowser.Document.InvokeScript("SetGizmo", new Object[] { new Gizmo()});
// get it back, this works
var gizmo1 = (Gizmo)this.webBrowser.Document.InvokeScript("GetGizmo");
// get a new Gizmo, via window.external.GiveMeAGizmo()
// this fails
var gizmo2 = (Gizmo)this.webBrowser.Document.InvokeScript("GetGizmo2");
<强> JavaScript的:强>
var _gizmo;
function SetGizmo(gizmo) { _gizmo = gizmo; }
function GetGizmo() { return _gizmo; }
function GetGizmo2() { return window.external.GiveMeAGizmo(); }
这只是猜测,但我认为这种行为可能与WebBrowser.ObjectForScripting
强加的.NET安全权限集有关。
答案 1 :(得分:0)
你需要做两件事
找出here所描述的对象类型。
使用Marshal.GetObjectForIUnknown提取实际对象(读到最后,有一个接口要实现)。