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 である必要があると思いますが、もちろん、期待どおりにマーシャリングされた string や int などとしてマーシャリングされた単純な値を送り返すことができます。
たとえば、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
注意: 「イベント」を呼び出すときに C# オブジェクトによって送信される引数よりも少ない引数を受け入れるように、jscript イベント ハンドラー関数を定義できます。私の経験では、正しい数の引数を明示的に受け入れるように VBScript でイベント ハンドラーを設計する必要があります。