Как получить доступ к коллекции, возвращенной с объекта CSharp COM в классическом ASP JScript?

Хорошо, это довольно ниша, но я надеюсь, что кто-то там может мне помочь. Кроме того, мне удобно в CSharp, но я неопытен в JScript и COM.

Проблема в этом. Я поддерживаю компонент приложения, написанный в CSharp и открытый как COM-объект. Он предоставляет несколько общедоступных методов, которые вызывают его клиентские приложения. Клиенты - это все классические файлы сценариев ASP, написанные на JScript. Я хотел бы добавить новый публичный метод к COM-объекту, который возвращает коллекцию объектов.

Во-первых, возврат одного объекта результата отлично работает...

Я могу вернуть один объект и получить доступ к его свойствам. Например, в этой подписи С#...

ResultObject GetResult();

... ResultObject - это POCO с простыми свойствами и без логики. Я могу получить доступ к его свойствам со следующим JScript:

var oMyObject = Server.CreateObject("MyNamespace.MyObject");
var result = oMyObject.GetResult();
Response.Write("<br /><i>('" + result.Value + "', '" + result.ID + "')</i>");

Однако он прерывается, когда я возвращаю массив...

Когда я пытаюсь вернуть простой массив ResultObjects из С#...

ResultObject[] GetResults();

... и получить доступ к нему из JScript...

var oMyObject = Server.CreateObject("MyNamespace.MyObject");
var results = oMyObject.GetResults();
for (var i = 0; i < results.length; i++) {
    Response.Write("<br /><i>('" + results[i].Value + "', '" + results[i].ID + "')</i>");
}

... При вызове скрипта я получаю следующую ошибку:

Ошибка выполнения Microsoft JScript "800a138f"

'results.length' - это null или не объект

Кроме того, попытка JScript "typeof results" дает мне тип "неизвестный".

Как я могу вернуть коллекцию (массив, IEnumerable и т.д.) Из класса CSharp, представленного как COM-объект и доступ к нему из классического ASP JScript?

+2
источник поделиться
2 ответа

Ну, после того, как вы задали этот вопрос, StackOverflow предложил некоторые связанные вопросы, которые в совокупности привели меня к решению.

Этот ответ по связанному вопросу показал изменения, которые мне нужно было сделать на С#. Очевидно, что COM предпочитает работать с тем, что он называет SAFEARRAY. Возвращение SAFEARRAY было довольно простым. Я только что изменил тип возвращаемого метода в С#, чтобы вернуть объект, и добавил атрибут для указания COM о том, как маршалировать возвращаемое значение:

[return: MarshalAs(UnmanagedType.Struct, SafeArraySubType = VarEnum.VT_ARRAY)]
object GetResults();

Затем я сделал некоторое причудливое кастинг на моем массиве до возвращения из этого метода С#:

ResultObject[] retv = //create and populate the return value array
return retv.Cast<object>().ToArray();

Это привело меня к тому, что я возвращаю COM-friendly SAFEARRAY.

(Обратите внимание: атрибут "MarshalAs" не представляется обязательным. Мой код ведет себя без него, но мне нравится поясняющая "документация", которую он предоставляет относительно возвращаемого значения.)

Затем этот ответ показал изменение, которое мне нужно было сделать в JScript. Кажется, что JScript плохо работает с SAFEARRAY. К счастью, вы можете легко преобразовать его в JScript-дружественный массив с помощью метода toArray():

var results = oMyObject.GetResults().toArray();

Теперь все ведет себя по своему желанию.

+2
источник

Что вы можете сделать, так это вернуть коллекцию вручную, например:

[ComVisible(true)] // may be optional depending on your other assembly settings
public class ResultList
{
    private List<Result> _innerList;

    internal ResultList(...parameters...)
    {
        _innerList = ...
    }

    public int Count
    {
        get
        {
            return _innerList.Count;
        }
    }

    public Result this[int index] // will be named "Item" in COM world
    {
        get
        {
            return _innerList[index];
        }
    }
}

Что вы можете использовать так:

var results = oMyObject.GetResults();
for (var i = 0; i < results.Count; i++) {
    Response.Write("<br /><i>('" + results.Item(i).Value + "', '" + results.Item(i).ID + "')</i>");
}
+2
источник

Посмотрите другие вопросы по меткам или Задайте вопрос