如何在Classic ASP JScript中访问从CSharp COM对象返回的集合?

时间:2013-08-13 14:12:07

标签: c# .net com asp-classic jscript

好的,这是非常适合的,但我希望有人可以帮助我。另外,我对CSharp很满意,但对JScript和COM缺乏经验。

问题是这个。我正在支持用CSharp编写并作为COM对象公开的应用程序组件。它公开了几个公共方法,它们由客户端应用程序调用。客户端都是用JScript编写的经典ASP脚本文件。 我想向COM对象添加一个新的公共方法,该方法返回一组对象。

首先,返回单个结果对象可以正常工作......

我能够返回一个对象并访问它的属性。例如,在这个C#签名......

ResultObject GetResult();

... ResultObject是一个具有简单属性且没有逻辑的POCO。我可以使用以下JScript访问它的属性:

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

然而,当我返回一个数组时它会中断...

当我尝试从C#返回一个简单的ResultObject数组时......

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”会给我一种“未知”。

如何从作为COM对象公开的CSharp类返回集合(数组,IEnumerable等)并从经典ASP JScript访问它?

2 个答案:

答案 0 :(得分: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's 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>");
}

答案 1 :(得分:2)

好吧,在提出这个问题之后,StackOverflow提出了一些相关的问题,这些问题共同帮助我解决了问题。

关于相关问题的

This answer显示了我需要在C#中进行的更改。显然,COM更喜欢使用它所谓的SAFEARRAY。返回SAFEARRAY非常简单。我只是在C#中更改了我的方法的返回类型以返回'对象',并添加了一个属性来指导COM如何编组返回值:

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

然后我在从这个C#方法返回之前对我的数组做了一些奇特的渲染:

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

这让我回到了COM友好的SAFEARRAY。

(注意,“MarshalAs”属性似乎不是必需的。我的代码没有它的行为,但我喜欢澄清它提供的关于返回值的“文档”。)

然后this answer显示了我需要在JScript中进行的更改。看起来JScript与SAFEARRAY并不是很好。幸运的是,您可以使用“toArray()”方法轻松将其转换为JScript友好的数组:

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

现在所有人都表现得很好。