【问题标题】:Converting a fairly simple C# Class library into a COM object?将一个相当简单的 C# 类库转换为 COM 对象?
【发布时间】:2008-11-14 23:20:15
【问题描述】:

这是我的问题:我必须从返回复杂数据类型的经典 ASP 页面调用具有安全标头的 Web 服务。由于有关第 3 方工具的各种原因,它必须是经典的 ASP。我们决定我应该创建一个外部 dll 来执行此操作 - 我做了(在 c# 中)所以它返回一个数据集(ASP 可以理解的东西)。但是现在我需要将该函数公开给 ASP 页。因为这是经典的 ASP,所以我认为唯一直接的方法是将这个类库公开为 COM 对象。我需要知道完成这项任务的最简单的方法。我必须对我的 dll 做什么?

我从未使用过之前创建过 COM 对象。有人说我的类必须是静态的,我不能有构造函数。这是真的?谁能帮我安排一下步骤?

帮助! (o:

编辑:这个特定的问题现在已经解决了,但是正如 Robert Rossney 所指出的,我不能对经典 ASP 中的 DataSet 做任何事情。这导致我发布了第二个问题here 关于实现 XmlTextWriter - 如果你看到这个罗伯特,我认为你真的可以提供帮助!

【问题讨论】:

    标签: c# web-services com asp-classic


    【解决方案1】:

    不,那(静态/无 ctor)不是真的。事实上,恰恰相反,因为 COM 需要创建一个实例!您只需要使 COM 类可见。主要是添加一些属性,注册为COM dll(regasm)。

    http://msdn.microsoft.com/en-us/library/zsfww439.aspx

    【讨论】:

    • 我的默认构造函数可以有agruments吗?例如,我希望他们分配将在 wse 安全标头中使用的用户名和密码,然后为他们需要的响应调用适当的函数。
    • 没有。添加一个“init”方法来为你的类提供用户和密码。
    • 我的所有字段都必须是公开的还是可以通过公共属性公开我的字段以保持适当的数据隐藏?
    • 带有私有字段的公共属性应该没问题。
    【解决方案2】:

    创建一个返回 DataSet 的类并不难:

    using System;
    using System.Data;
    using System.Runtime.InteropServices;
    
    namespace COMTest
    {
       [Guid("AC4C4347-27EA-4735-B9F2-CF672B4CBB4A")]
       [ComVisible(true)]
       public interface ICOMTest
       {
           [ComVisible(true)]
           DataSet GetDataSet();
       }
    
       [Guid("CB733AB1-9DFC-437d-A769-203DD7282A8C")]
       [ProgId("COMTest.COMTest")]
       [ComVisible(true)]
       public class COMTest : ICOMTest
       {
           public DataSet GetDataSet()
           {
               DataSet ds = new DataSet("COMTest");
               return ds;
           }
       }
    

    }

    您需要选中项目属性中的“注册 COM 互操作”框,还需要对程序集进行签名,并且需要确保 IIS 用户可以访问您的 bin\Debug目录。

    完成此操作后,您就可以从 ASP 中创建一个实例了:

    <%
    Dim o
    Set o = Server.CreateObject("COMTest.COMTest")
    Response.Write("Server.CreateObject worked.")
    Response.Write("<br/>")
    Dim ds
    Set ds = o.GetDataSet()
    If Not ds is Nothing Then
      Response.Write("o.GetDataSet returned an object.  Can we use it?")
      Response.Write("<br/>")
      Response.Write("We have a DataSet, and its DataSetName is: ")
      Response.Write(ds.DataSetName)
    End If
    %>
    

    在这里你会很伤心。因为虽然返回 DataSet 的方法对 COM 可见,但 DataSet 的任何属性或方法都不可见。

    【讨论】:

    • 我必须将 Guid 添加到我的 dll 中的所有帮助程序类还是只添加主界面和类?
    • 我的所有字段都必须是公开的 - 或者我可以通过公共属性公开我的字段以保持适当的数据隐藏吗?
    • 很抱歉这么晚才回来。您只需使用 GUID 标记类和接口。您不仅可以通过公共属性公开您的字段,而且这是公开它们的唯一方法 - 您不能通过接口公开字段。
    【解决方案3】:

    有人说我的课必须是 静态的,我不能有一个构造函数。 这是真的?

    COM 类需要有一个默认构造函数,客户端在调用 CoCreateInstance 时将使用该构造函数。对象创建后,可以设置属性,或者调用其他方法。

    这类似于 .Net 处理可序列化对象的方式...您使用默认构造函数构造它,然后设置其所有属性。 (如果你喜欢 RAII,那么你在 COM 和 .Net 上都不走运。克服它;)

    至于静态评论,不,这不是真的,正如 Marc 指出的那样。

    【讨论】:

    • 其实只有XmlSerializer需要一个默认的ctor; BinaryFormatter 和 DataContractSerializer 有更多……“有趣”的对象构造方法。
    • +1 表示“如果你喜欢 RAII,那么你在 COM 和 .Net 上都不走运。克服它;”在喝了 RAII Kool-Aid 之后,我花了很长时间才接受这个事实,在那个范式中写了很多 .NET 东西(有很多 using 语句来伪造析构函数),然后尝试用默认构造函数将它们包装回 COM 和初始化方法。
    猜你喜欢
    • 1970-01-01
    • 2011-05-07
    • 1970-01-01
    • 2019-03-02
    • 1970-01-01
    • 2010-12-07
    • 1970-01-01
    • 2012-09-15
    • 1970-01-01
    相关资源
    最近更新 更多