Betrachten Sie die automatisierungskompatible COM-Bibliothek in C#, wie unten angegeben. Es folgt ein gemeinsames COM-Muster mit einer sichtbaren Factory-Co-Klasse FooFactory, die ICreateFoos implementiert und ein Objekt vom Typ IFoo erzeugt. FooFactory ist die einzige Co-Klasse in der Typbibliothek. (Das Factory-Muster ist besonders nützlich bei COM, da parametrisierte Konstruktoren nicht berücksichtigt werden).Warum ist diese C# COM-Klasse aus VBScript, aber nicht aus JScript verwendbar?
In dem folgenden Code, ich finde, dass ich nicht die zurück IFoo Schnittstelle von jscript, wenn ich die FooImpl Klasse ComVisible machen zugreifen kann (von kommentierten Zeilen uncommenting; dies bewirkt, dass sie als Co-Klasse in der erscheinen Typbibliothek). Es gibt kein Problem beim Zugriff von VBScript.
Das heißt, kann ich diese VBScript ausführen:
set ff = CreateObject("jstest.FooFactory")
set foo = ff.CreateFoo(0)
foo.Foo
Aber diese funktional identisch JScript fehlschlägt, mit dem Fehler „C: \ temp \ jstest \ jstest.js (4, 1) Microsoft JScript Laufzeitfehler: ‚foo‘ ist null oder kein Objekt ":
var ff = new ActiveXObject("jstest.FooFactory");
var foo = ff.CreateFoo(0)
//WScript.Stdout.WriteLine(null==foo)
foo.Foo();
Wenn ich die Zeile Kommentar-, kann ich sehen, dass null == foo falsch ist.
Warum passiert das? Ist es ein Fehler? Beachten Sie, dass dies ein Problem ist, eine Kombination aus JScript und der C#/.net-spezifischen Implementierung (möglicherweise von IDispatch), weil ich andere ähnliche COM-Server - in C++ implementiert - habe, die dieses Problem von JScript nicht aufweisen.
Das Problem verschwindet, wenn ich die kommentierten Zeilen im Code unten auskommentieren, wodurch FooImpl als Co-Klasse sichtbar gemacht wird - aber ich möchte dies nicht tun, da ich die Implementierungsdetails nicht offenlegen will. Ein Workaround scheint zu sein, FooImpl ComVisible zu machen, aber seinen Konstruktor intern zu markieren, was Clients daran hindert, CoCreate zu erstellen, aber das ist nicht elegant.
Ich bin auf WinXP SP3 mit Visual Studio 2005, .net 2 ausgeführt und konnte das Problem bei einer völlig neuen Installation von TinyXP auf einer VirtualBox (beide mit Windows Script Host 5.7) reproduzieren, und auch auf Windows 7 Ultimate mit .net SDK 2.0, 3.0, 3.5 und 4.0 (WSH 5.8). Alle Betriebssysteme waren 32-Bit.
Der Bibliothekscode:
using System;
using System.Runtime.InteropServices;
[assembly: ComVisible(false)]
namespace jstest
{
[ComVisible(true)]
public interface ICreateFoos
{
IFoo CreateFoo(int importantNumber);
}
[ComVisible(true)]
public interface IFoo
{
void Foo();
}
[ComVisible(true)]
public class FooFactory : ICreateFoos
{
public IFoo CreateFoo(int importantNumber)
{ // in *this* version, we don't use importantNumber yet
return new FooImpl();
}
}
//[ComVisible(true)]
public class FooImpl : IFoo
{
public void Foo()
{
Console.WriteLine("Foo");
}
}
}
Sie können kompilieren und registrieren (Sie müssen als Admin regasm laufen) diese mit
csc /target:library jstest.cs
regasm /codebase jstest.dll
BTW - bitte kommentieren Sie, wenn Sie versucht haben, dieses Problem zu reproduzieren und es geschafft hat/fehlgeschlagen. – bacar
Reproduziert mit VS2010 (C# Express) und Windows XP SP3. – arx