.NET DLL中使用的复杂类型(但在外部Web服务中定义)在VB6中不可用

时间:2013-12-06 10:36:10

标签: c# .net dll vb6 com-interop

我开发了一个Web服务,通​​过查询中央数据库来检查用户授权。每当用户启动它时,它应该被任何应用程序使用,以便检查是否允许用户运行该应用程序。 由于在公司中有许多用Visual Basic 6编写的旧应用程序由没有良好编程技能的人编写,我正在尝试创建一个他们可以在VB6应用程序中轻松使用的DLL,通过简单的函数调用来检查用户授权而不是处理Web服务调用和XML消息等细节。

我使用C#在Visual Studio 2010中创建了一个类库,只需包装Web服务功能。我成功创建了DLL文件并将其(通过RegAsm)注册到另一台用于开发Visual Basic 6应用程序的机器中。

在VB6中,intellisense显示DLL暴露的函数(可以调用),但它不适用于函数返回的复杂类型。 例如,DLL定义了以下函数,其中返回的类型(User)被定义到Web服务代码中:

[ClassInterface(ClassInterfaceType.AutoDual)]
[ProgId("AuthorLibrary.Author")]
[Guid("D2E23F5E-C209-464A-AF32-CC0251078076")]
//[ComDefaultInterface(typeof(IAuthor))]
public class Author //: AuthorLibrary.IAuthor
{
    //[...]

    public User getUserData(string username)
    {
        ResponseMessageOfUser user;
        using (AccessControlSoapClient ws = new AccessControlSoapClient())
        {
            user = ws.getUserData(username);
        }
        if (user.response != ResponseType.Ok)
            throw new Exception(user.response.ToString());
        return user.result;
    }

    //[...]
}

在VB6中,以下代码正确运行:

    Dim ws As AuthorLibrary.Author
    Set ws = New AuthorLibrary.Author

    Dim u As AuthorLibrary.User
    Set u = ws.getUserData("john.smith")
    Text1.Text = u.email

问题在于,当开发人员写u.时,没有任何内容出现,因此他不知道对象的可用属性和/或方法(即使在上面的示例中u.email有效)

另一种方法返回Department的实例(让我们称之为dept)。我可以成功打印简单string属性的值,例如dept.Descriptiondept.Code,但更复杂的属性,例如dept.childrenDepartments - 应返回Department列表 - 给出错误:“缺少对象”。

我认为问题是 DLL文件没有显示定义到Web服务中的类/类型/结构。我怎么能这样做?

我还试图定义以下界面(IAuthor,正如您从第一个代码中看到的那样),但它似乎不起作用:

[InterfaceType(ComInterfaceType.InterfaceIsDual)]
[Guid("DB3BA840-B997-4D5E-86F0-0FC0A786C0D3")]
interface IAuthor
{
    //[...]
}

1 个答案:

答案 0 :(得分:1)

[InterfaceType]属性确实是关键。如果未明确应用该属性,则默认值为ComInterfaceType.InterfaceIsIDispatch。这只允许后期绑定,相当于在C#中调用 dynamic 类型的对象引用上的方法。请注意,如果没有获得IntelliSense,VB6程序员也会遇到同样的问题。

您尝试的IAuthor可能无法正常工作,因为您忘记将其公之于众。

所以你需要在User类上获得该属性。您将遇到问题,因为您没有创建该类。因此,对于其中一个,您可能也不能轻易声明IUser接口。这方面的后果是在课堂上应用[ClassInterface(ClassInterfaceType.AutoDual)]。它不是最漂亮的解决方案,也暴露了System.Object的成员,并为VB6程序员提供了对.NET Framework类型库的依赖,但这不是世界末日。但是,您仍然需要编辑类声明以应用该属性。

如果它是从Web服务生成的,那么您将面临维护问题。每次重新生成时,您都必须再次进行编辑。然后,这也很容易打破VB6代码,它必须重新编译。因此,您可能需要考虑隔离该声明,因此这不是必需的。声明您自己的User类并编写代码以将Web服务的User对象的字段/属性复制到您的用户对象。当然,编写接口和应用属性也不会有任何问题。