在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。


我已经看过了如何在点击时用JavaScript编写用C#引发事件的ActiveX控件? ,但那里的答案看起来实际上很复杂,而且使用起来很复杂。


从这篇文章中 ,似乎XMLHttpRequest事件不是COM事件。 onreadystatechangeIDispatch类型的属性。 当脚本客户端将该属性设置为函数时,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,但是当然你可以发送回作为字符串,整数等封送的简单值,这些值按照您的预期编组。

例如,修改C#代码以发回对自身的引用,以及数字42。

  onHello .GetType() .InvokeMember ("", BindingFlags.InvokeMethod, null, onHello, 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#对象发送的更少的args。 根据我的经验,您需要在VBScript中设计事件处理程序以显式接受正确数量的参数。

哇,哇! 可能很容易?

 using System; using System.EnterpriseServices; [assembly: ApplicationName("Calculator")] [assembly: ApplicationActivation(ActivationOption.Library)] public class Calculator : ServicedComponent { public int Add(int x, int y){ return (x + y); } } 

然后使用这些构建命令

  sn -k Calculator.snk csc /t:library Calculator.cs regsvcs Calculator.dll 

在jscript(wsh)上:

 c = new ActiveXObject("Calculator"); WScript.Echo(typeof(c)); // output: object WScript.Echo(c.Add(4,1)); // output: 5 

来源: msdn

请享用!

    Interesting Posts