考虑下面给出的 C# 中与自动化兼容的 COM 库。它遵循一个常见的 COM 模式,即有一个可见的工厂 coclass FooFactory 实现 ICreateFoos,它创建一个 IFoo 类型的对象。 FooFactory 是类型库中唯一的 coclass。 (工厂模式对于 COM 特别有用,因为它不允许参数化构造函数)。
在下面的代码中,我发现我无法从 jscript 访问返回的 IFoo 接口(interface) 除非我使 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 runtime error: 'foo' is null or not an object ":
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,但将其构造函数标记为内部,这会阻止客户端能够 CoCreate 它,但这并不优雅。
我在带有 Visual Studio 2005、.net 2 的 WinXP SP3 上运行,并且能够在 VirtualBox(均使用 Windows Script Host 5.7)和 Windows 上全新安装 TinyXP 时重现该问题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
最佳答案
当针对从 CreateFoo
为 IDispatch GUID 返回的 IFoo
对象调用 QueryInterface 时,它返回 E_NOINTERFACE
除非 ComVisible是为实际实现类设置的。
当 jscript 准备调用 Foo
方法时,它多次调用 QueryInterface,包括使用这个特定的 GUID,并且由于返回错误,它不会尝试使用调用
。
当 vbscript 准备调用 Foo
方法时,它不会检查接口(interface)是否支持 IDispatch
。使用 IDispatchEx 的 GUID 调用 QueryInterface 一次,但它似乎只是假设将支持 IDispatch。
关于c# - 为什么这个 C# COM 类可用于 VBScript 而不是 JScript?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3712005/