草庐IT

c# - 通过 COM 从 JavaScript 将 C# 类实例传回托管代码

coder 2024-07-25 原文

下面的代码显示了我的问题的基本轮廓。我在一个表单中托管一个 WebBrowser 控件,并提供一个具有两种方法的 ObjectForScripting:GiveMeAGizmoGiveMeAGizmoUser。两种方法都返回各自的类实例:

[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 类型。它抛出以下错误:

Unable to cast COM object of type 'System.__ComObject' to interface type 'Gizmo'

不确定如何继续,我尝试了一些其他的事情:

  • 安全转换 Gizmo g = oGizmo as Gizmo;(gnull)
  • 让类实现IDispatch 并调用InvokeMember,如explained here .成员“名称”为 null

我需要它来处理低于 4.0 的 .NET 框架版本,所以我不能使用 dynamic。有人知道我怎样才能让它工作吗?

最佳答案

真有趣。当我们在 doSomethingWith 中接收到 oGizmo 对象时,它的类型是 Windows Runtime Object。此行为在 JavaScript 和 VBScript 之间是一致的。

现在,如果我们在 GiveMeAGizmo() 方法的返回值上显式指定 MarshalAs(UnmanagedType.IUnknown)一切正常,对象可以在 doSomethingWith 中转换回 Gizmo:

[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.IDispatchUnmanagedType.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(); }

这只是一个猜测,但我认为这种行为可能与 .NET 安全权限集有关,由 WebBrowser.ObjectForScripting 强加。 .

关于c# - 通过 COM 从 JavaScript 将 C# 类实例传回托管代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21120192/

有关c# - 通过 COM 从 JavaScript 将 C# 类实例传回托管代码的更多相关文章

  1. ruby - 如何在 buildr 项目中使用 Ruby 代码? - 2

    如何在buildr项目中使用Ruby?我在很多不同的项目中使用过Ruby、JRuby、Java和Clojure。我目前正在使用我的标准Ruby开发一个模拟应用程序,我想尝试使用Clojure后端(我确实喜欢功能代码)以及JRubygui和测试套件。我还可以看到在未来的不同项目中使用Scala作为后端。我想我要为我的项目尝试一下buildr(http://buildr.apache.org/),但我注意到buildr似乎没有设置为在项目中使用JRuby代码本身!这看起来有点傻,因为该工具旨在统一通用的JVM语言并且是在ruby中构建的。除了将输出的jar包含在一个独特的、仅限ruby​​

  2. ruby - 通过 rvm 升级 ruby​​gems 的问题 - 2

    尝试通过RVM将RubyGems升级到版本1.8.10并出现此错误:$rvmrubygemslatestRemovingoldRubygemsfiles...Installingrubygems-1.8.10forruby-1.9.2-p180...ERROR:Errorrunning'GEM_PATH="/Users/foo/.rvm/gems/ruby-1.9.2-p180:/Users/foo/.rvm/gems/ruby-1.9.2-p180@global:/Users/foo/.rvm/gems/ruby-1.9.2-p180:/Users/foo/.rvm/gems/rub

  3. ruby-on-rails - Rails 源代码 : initialize hash in a weird way? - 2

    在rails源中:https://github.com/rails/rails/blob/master/activesupport/lib/active_support/lazy_load_hooks.rb可以看到以下内容@load_hooks=Hash.new{|h,k|h[k]=[]}在IRB中,它只是初始化一个空哈希。和做有什么区别@load_hooks=Hash.new 最佳答案 查看rubydocumentationforHashnew→new_hashclicktotogglesourcenew(obj)→new_has

  4. ruby - 通过 erb 模板输出 ruby​​ 数组 - 2

    我正在使用puppet为ruby​​程序提供一组常量。我需要提供一组主机名,我的程序将对其进行迭代。在我之前使用的bash脚本中,我只是将它作为一个puppet变量hosts=>"host1,host2"我将其提供给bash脚本作为HOSTS=显然这对ruby​​不太适用——我需要它的格式hosts=["host1","host2"]自从phosts和putsmy_array.inspect提供输出["host1","host2"]我希望使用其中之一。不幸的是,我终其一生都无法弄清楚如何让它发挥作用。我尝试了以下各项:我发现某处他们指出我需要在函数调用前放置“function_”……这

  5. ruby-on-rails - 如何使用 instance_variable_set 正确设置实例变量? - 2

    我正在查看instance_variable_set的文档并看到给出的示例代码是这样做的:obj.instance_variable_set(:@instnc_var,"valuefortheinstancevariable")然后允许您在类的任何实例方法中以@instnc_var的形式访问该变量。我想知道为什么在@instnc_var之前需要一个冒号:。冒号有什么作用? 最佳答案 我的第一直觉是告诉你不要使用instance_variable_set除非你真的知道你用它做什么。它本质上是一种元编程工具或绕过实例变量可见性的黑客攻击

  6. ruby 正则表达式 - 如何替换字符串中匹配项的第 n 个实例 - 2

    在我的应用程序中,我需要能够找到所有数字子字符串,然后扫描每个子字符串,找到第一个匹配范围(例如5到15之间)的子字符串,并将该实例替换为另一个字符串“X”。我的测试字符串s="1foo100bar10gee1"我的初始模式是1个或多个数字的任何字符串,例如,re=Regexp.new(/\d+/)matches=s.scan(re)给出["1","100","10","1"]如果我想用“X”替换第N个匹配项,并且只替换第N个匹配项,我该怎么做?例如,如果我想替换第三个匹配项“10”(匹配项[2]),我不能只说s[matches[2]]="X"因为它做了两次替换“1fooX0barXg

  7. ruby - 通过 ruby​​ 进程共享变量 - 2

    我正在编写一个gem,我必须在其中fork两个启动两个webrick服务器的进程。我想通过基类的类方法启动这个服务器,因为应该只有这两个服务器在运行,而不是多个。在运行时,我想调用这两个服务器上的一些方法来更改变量。我的问题是,我无法通过基类的类方法访问fork的实例变量。此外,我不能在我的基类中使用线程,因为在幕后我正在使用另一个不是线程安全的库。所以我必须将每个服务器派生到它自己的进程。我用类变量试过了,比如@@server。但是当我试图通过基类访问这个变量时,它是nil。我读到在Ruby中不可能在分支之间共享类变量,对吗?那么,还有其他解决办法吗?我考虑过使用单例,但我不确定这是

  8. ruby - 通过 RVM (OSX Mountain Lion) 安装 Ruby 2.0.0-p247 时遇到问题 - 2

    我的最终目标是安装当前版本的RubyonRails。我在OSXMountainLion上运行。到目前为止,这是我的过程:已安装的RVM$\curl-Lhttps://get.rvm.io|bash-sstable检查已知(我假设已批准)安装$rvmlistknown我看到当前的稳定版本可用[ruby-]2.0.0[-p247]输入命令安装$rvminstall2.0.0-p247注意:我也试过这些安装命令$rvminstallruby-2.0.0-p247$rvminstallruby=2.0.0-p247我很快就无处可去了。结果:$rvminstall2.0.0-p247Search

  9. ruby-on-rails - Enumerator.new 如何处理已通过的 block ? - 2

    我在理解Enumerator.new方法的工作原理时遇到了一些困难。假设文档中的示例:fib=Enumerator.newdo|y|a=b=1loopdoy[1,1,2,3,5,8,13,21,34,55]循环中断条件在哪里,它如何知道循环应该迭代多少次(因为它没有任何明确的中断条件并且看起来像无限循环)? 最佳答案 Enumerator使用Fibers在内部。您的示例等效于:require'fiber'fiber=Fiber.newdoa=b=1loopdoFiber.yieldaa,b=b,a+bendend10.times.m

  10. ruby-on-rails - Rails - 从另一个模型中创建一个模型的实例 - 2

    我有一个正在构建的应用程序,我需要一个模型来创建另一个模型的实例。我希望每辆车都有4个轮胎。汽车模型classCar轮胎模型classTire但是,在make_tires内部有一个错误,如果我为Tire尝试它,则没有用于创建或新建的activerecord方法。当我检查轮胎时,它没有这些方法。我该如何补救?错误是这样的:未定义的方法'create'forActiveRecord::AttributeMethods::Serialization::Tire::Module我测试了两个环境:测试和开发,它们都因相同的错误而失败。 最佳答案

随机推荐