Considerare la libreria COM compatibile con l'automazione in C#, riportata di seguito. Segue un modello COM comune di avere una coclasse di fabbrica visibile FooFactory che implementa ICreateFoos che crea un oggetto di tipo IFoo. FooFactory è la solo coclasse nella libreria dei tipi. (Il pattern factory è particolarmente utile con COM, poiché non consente costruttori parametrizzati).Perché questa classe COM C# è utilizzabile da VBScript ma non da JScript?
Nel codice qui sotto, ho constatato che non posso accedere all'interfaccia IFoo tornato da JScripta meno che io faccio la classe FooImpl ComVisible (decommentando righe di commento, questo fa sì che appaia come una coclasse nella digita libreria). Non c'è alcun problema con l'accesso da VBscript.
Cioè, posso correre questo VBScript:
set ff = CreateObject("jstest.FooFactory")
set foo = ff.CreateFoo(0)
foo.Foo
Ma questo funzionalmente identici JScript non riesce, con l'errore "C: \ temp \ jstest \ jstest.js (4, 1) Microsoft JScript errore di runtime: 'foo' è null o non un oggetto ":
var ff = new ActiveXObject("jstest.FooFactory");
var foo = ff.CreateFoo(0)
//WScript.Stdout.WriteLine(null==foo)
foo.Foo();
Se decommentare la linea, posso vedere che nulla == foo è falso.
Perché succede? E 'un errore? Notare che penso che questo sia un problema sia una combinazione di JScript e l'implementazione specifica di C#/.net (possibilmente di IDispatch), perché ho altri server COM simili - implementati in C++ - che non presentano questo problema da JScript.
Il problema scompare se annullo le righe commentate nel codice sottostante, rendendo FooImpl visibile come una coclasse - ma in particolare non voglio farlo perché non voglio esporre dettagli di implementazione. Una soluzione sembra essere quella di rendere FooImpl ComVisible, ma contrassegnare il suo costruttore interno, che impedisce ai client di essere in grado di creare CoCreate, ma non è elegante.
Sono in esecuzione su WinXP SP3 con Visual Studio 2005, .net 2 e sono stato in grado di riprodurre il problema su un'installazione completamente nuova di TinyXP su un VirtualBox (entrambi con Windows Script Host 5.7) e anche su Windows 7 Ultimate utilizza .net SDK 2.0, 3.0, 3.5 e 4.0 (WSH 5.8). Tutti i sistemi operativi erano a 32 bit.
Il codice libreria:
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");
}
}
}
è possibile compilare e registrare (potrebbe essere necessario eseguire come amministratore per regasm) questo con
csc /target:library jstest.cs
regasm /codebase jstest.dll
BTW - si prega di commentare se si è tentato di riprodurre questo problema ed è riuscito/non è riuscito a farlo. – bacar
Riprodotto con VS2010 (C# express) e Windows XP SP3. – arx