类型库完全等同于 .NET 元数据。它对客户端程序员最有用,它使编译器和 IDE 对您的库更智能。提供自动完成和语法检查,因此他的代码和你的代码不匹配的可能性很小。注册步骤是必要的,这样您的文件就可以被找回。类型库通常作为资源嵌入到 DLL 本身中,例如 .NET 元数据,但 .NET 构建模型并不容易做到这一点。客户端编译器使用类型库信息来生成适当的 COM 调用。 Guid 很重要,因为这是客户端编译器需要使用的,标识符名称不起作用。有一种方法可以使用名称来使用“后期绑定”,这与 .NET 中的反射完全等效,但不涉及类型库。
谁在生成 GUID?
CLR 可以。每个 .NET 接口或类都有一个,无论它是否为 [ComVisible(true)]。也通过 Type.GUID 属性公开。如果您没有在类型上使用 [Guid] 属性,那么它会运行一个算法来生成使用类型声明作为输入的 Guid。或者换句话说,如果您对类型进行任何更改,那么您可以确定 Guid 将具有不同的值。这是你永远不应该使用 [Guid] 属性的基本原因,除非你必须创建一个精确的插入替换并且不能重新编译客户端代码。 TLBID 来自于您在创建项目时自动生成的 AssemblyInfo.cs 文件。
在 dll 中、在 tlb 中还是在两个文件中?
它仅在您使用 [Guid] 属性时存在于 DLL 中,但通常它是在运行时生成的,如上所述。它始终存在于类型库中,这就是客户端编译器知道创建类的对象并使用其接口的方式。
将生成完全相同的 GUID
是的,只有类型声明起作用。
如果我运行 regasm 并传递现有的 dll 和 tlb 文件
Regasm 只能创建一个类型库,根据其 /tlb 选项的要求,它不能采用现有的。否则,它的作用与 Tlbexp.exe 完全相同,使用反射枚举程序集中的类型以查找 [ComVisible(true)] 并生成匹配的类型库声明。它所做的额外事情是将类型库的注册表项写入 HKLM/Software/Classes/Typelib。所以客户端 IDE 可以找回来。
设置了 dll 和 tlb 参数运行 regasm 有什么意义?
“dll 参数”可能意味着没有真正的想法。如上所述,使用 /tlb 生成类型库。是否部署类型库取决于它的使用情况,如果您不提供客户端代码,那么您应该始终部署它,以便客户端程序员可以使用它。类型库的其他用法是this post 的主题。如果您不确定客户端程序员将如何使用您的代码,请始终部署。
不是所有的信息都已经在注册表中了吗?
注册表中的内容是有限的,只有足够的信息才能找到类型库文件。您的接口的描述、它们的方法签名、guid 和工厂函数所需的 CLSID 都在类型库中。
取消注册 regasm 时,我们需要提供什么?
与注册完全一样,您只需添加 /unregister。如果您以前使用过 /tlb,您还必须提供它,以便可以删除 TypeLib 注册表项。当您忙于开发和测试库时,自动化这一点非常重要,因为 guid 通常是自动生成的,您可能会在注册表中产生大量垃圾。当您忘记运行 Regasm 时,还会让人头疼。项目 > 属性 > 构建选项卡,“注册 COM 互操作”复选框。但缺点是你必须运行 VS 提升才能写入注册表。
regasm 也总是会在 SysWow64 下生成条目?
SysWow64 没有任何作用,请始终避免部署到 c:\windows。但是,是的,位数确实很重要,注册表的结构使得 64 位应用程序不会意外地在 32 位库中创建对象并死于丑陋的异常。反之亦然。 32 位客户端应用程序将从 HKLM/Software/WOW6432Node 读取注册表项,您只能在使用 32 位版本的 Regasm 时获取您的注册表项。值得注意的是,考虑到 C# 代码可以在任何平台上运行,通常可以同时运行两种 Regasm。