Variant 和 COM
关于将 Variant 与 COM 结合使用的技巧
引言
COM 是一项不错的技术,但将 COM 与 .NET 结合使用可能会带来麻烦,因为您会在沮丧时将其删除。 太多 COM 组件使用 Variant 数据类型。 哦,我多么讨厌 Variants。 我从未发现 Variants 在 Visual Basic 中可以接受,并且它们对于强类型语言来说只是非常麻烦。 我喜欢强类型语言; 我想确切地知道我正在使用的数据类型。 我认为 Variants 是一个很大的错误,现在很难处理,尤其是在 COM 组件仍然被广泛使用的情况下。
本文提供了在 C# 中使用带有 COM Interop 的 Variants 时的技巧。 我需要与一个 COM 组件交互以访问专有数据库。 此 COM 组件仅在 Visual Basic 6.0 上受支持。 因为我的应用程序需要使用 Web Services,所以我不希望在 Visual Basic 中实现 Web Services。 所以,我尝试强制 COM 在 C# 中工作。 令我惊讶的是,它工作得非常好。 问题不在于技术,而在于文档。
在开始让我写这篇文章的项目之前,每次我看到可以使用 COM 和 .NET 的项目时,我都会努力避免使用 COM,或者向处理 COM 的预算中投入额外的资金。 现在,在完成了那个项目之后,COM 和 .NET 不再像以前那样让我害怕了。 希望在您阅读本文后,您不会再像我一样害怕 COM 和 .NET,也不会犯我犯过的错误。 我真的希望这些技巧对您有用。
背景
创建 COM Interop 最简单的方法是让 Visual Studio 为您完成。 这些说明适用于 Visual Studio 2003。 在较新版本的 IDE 上,它们可能会略有不同。
- 创建一个新项目。
- 从解决方案资源管理器中,右键单击“引用”,然后选择“添加引用...”
- 将出现以下对话框。 单击“COM”选项卡。
- 浏览 COM 组件,双击您想要的组件,然后单击“确定”。
- 在解决方案资源管理器中,您现在将在“引用”下看到 COM Interop 库。
这很容易,不是吗? 现在,您需要做的就是使用这些 Interop 库,就是在您的类中使用 using
语句。 微软做得很好。
规格
我正在使用的 COM 组件附带了文档。 如果您使用的是 Visual Basic,那是一份不错的文档,但如果您使用的是 C#,则会有点令人沮丧。 这是他们的文档(没有函数描述的大部分内容)
Syntax ReturnCode = RecipeVar.GetRecipeHistory(NumVersions, Dates, Authors, Comments) where Parameters Data Type Description NumVersions Integer Number of recipe versions available. Dates Variant Array of dates for each recipe version. Authors Variant Array of authors for each recipe version. Comments Variant Array of comments for each recipe version.
Interop 的方法通过对象浏览器定义为
GetRecipeHistory(ref short, ref object, ref object, ref object)
初始化
Microsoft 的 .NET Framework SDK 文档指出
An argument passed to a ref parameter must first be initialized. Compare this to an out parameter, whose argument does not have to be explicitly initialized before being passed to an out parameter.
文档指出,当使用 ref
时,与不需要显式初始化的 out
相比,需要初始化参数。 问题是这些对象是数组,并且无法预先定义确切的数据类型。 它将编译,但是当您运行应用程序时,将生成一个异常,指出引用了错误的数据类型。 我认为文档失败的地方在于您可以将变量初始化为 null
。 将变量初始化为 null
被认为是初始化。 我想在“initialized”之后立即看到“显式初始化”这几个字,使我认为需要通过实例化来分配变量的内存。 因此,用法是
int numVersions = 0;
object dates = null;
object authors = null;
object comments = null;
bool err = recipe.GetRecipeHistory(ref numVersions,
ref dates, ref authors, ref comments);
集合
既然我已经获得了数据,我该如何使用它呢? 好吧,COM 文档指出它是一个数组,所以我可以使用该数组来获取数据。
string[] arr = new string[numVersions];
Array.Copy(comments, arr, numVersions);
借助 .NET 的强大功能,我还可以使用其他一些组件
string[] arr = new string[numVersions];
System.Collections.ICollection collection =
(System.Collections.ICollection) dates;
int i = 0;
foreach(object o in collection)
{
arr[i++] = "" + i + "\t" + o.ToString();
}
结论
本文说明了在 C# 中使用 Variants 的一些方法。 我花了几个小时在网上搜索 Variants、COM、.NET 和 C# 的各种组合,但我找不到答案。 我在这里展示的解决方案可能不适用于您的 COM 组件,但尝试一下可能值得一试,并节省您一些时间。 祝你编程愉快。