12

我使用“Visual Studio 插件”向导创建了一个新的插件项目,现在,我正在尝试添加一些事件处理程序:

public void OnConnection(object application, ext_ConnectMode connectMode, object addInInst, ref Array custom)
{
    _applicationObject = (DTE2)application;
    _addInInstance = (AddIn)addInInst;

    _applicationObject.Events.BuildEvents.OnBuildBegin += BuildEvents_OnBuildBegin;
    _applicationObject.Events.BuildEvents.OnBuildDone += BuildEvents_OnBuildDone;
    _applicationObject.Events.SelectionEvents.OnChange += SelectionEvents_OnChange;
    _applicationObject.Events.DocumentEvents.DocumentOpened += DocumentEvents_DocumentOpened;
    _applicationObject.Events.DocumentEvents.DocumentSaved += DocumentEvents_DocumentSaved;
}

但无论我做什么,我的处理程序都不会被执行!

我瞎了吗?我是否必须做任何其他事情来注册这些处理程序,或者为什么它不起作用?

4

2 回答 2

22

看来你是垃圾收集器的受害者。见:http ://www.mztools.com/articles/2005/mz2005012.aspx

 private readonly BuildEvents _buildEvents;
 private readonly SelectionEvents _selectionEvents;
 private readonly DocumentEvents _documentEvents;
 private readonly Events _events;

 public void OnConnection(object application, ext_ConnectMode connectMode, object addInInst, ref Array custom)
 {
     _applicationObject = (DTE2)application;
     _addInInstance = (AddIn)addInInst;
     _events = _applicationObject.Events;

     _buildEvents = _events.BuildEvents;
     _buildEvents.OnBuildBegin += BuildEvents_OnBuildBegin;
     _buildEvents.OnBuildDone += BuildEvents_OnBuildDone;

     _selectionEvents = _events.SelectionEvents;
     _selectionEvents.OnChange += SelectionEvents_OnChange;

     _documentEvents = _events.DocumentEvents;
     _documentEvents.DocumentOpened += DocumentEvents_DocumentOpened;
     _documentEvents.DocumentSaved += DocumentEvents_DocumentSaved;
 }
于 2013-01-13T18:11:28.290 回答
1

如果您在调试器中查看 applicationObject,您会看到它是一个 COM 对象,但 xxxEvents 类不是(如果您无法让代码在 OnConnection 上中断,那么您的插件在调试时可能没有被加载,检查工具菜单)

COM 中的事件由单独的 COM 接口(在本例中为多个)在服务器 (VS) 调用以触发它们的另一个方向上处理。

尽管 COM 对象具有与 CLR 程序集类似的类型化程序集概念,但它们在内部是非托管代码,因此不能保留托管对象的根

因此,尽管您可以通过与本机 CLR 事件完全相同的方式将委托与 COM 事件挂钩,但您的事件却与 RCW(运行时可调用包装器)挂钩。有一个从服务器到 RCW com 接口的 COM 引用,但是没有 CLR 根,RCW 最终会被释放,这会卸载 com 接口,之后您将不会接收任何事件。

我不确定,但我认为这通常在您使用与其事件接口直接关联的单个 COM 对象时起作用,因此这可能是由于 DTE COM 接口的结构方式所致……

无论如何,正如其他人所说,您只需要从应用程序对象中对 BuildEvents、SelectionEvents 和 DocumentEvents 类进行任何类型的托管引用来修复它。VS 的多个实例加载单独的加载项实例,因此您只需添加静态对象引用列表并将它们设置在 OnConnect 中。

订阅 DTE 事件似乎不起作用 - 没有调用事件

http://msdn.microsoft.com/en-us/library/k639e386.aspx

于 2013-01-14T11:15:05.407 回答