В JScript: Могу ли я перечислить методы объекта, созданного с помощью нового ActiveXObject ()? - PullRequest
3 голосов
/ 22 августа 2011

Это действительно вопрос к Эрику Липперту или кому-то из Microsoft, кто знаком с реализацией механизма JScript.

Могу ли я сделать это:

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

?

(предположим, что тип COM поддерживает IDispatch)

и если да, то что делает GetMethodsViaMagic()как выглядит?


EDIT - конечно, первое, что я попробовал, был цикл 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)?

Ответы [ 3 ]

6 голосов
/ 22 августа 2011

Прежде всего, имейте в виду, что я не работал над JScript более десяти лет; двигатель изменился за это время, и моя память исчезла.

Насколько я помню и знаю: цикл for-in будет работать, если объект реализует IDispatchEx, но не если объект просто реализует IDispatch.

Я всегда хотел добавить механизм, чтобы программы JScript могли использовать информацию, доступную из информации о типе, связанной с объектом диспетчеризации, для перечисления свойств, но я не думаю, что когда-либо писал код.

3 голосов
/ 22 августа 2011

Я обнаружил, что могу использовать цикл Javascript for...in для перечисления методов и свойств, , если я реализовал IReflect для объекта ComVisible .NET .

IReflect маршалируется как IDispatch через CCW.

2 голосов
/ 22 августа 2011

Вы сможете выполнить

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

, тогда массив methods будет содержать имена методов.Если рассматриваемый объект является экземпляром какого-либо конструктора, вы можете отменить проверку hasOwnProperty, поскольку это ограничивает все, чтобы смотреть только на свойства / методы, которые определены в самом объекте, а не на свойства в его цепочке прототипов.

Что касается количества аргументов, вы можете использовать (как указывает Доменик в комментариях) свойство .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.


Редактировать: я думал о том, чтобы получить имена (а не просто число) аргументов, когда я впервые написал этот ответ, и таким образом включил некоторый довольно хакерский код для полученияэти имена.Если кому-то интересно, вот код для этого, который я просто бесстыдно украл адаптировал из 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 анализирует его с помощью некоторого регулярного выражения), но в случае нативного кода вы можете просто получить строку «нативный код» или что-то в этом роде.назад, а не исходный код.

...