Рассмотрим совместимую с автоматизацией библиотеку COM на C #, приведенную ниже. Он следует общему шаблону COM, заключающемуся в наличии видимого фабричного кокласса FooFactory, реализующего ICreateFoos, который создает объект типа IFoo. FooFactory - это единственный компонентный класс в библиотеке типов. (Заводской шаблон особенно полезен с COM, поскольку он не позволяет использовать параметризованные конструкторы.)
В приведенном ниже коде я обнаружил, что не могу получить доступ к возвращаемому интерфейсу IFoo из jscript , если я не сделайте класс FooImpl ComVisible (раскомментировав закомментированные строки; это заставит его отображаться как компонентный класс в библиотеке типов). Нет такой проблемы с доступом к этому из VBscript .
То есть я могу запустить этот VBScript:
set ff = CreateObject("jstest.FooFactory")
set foo = ff.CreateFoo(0)
foo.Foo
Но этот функционально идентичный JScript не работает с ошибкой "C: \ temp \ jstest \ jstest.js (4, 1) Ошибка выполнения Microsoft JScript: 'foo' имеет значение null или не является объектом ":
var ff = new ActiveXObject("jstest.FooFactory");
var foo = ff.CreateFoo(0)
//WScript.Stdout.WriteLine(null==foo)
foo.Foo();
Если я раскомментирую строку, я вижу, что null == foo является ложным.
Почему это происходит? Это ошибка? Обратите внимание, что я думаю, что проблема заключается в комбинации JScript и специфической для C # / .net реализации (возможно, IDispatch), потому что у меня есть другие похожие COM-серверы, реализованные на C ++, которые не демонстрируют эту проблему из JScript.
Проблема исчезнет, если я раскомментирую закомментированные строки в приведенном ниже коде, сделав FooImpl видимым как кокласс, но я специально не хочу этого делать, потому что я этого не делаю. не хочу раскрывать детали реализации. Похоже, что обходной путь состоит в том, чтобы сделать FooImpl ComVisible, но пометить его конструктор как внутренний, что не позволяет клиентам создавать его совместно, но это вряд ли элегантно.
Я работаю на WinXP SP3 с Visual Studio 2005, .net 2, и смогли воспроизвести проблему при полностью новой установке TinyXP на VirtualBox (как с Windows Script Host 5.7), так и в Windows 7 Ultimate с использованием .net SDK 2.0, 3.0, 3.5 и 4.0 (WSH 5.8). Все операционные системы были 32-битными.
Код библиотеки:
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");
}
}
}
Вы можете скомпилировать и зарегистрировать (вам, возможно, придется запускать от имени администратора для регазмирования) это с помощью
csc /target:library jstest.cs
regasm /codebase jstest.dll