3

对于 Eric Lippert 或熟悉 JScript 引擎实现的 Microsoft 人员来说,这确实是一个问题。

我可以这样做:

var obj = new ActiveXObject("My.ProgId");
var methods = GetMethodsViaMagic(obj);

?

(假设 COM 类型支持 IDispatch)

如果是这样,它GetMethodsViaMagic()看起来像什么?


编辑- 当然,我尝试的第一件事是for...in循环,但这不适用于在 ActiveX 对象上定义的方法和属性。至少,不适用于我在 .NET 中定义并通过ComVisible.


在 C# 中,我可以像这样定义 IDispatch:

 [Guid("00020400-0000-0000-c000-000000000046"),
  InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
 public interface IDispatch
 {
     int GetTypeInfoCount();
     System.Runtime.InteropServices.ComTypes.ITypeInfo
         GetTypeInfo([MarshalAs(UnmanagedType.U4)] int iTInfo,
                     [MarshalAs(UnmanagedType.U4)] int lcid);

     [PreserveSig]
     int GetIDsOfNames(ref Guid riid,
                       [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPWStr)] string[] rgsNames,
                       int cNames,
                       int lcid,
                       [MarshalAs(UnmanagedType.LPArray)] int[] rgDispId);

     [PreserveSig]
     int Invoke(int dispIdMember,
                ref Guid riid,
                [MarshalAs(UnmanagedType.U4)] int lcid,
                [MarshalAs(UnmanagedType.U4)] int dwFlags,
                ref System.Runtime.InteropServices.ComTypes.DISPPARAMS pDispParams,
                [Out, MarshalAs(UnmanagedType.LPArray)] object[] pVarResult,
                ref System.Runtime.InteropServices.ComTypes.EXCEPINFO pExcepInfo,
                [Out, MarshalAs(UnmanagedType.LPArray)] IntPtr[] pArgErr);
 }

然后我可以做这样的事情:

    var idispatch = (IDispatch) comObject ;
    System.Runtime.InteropServices.ComTypes.ITypeInfo typeInfo =
        idispatch.GetTypeInfo(0, 0);

    System.Runtime.InteropServices.ComTypes.FUNCDESC funcDesc;
    string strName, strDocString, strHelpFile;
    int dwHelpContext;

    typeInfo.GetFuncDesc(i, out pFuncDesc);// i = 1, 2, 3...
    funcDesc = (System.Runtime.InteropServices.ComTypes.FUNCDESC)
        Marshal.PtrToStructure(pFuncDesc,
                               typeof(System.Runtime.InteropServices.ComTypes.FUNCDESC));

...并获取函数(方法)名称,以及参数的数量等。

我可以在 JScript 中为 ActiveX (COM IDispatch) 对象做类似的事情吗?

4

3 回答 3

6

首先,请记住,我已经有十多年没有从事过 JScript 工作了。那段时间引擎发生了变化,我的记忆消失了。

据我的回忆和知识:如果对象实现了 IDispatchEx,for-in 循环将起作用,但如果对象仅实现 IDispatch,则不会。

我一直想添加一种机制,以便 JScript 程序可以使用与调度对象关联的类型信息中可用的信息来枚举属性,但我不相信我曾经真正编写过代码。

于 2011-08-22T15:30:11.647 回答
3

我发现如果我在 ComVisible .NET 对象上实现了 IReflectfor...in ,我可以使用 Javascript循环来枚举方法和属性。

IReflect在 CCW 中被编组为 IDispatch。

于 2011-08-22T13:00:09.370 回答
2

你应该能够做到

var methods = [];
for( var property in obj ) {
    if( obj.hasOwnProperty(property) && typeof obj[property] === 'function' ) {
        methods.push(property);
    }
}

然后methods数组将包含方法名称。如果有问题的对象是某个构造函数的实例,您可能希望放弃hasOwnProperty检查,因为这将所有内容都限制为仅查看在 obj 本身上定义的属性/方法,而不是其原型链中的属性/方法。

至于参数的数量,您可以使用(正如 Domenic 在评论中指出的那样)函数本身.length属性

因此,要获取每个方法的名称和参数数量obj

var methods = [];
for( var property in obj ) {
    if( obj.hasOwnProperty(property) && typeof obj[property] === 'function' ) {
        methods.push({
            name: property,
            args: obj[property].length
        });
    }
}

你会得到一个对象字面量数组,每个字面量都包含一个方法的名称和参数个数obj


编辑:当我第一次写这个答案时,我正在考虑获取参数的名称(而不是简单的数量),因此包含一些相当hacky的代码来获取这些名称。如果有人感兴趣,这里是代码,我只是厚颜无耻地Prototype.js中偷来的)

function argumentNames(func) {
  var names = func.toString().match(/^[\s\(]*function[^(]*\(([^)]*)\)/)[1]
    .replace(/\/\/.*?[\r\n]|\/\*(?:.|[\r\n])*?\*\//g, '')
    .replace(/\s+/g, '').split(',');
  return names.length == 1 && !names[0] ? [] : names;
}

将函数/方法传递给该函数,它会给你返回参数名称......也许。如果你返回的对象是一个成熟的宿主对象,它的方法/函数可能无法被toString(). 通常,toString()将返回方法/函数的实际源代码(并且argumentNames函数会使用一些正则表达式对其进行解析),但在本机代码的情况下,您可能只会返回字符串“本机代码”或其他内容,而不是源代码代码。

于 2011-08-21T22:52:56.417 回答