【问题标题】:In JScript: Can I enumerate the methods on an object created via new ActiveXObject()?在 JScript 中:我可以枚举通过 new ActiveXObject() 创建的对象的方法吗?
【发布时间】:2011-08-21 22:35:58
【问题描述】:

这确实是 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) 对象做类似的事情吗?

【问题讨论】:

    标签: javascript activexobject


    【解决方案1】:

    首先,请记住,我已经有十多年没有从事 JScript 工作了。那段时间引擎变了,我的记忆也变淡了。

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

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

    【讨论】:

    • 感谢 Lippert 先生的贡献。拥有您描述的功能会很方便。无法想象现在添加该功能会破坏许多程序。我知道 Win8 越来越喜欢 Javascript;看起来很有趣。
    【解决方案2】:

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

    IReflect 在 CCW 中被封送为 IDispatch。

    【讨论】:

    • 这似乎不是这样。 for..in 循环不适用于 com-visible、基于 IReflect 的类。唯一的原因似乎是上面埃里克的回答;也就是说,它需要一个 IDispatchEx 接口(而 IReflect 只实现 IDispatch,如您的链接中所述)。
    【解决方案3】:

    你应该可以的

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

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

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

    所以要获取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 函数会使用一些正则表达式对其进行解析),但对于本机代码,您可能只会得到字符串“本机代码”或其他内容返回,而不是源代码。

    【讨论】:

    • 可以通过函数对象的length属性获取函数的参数个数:developer.mozilla.org/en/JavaScript/Reference/Global_Objects/…
    • Domenic:当然,你是对的——出于某种原因,我正在考虑参数 names。我会更新我的答案。谢谢!
    • 期待 Microsoft 的 ActiveX 对象来实现 Netscape 的 JavaScript 或 ECMAScript 的功能正在拉长弓。不要惊讶它失败或抛出错误。
    • @RobG:确实如此……但是使用for…in-loop 获取方法名称应该可以。但是,是的,我不知道其他的东西......
    • Flambino 和 RobG:哎呀——我写这个问题的时候累了。我应该提到我尝试了for..in 循环,但它不适用于 COM 对象。
    猜你喜欢
    • 1970-01-01
    • 2011-07-24
    • 2011-11-16
    • 1970-01-01
    • 1970-01-01
    • 2010-12-11
    • 1970-01-01
    • 2021-03-10
    • 1970-01-01
    相关资源
    最近更新 更多