_Application和Application之间有什么区别

时间:2016-11-23 13:42:30

标签: c# vb.net ms-word

为什么使用Word定义一个这样的变量:

Dim Word As Microsoft.Office.Interop.Word._Application

OR

Microsoft.Office.Interop.Word._Application Word;

然后像这样设置:

Word = New Microsoft.Office.Interop.Word.Application

OR

Word = new Microsoft.Office.Interop.Word.Application();

应用程序 _Application

之间的区别是什么?

我怀疑一个人可能是一个班级而另一个人是一个界面,或者一个人可能是公开的而另一个是私人的,但对我来说仍然没有意义。

我希望有人可以向我解释。越多细节就越好。

2 个答案:

答案 0 :(得分:12)

两者都是接口,Application接口继承自_Application接口(与ApplicationEvents4_Event接口一起)。

那么何时使用什么?差异在MSDN中解释(强调添加):

<强> Application interface

[GuidAttribute("00020970-0000-0000-C000-000000000046")]
public interface Application : _Application, 
    ApplicationEvents4_Event
  

这是一个源自COM coclass的.NET接口,托管代码需要该COM接口才能与相应的COM对象进行互操作。 使用此派生接口访问COM对象的所有方法,属性和事件成员。但是,如果要使用的方法或事件在同一COM对象下共享相同的名称,则强制转换为相应的主接口以调用该方法,并转换为最新的事件接口以连接到该事件。有关COM对象的信息,请参阅此主题。

<强> _Application interface

[TypeLibType(4304)]
[Guid("00020970-0000-0000-C000-000000000046")]
[ComImport]
public interface _Application  { ... }
  

这是托管代码所需的COM coclass中的主要接口,用于与相应的COM对象进行互操作。 仅当您要使用的方法与COM对象的事件具有相同名称时才使用此主界面;在这种情况下,强制转换到此接口以调用该方法,并转换为最新的事件接口以连接到该事件。否则,使用从COM coclass派生的.NET接口来访问COM对象的方法,属性和事件。

实际后果

简而言之:在您的代码中使用Application而不是_Application,除非您必须这样做,因为方法名称和事件名称之间存在歧义。

例如,在Application.Quit事件(在应用程序退出时触发)和Application.Quit(ref Object SaveChanges, ref Object OriginalFormat, ref Object RouteDocument)方法(在调用时退出应用程序)之间存在这种歧义。

为了调用该方法,您可以简单地编写(例如退出而不提示保存更改):

Application.Quit(false);

但是,这可能会给您以下编译器警告:

  

警告3方法'Microsoft.Office.Interop.Word._Application.Quit(ref object,ref object,ref object)'和非方法'Microsoft.Office.Interop.Word.ApplicationEvents4_Event.Quit'之间存在歧义。使用方法组。

要避免警告,您可以将应用程序对象强制转换为_Application界面:

((_Application)Application).Quit(false); 

如果要订阅该事件,则需要将应用程序对象强制转换为相应的事件接口:

((ApplicationEvents4_Event)Application).Quit += OnApplicationQuit;

private void OnApplicationQuit()
{
    // handle event here
}

答案 1 :(得分:9)

这是一个长篇故事,以惊人的速度。 COM使用基于超纯接口的范例。客户端应用程序只对界面成员进行调用,&#34; coclass&#34;实现界面的视图完全隐藏。所有暴露的都是coclass的指导,即CLSID。这将传递给通用的CoCreateInstance()工厂函数,它返回您要求的接口。这种隔离是COM服务器可以用任何语言编写的主要原因,它的实现细节都不可见,因此永远不会与您使用的任何语言不兼容。

然而,使用接口是早期VB版本的一个问题,与VB.NET不同,它们没有任何接口支持。因此,他们的运行时支持将其搞砸了,并使其看起来就像您正在使用类一样。在这种情况下命名为Application。在这种情况下,该类的成员是默认接口_Application的成员。来自默认源接口的任何连接点都将添加为事件。

_Application中的前导下划线也是一个技巧,它告诉类型库浏览器隐藏接口。 Visual Studio中的对象浏览器没有做的事情,也许是你问这个问题的一个原因。诡计无法实现的一件事是处理实现多个接口的coclass。但是在类型设计师的注意下,他确保只为coclass提供一个默认接口和一个源接口。

类似的技巧对于给.NET程序员提供相同类型的api是必要的,确保他们也可以使用Application并轻松移植他们的代码。这是由类型库导入器(Tlbimp)完成的,它合成了一个与coclass同名的额外接口,它的所有成员都与默认接口完全相同。

这是一个接口,VB.NET和C#编译器允许您创建它的实例。与普通界面无关。导入器合成一个类,与coclass同名,使用&#34; Class&#34;追加。所以ApplicationClass在这里。它实现了coclass实现的所有接口。你在VB.NET中没有实际用途,你应该避免它,因为非常理想的嵌入式互操作类型&#34;功能不支持嵌入它。但是你可能希望用F#之类的语言或者移植到.NET但却不支持接口的语言来使用它。

长话短说,_Application是来自类型库的实际界面。但你应该赞成合成的Application,与你遇到的所有代码样本最匹配。