为了账号安全,请及时绑定邮箱和手机立即绑定

C#编译器如何检测COM类型?

C#编译器如何检测COM类型?

C#
互换的青春 2019-08-01 14:33:06
C#编译器如何检测COM类型?C#编译器有点神奇地处理COM类型。例如,这个陈述看起来很正常......Word.Application app = new Word.Application();......直到你意识到这Application是一个界面。在接口上调用构造函数?Yoiks!这实际上被转换为对Type.GetTypeFromCLSID()另一个的调用Activator.CreateInstance。此外,在C#4中,您可以对ref参数使用非ref 参数,并且编译器只是添加一个局部变量以通过引用传递,丢弃结果:// FileName parameter is *really* a ref parameterapp.ActiveDocument.SaveAs(FileName: "test.doc");(是的,有一堆参数丢失。不是可选参数好吗?:)我正在尝试调查编译器的行为,我没有假装第一部分。我可以做第二部分没有问题:using System;using System.Runtime.InteropServices;using System.Runtime.CompilerServices;[ComImport, GuidAttribute("00012345-0000-0000-0000-000000000011")]public interface Dummy{     void Foo(ref int x);}class Test{     static void Main()     {         Dummy dummy = null;         dummy.Foo(10);     }}我想能够写:Dummy dummy = new Dummy();虽然。显然它会在执行时爆炸,但没关系。我只是在试验。编译器为链接的COM PIA(CompilerGenerated和TypeIdentifier)添加的其他属性似乎没有做到这一点......什么是神奇的酱油?
查看完整描述

3 回答

?
Helenr

TA贡献1780条经验 获得超3个赞

我绝不是这方面的专家,但最近我偶然发现了我想要的东西:CoClass属性类。

[System.Runtime.InteropServices.CoClass(typeof(Test))]public interface Dummy { }

coclass提供一个或多个接口的具体实现。在COM中,这种具体实现可以用任何支持COM组件开发的编程语言编写,例如Delphi,C ++,Visual Basic等。

请参阅我对有关Microsoft Speech API的类似问题的回答,您可以在其中“实例化”界面SpVoice(但实际上,您正在实例化SPVoiceClass)。

[CoClass(typeof(SpVoiceClass))]public interface SpVoice : ISpeechVoice, _ISpeechVoiceEvents_Event { }


查看完整回答
反对 回复 2019-08-01
?
芜湖不芜

TA贡献1796条经验 获得超7个赞

在你和迈克尔之间,你几乎把这些东西放在一起。我认为这是它的工作原理。(我没有写代码,所以我可能会稍微误解它,但我很确定这是怎么回事。)

如果:

  • 你是一个“新”的界面类型,和

  • 接口类型有一个已知的coclass,和

  • 您正在使用此界面的“no pia”功能

然后代码生成为(IPIAINTERFACE)Activator.CreateInstance(Type.GetTypeFromClsid(GUID OF COCLASSTYPE))

如果:

  • 你是一个“新”的界面类型,和

  • 接口类型有一个已知的coclass,和

  • 您没有使用此界面的“no pia”功能

然后生成代码就像你说“new COCLASSTYPE()”一样。

乔恩,如果你对这些东西有疑问,请随时给我或Sam直接打扰。仅供参考,Sam是此功能的专家。


查看完整回答
反对 回复 2019-08-01
?
ITMISS

TA贡献1871条经验 获得超8个赞

好吧,这只是为迈克尔的答案提供了更多的内容(如果他愿意的话,欢迎他加入,在这种情况下我会删除这个)。

查看Word.Application的原始PIA,涉及三种类型(忽略事件):

[ComImport, TypeLibType(...), Guid("..."), DefaultMember("Name")]public interface _Application{
     ...}[ComImport, Guid("..."), CoClass(typeof(ApplicationClass))]public interface Application : _Application{}[ComImport, ClassInterface(...), ComSourceInterfaces("..."), Guid("..."), 
 TypeLibType((short) 2), DefaultMember("Name")]public class ApplicationClass : _Application, Application{}

由于Eric Lippert在另一个答案中谈到的原因,有两个接口。正如你所说的那样,就是CoClass类本身和Application界面上的属性。

现在,如果我们在C#4中使用PIA链接,其中一些内容将嵌入到生成的二进制文件中...但不是全部。创建一个Application以这些类型结束的实例的应用程序:

[ComImport, TypeIdentifier, Guid("..."), CompilerGenerated]public interface _Application[ComImport, Guid("..."), CompilerGenerated, TypeIdentifier]public interface Application : _Application

ApplicationClass- 可能是因为它将在执行时从真实的 COM类型动态加载。

另一个有趣的事情是链接版本和非链接版本之间的代码差异。如果您反编译该行

Word.Application application = new Word.Application();

引用的版本中,它最终为:

Application application = new ApplicationClass();

而在链接版本中它最终为

Application application = (Application) 
    Activator.CreateInstance(Type.GetTypeFromCLSID(new Guid("...")));

所以它看起来像“真实” PIA需要的CoClass属性,但链接的版本,不会因为有没有一个CoClass编译器可以实际引用。它必须动态地完成它。

我可能会尝试使用此信息伪造一个COM接口,看看我是否可以让编译器链接它...


查看完整回答
反对 回复 2019-08-01
  • 3 回答
  • 0 关注
  • 527 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信