2012-06-24 11 views
9

C#' da bir COM nesnesi oluşturmak ve bunu JScript'ten IDispatch ile kullanmak istiyorum. Bu bölüm oldukça basit.C# 'da COM/ActiveXObject oluşturun, basit bir olayla JScript içinden kullanın,

Ayrıca, bir tarayıcıda kullanılabilen XmlHttpRequest nesnesi tarafından gösterilen olaya benzer COM nesnesinde basit geri aramalar uygulamak istiyorum.

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

benim istemci tarafı JScript kodu şöyle bakmak istiyorum: O model JavaScript böyle olay işleyicileri eklemek sağlar

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

nasıldır C# kodu görünüyor? Genel davayı istiyorum - Argümanları Javascript'e geri döndürmek istiyorum.


Ben How can I make an ActiveX control written with C# raise events in JavaScript when clicked? gördüm ama orada cevaplar gerçekten uygulanması karmaşık ve kullanımı karmaşık bak. this article itibaren


, XMLHttpRequest olaylar COM olayları değil gibi görünüyor. onreadystatechange, IDispatch türünde bir özelliktir. Komut istemcileri bu özelliği bir işleve ayarladıklarında, JScript bunu bir IDispatch nesnesi olarak sıralar.

Kalan tek sorun, kimliğini C# 'den çağırmaktır.

cevap

14

COM olduğundan, bir arabirim tanımlayarak başlayın. Basit tutalım.

[Guid("a5ee0756-0cbb-4cf1-9a9c-509407d5eed6")] 
[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)] 
public interface IGreet 
{ 
    [DispId(1)] 
    string Hello(string name); 

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

Sonra uygulanması:

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

ana hüner FireEvent yöntemdir. Bu benim için çalıştı.

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

... Ve sonra böyle JScript kullanılır:: Çalışır

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

hep birlikte, RegAsm ile kayıt

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

     return "ok"; 
    } 

Derleme.

Ayrıca VBScript diyebilirsiniz:

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) 

Ben nesneler ıdispatch olması gerektiğini düşünüyorum, bu yaklaşımla JScript'e C# geri parametrelerini geçirmek için, ama tabii ki geri basit gönderebilir değerler, beklediğiniz gibi sıralanmış olan dize, int, vb. olarak sıralanmıştı. Örneğin, kendisine bir başvuru göndermek için C# kodunu değiştirin ve 42 numaralı numarayı değiştirin.

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

Ya şöyle VBScript'teki:

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

Sonra şöyle jscript o alabilirsiniz

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

NB: Sen kabul edecek JScript olay işleyici işlevini tanımlayabilir "olay" ı çağırırken C# nesnesi tarafından gönderilen daha az sayıda args. Tecrübemde doğru sayıda argümanı açıkça kabul etmek için VBScript'te olay işleyicisini tasarlamanız gerekiyor.

+0

Bu geç bir ilişkili çağrı değil bir olaydır. .NET olaylarını açığa çıkarmak için [ComSourceInterfaces] özniteliğini kullanın. –

+3

Tam olarak. Bu bir COM olayı değildir, ancak bu kısıtlı senaryo için COM olaylarını kablolamaktan ve kullanmaktan daha basittir - bir nesne ve bu nesnenin bir kullanıcısı. Ve aslında, bir COM olayı olmasa da, programcılar bunu bir betik nesnesi için "bir olaya" yönelik ihtiyaçlarını karşılamak için doğru bir şekilde anlarlar. Bu nedenle, XMLHttpRequest, "onreadystatechange" için yaklaşımı kullanır. Bu da, "bir olay değil **" dir, ama kesinlikle milyonlarca dev tarafından bir olay olduğu anlaşılmaktadır. COM'un "olay" teriminin özel tanımı, bazı amaçlar için ilgisizdir. – Cheeso

+0

JScript'te ActiveXObject oluşturarak, başka bir yere tamamen '' ProjId' DLL adından gel "Cheeso.Greet" ',' Namespace.ClassName' veya çalışır? Ne denediğim önemli değil Her zaman "Otomasyon sunucusu nesne oluşturamaz" gibi görünüyor. –

2

Vay, vay! Kolay olabilir mi?

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

daha sonra bu yapı komutunu jscript On

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

(wsh) kullanın:

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

kaynak: msdn

tadını çıkarın!

İlgili konular