gpt4 book ai didi

c# - C#COM可见类型:是否需要GUID?

转载 作者:行者123 更新时间:2023-11-30 20:31:19 26 4
gpt4 key购买 nike

我有以下课程:



[ComVisible(true)]
[Guid("F8351C66-7F0E-4E38-AE64-9A262202E230")]
[ProgId("CarProject.CarFactory")]
[ClassInterface(ClassInterfaceType.AutoDual)]
public class CarFactory
{
public CarFactory()
{}

[DispId(0)]
public Car CreateCar(int tyres)
{
return new Car(tyres);
}
}

[ComVisible(true)]
[Guid("83f622b9-74f4-4700-9167-52c4ce9e79aa")]
[ClassInterface(ClassInterfaceType.AutoDual)]
public class Car
{
[DispId(0)]
public int NumberOfTyres { get; private set; }

public Car(int tyres)
{
this.NumberOfTyres = tyres;
}
}


Car对象是由工厂创建的,因此COM客户端仅使用自动生成的 _Car接口。请注意,由于没有默认的构造函数,因此无法通过COM实例化该类。

我的问题是:是否需要 Guid属性?我在注册表中找不到它的值。

最佳答案

不,不需要,因为它将永远不会使用。实际上,它永远都不需要,并且应用[Guid]是非常糟糕的做法。

这种声明样式还存在其他一些问题,要讨论它们,都需要我写一本书,但这不是很实际。查看反编译的类型库会容易得多,这样您便可以看到客户端编译器看到的内容。如果您还没有Tlbexp.exe,请使用Visual Studio Developer命令提示符,生成类型库。运行Oleview.exe,依次选择“文件”>“查看Typelib”,然后选择.tlb文件。突出显示您现在看到的相关详细信息:

importlib("mscorlib.tlb");


这很尴尬,客户端程序员不仅要添加对您的类型库的引用,还要为mscorlib.dll添加.NET类型库。存储在c:\ windows \ microsoft.net \ framework \ v4.0.30319目录中。或旧版本v2.0.50727。相当不直观,通常不会达到良好的效果。请注意上一个问题中您是如何遇到麻烦的。继续阅读以了解发生这种情况的原因。

[
odl,
uuid(BD7A2C0E-E561-3EBC-8BB7-1C72EE61D5B0),
hidden,
dual,
nonextensible,
oleautomation,
custom(0F21F359-AB84-41E8-9A78-36D110E6D2F9, "ClassLibrary171.Car")

]
interface _Car : IDispatch {
// etc..
}


这是自动生成的“类接口”,您现在已经知道了。这是客户端编译器实际用于进行调用的程序。注意[uuid]属性,与C#中的[Guid]属性相同。但是它具有相当随机的值。它是自动生成的,就像界面一样。因此,在声明中使用[Guid]实际上并没有完成任何事情。

[hidden]属性以及接口名称上的前导下划线告诉类型浏览器工具(如VS中的对象浏览器)隐藏声明。使用OleView来查看细节非常重要。否则,古怪的事情就可以回溯到不支持接口的语言,Visual Basic的旧版本(如VB6和VBA)和脚本语言(如VBScript和JavaScript)是主要示例。此类语言需要通过使界面看起来像一个类来模仿它们,这是您考虑完全公开该类的唯一原因。

[
uuid(83F622B9-74F4-4700-9167-52C4CE9E79AA),
version(1.0),
noncreatable,
custom(0F21F359-AB84-41E8-9A78-36D110E6D2F9, "ClassLibrary171.Car")
]
coclass Car {
[default] interface _Car;
interface _Object;
};


注意[noncreatable]属性。类型库导出器可能会看到客户端代码无法创建Car实例,因为它没有默认构造函数。反过来,这有助于Regasm.exe找出不必为Car注册CLSID的原因,这就是为什么您无法在注册表中找到它。

并注意 _Object界面。出现是因为每个.NET类都派生自System.Object。同样,由于 _Car继承了它们,因此 Car接口还具有Object(ToString,Equals,GetHashCode,GetType)的方法。这就是您最终依赖于mscorlib.tlb的方式。它们可能对客户程序员很有用,但这并不常见,您通常当然也不必记录它们。暴露的越少越好。



长话短说,发生这种情况是因为您使用了 ClassInterfaceType.AutoDual。这是一种便利,但不是很好,Microsoft强烈建议使用ClassInterfaceType.AutoDispatch来代替它。但这仅对脚本语言有用。

通过显式声明 ICar接口,而不是让类型库导出程序为您生成它,可以避免所有这些情况。它必须是[ComVisible(true)],并且该类需要实现它。现在您可以使用 ClassInterfaceType.None

现在,您可以为界面指定[Guid]。但是请注意,这是一个坏习惯,COM要求接口是不可变的。一旦在野外暴露了一个,就再也无法更改。非常重要的是,COM有一个讨厌的DLL Hell问题,这是由于注册是在整个计算机范围内引起的,因此您通常无法保证可以重新编译客户端程序。崩溃可能导致非常难以诊断。如果必须更改它,则该接口需要一个新的[Guid],因此旧接口和新接口都可以共存。通过简单地完全省略该属性,最简单的方法是CLR已经自动生成了该属性。使用[Guid]确实允许创建与旧接口声明二进制兼容的接口,但这很难正确完成。

关于c# - C#COM可见类型:是否需要GUID?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43388170/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com