微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

在C#中创建COM / ActiveXObject,使用JScript,使用简单的事件

我想在C#中创建一个COM对象,并通过JScript的Idispatch使用它.那部分很简单.

我也想在COM对象上实现简单的回调,类似于在浏览器中可用的XmlHttpRequest对象公开的事件.该模型允许Javascript附加事件处理程序,如下所示:

var xmlhttp = new ActiveXObject("MSXML.XMLHTTP"); 
xmlhttp.onReadyStateChange = function() {
  ...
};

我想要我的客户端JScript代码看起来像这样:

var myObject = new ActiveXObject("MyObject.ProgId");
myObject.onMyCustomEvent = function(..args here..) { 
   ...
};

C#代码是什么样的?我想要一般情况 – 我想能够将参数传回给Javascript fn.

我看过How can I make an ActiveX control written with C# raise events in JavaScript when clicked?,但是那里的答案看起来真的很复杂,而且使用起来很复杂.

this article起,XMLHttpRequest事件似乎不是COM事件. onreadystatechange是Idispatch类型的属性.当脚本客户端将该属性设置为一个函数时,JScript会将其作为Idispatch对象进行编组.

剩下的唯一问题是从C#调用Idispatch.

解决方法

由于它是COM,首先定义一个接口.让我们保持简单.
[Guid("a5ee0756-0cbb-4cf1-9a9c-509407d5eed6")]
[InterfaceType(ComInterfaceType.InterfaceIsIdispatch)]
public interface IGreet
{
    [dispId(1)]
    string Hello(string name);

    [dispId(2)]
    Object onHello { get; set; }
}

然后,执行:

[ProgId("Cheeso.Greet")]
[ComVisible(true)]
[Guid("bebcfaff-d2f4-4447-ac9f-91bf63b770d8")]
[ClassInterface(ClassInterfaceType.None)]
public partial class Greet : IGreet
{
    public Object onHello { get; set; }

    public String Hello(string name)
    {
        var r = FireEvent();
        return "Why,Hello," + name + "!!!" + r;
    }
}

主要技巧是FireEvent方法.这对我有

private string FireEvent()
    {
        if (onHello == null) return " (N/A)";
        onHello
            .GetType()
            .InvokeMember
            ("",BindingFlags.InvokeMethod,null,onHello,new object [] {});

        return "ok";
    }

一起编译,注册regasm:

%NET64%\regasm.exe Cheeso.Greet.dll /register /codebase

…然后使用它从JScript像这样:

var greet = new ActiveXObject("Cheeso.Greet"),response;
greet.onHello = function() {
    WScript.Echo("onHello (Javascript) invoked.");
};
response = greet.Hello("Fred");
WScript.Echo("response: " + response);

有用.

您也可以从VBScript调用它:

Sub onHello ()
    WScript.Echo("onHello (VBScript) invoked.")
End Sub

Dim greet
Set greet = WScript.CreateObject("Cheeso.Greet")
greet.onHello = GetRef("onHello")
Dim response
response = greet.Hello("Louise")
WScript.Echo("response: " &  response)

要使用这种方法将参数从C#传递给JScript,我认为对象需要是Idispatch,但是当然你可以发回简单的值作为字符串,int等等,它们是被封送的,就像你所期望的那样.

例如,修改C#代码以发回自己的引用,并且编号42.

onHello
            .GetType()
            .InvokeMember
            ("",new object [] { this,42 });

那么你可以这样在jscript中

greet.onHello = function(arg,num) {
    WScript.Echo("onHello (Javascript) invoked.");
    WScript.Echo("  num = " + num + "  stat=" + arg.status);
};

或者在VBScript中如此:

Sub onHello (obj,num)
    WScript.Echo("onHello (VBScript) invoked. status=" & obj.status )
    WScript.Echo("  num= " & num)
End Sub

注意:您可以定义jscript事件处理函数来接受比调用“事件”时由C#对象发送的更少的参数.根据我的经验,您需要设计VBScript中的事件处理程序以明确接受正确的参数数量.

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐