2012-06-24 16 views
9

私はC#でCOMオブジェクトを作成し、JScriptのIDispatch経由で使いたいと思っています。その部分はかなり簡単です。C#でCOM/ActiveXObjectを作成し、単純なイベントでJScriptから使用

私は、ブラウザで使用可能であるXMLHttpRequestオブジェクトによって公開されるイベントに似COMオブジェクトに、単純なコールバックを実装します。このモデルは、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を呼び出すことです。

答えて

14

これは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方法です。これは私のために働いた。

%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); 

をすべて一緒に、します。regasmに登録

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

     return "ok"; 
    } 

コンパイル。あなたはまた、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を返すようにします。そのよう

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

またはVBScriptで:

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

その後、あなたはそうのようなJScriptでそれを得ることができます

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

NB:あなたが受け入れるようにあなたのJScriptイベントハンドラ関数を定義することができますが"イベント"を呼び出すときにC#オブジェクトによって送信されるよりも少ない数の引数があります。私の経験上、正しい数の引数を明示的に受け入れるには、VBScriptでイベントハンドラを設計する必要があります。

+0

これはイベントではなく、遅延バインドコールです。 [ComSourceInterfaces]属性を使用して.NETイベントを公開します。 –

+3

正確に。これはCOMイベントではありませんが、この制限されたシナリオ(COMイベントを1つのオブジェクトとそのオブジェクトの1人のユーザー)に配線するよりも、構築して使用する方が簡単です。実際、COMイベントではありませんが、プログラマは、スクリプト可能なオブジェクトの「イベント」のニーズを満たすために正しく理解しています。これは、XMLHttpRequestが 'onreadystatechange'のためのアプローチを使用している理由です。それも、「**イベントではない」**ですが、確かに何百万人もの開発者によるイベントと理解されています。 COMの用語「イベント」の特定の定義は、いくつかの目的には関係ありません。 – Cheeso

+0

JScriptでActiveXObjectを作成するとき、 '' Cheeso.Greetは '' ProjId'、DLL名、 'Namespace.ClassName'または他の場所から来ますか?私が何を試しても、私はいつも "オートメーションサーバーはオブジェクトを作成できません"と思われます。 –

2

うわー、うわー!簡単だろうか?

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); } 
} 

は、JScriptの(WSH)では、これらのビルドコマンドに

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

を使用します。

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

ソース:msdn

はお楽しみに!

関連する問題