Почему этот COM-класс C # можно использовать из VBScript, но не из JScript?

Рассмотрим совместимую с автоматизацией библиотеку 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
6
задан bacar 20 September 2010 в 23:36
поделиться