Рассмотрим автоматизированную COM-библиотеку в C #, приведенную ниже. Он следует общепринятому шаблону COM с наличием видимого фабричного класса FooFactory, реализующего ICreateFoos, который создает объект типа IFoo. FooFactory - это класс only в библиотеке типов. (Заводской шаблон особенно полезен для 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 »равно нулю или не является объектом» :
var ff = new ActiveXObject("jstest.FooFactory");
var foo = ff.CreateFoo(0)
//WScript.Stdout.WriteLine(null==foo)
foo.Foo();
Если я раскомментирую строку, я вижу, что null == foo равно false.
Почему это происходит? Это ошибка? Обратите внимание, что я думаю, что это проблема - комбинация 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");
}
}
}
Вы можете скомпилировать и зарегистрировать (вам может потребоваться запустить от имени администратора, чтобы regasm) это с помощью
csc /target:library jstest.cs
regasm /codebase jstest.dll