c# - 我如何比较 "reference equality"的 Word Interop 对象并确定某个段落所属的集合或父对象?

标签 c# vba ms-word office-interop

我希望能够:

  1. 在“引用相等”的基础上比较 Word Interop COM 代理;和
  2. 从一个特定的对象(比如一个段落)映射到它来自的集合,或者至少
  3. 判断两段是否来自同一节,哪一段相对在前一段

我为什么要这样做?我正在尝试构建一个 Word 加载项,它在后台运行的意义上类似于拼写检查程序(后台我的意思是通过使用 SendMessage 定期从主 Word 线程窃取时间)并扫描文档以确定文本“ token ”。我希望能够保留一组标记并在文档更改时更新它们。一个具体的例子是,如果用户编辑给定的段落,我想重新扫描该段落并更新指向该段落的数据结构。如果无法在用户编辑的段落(即选择范围开始的段落)和我“存储”在数据结构中的段落之间进行映射,我将无法执行此操作。


上述第 1 项的示例代码

如果我编写以下 VBA 代码:

Dim Para1 As Paragraph
Dim Para2a As Paragraph
Dim Para2b As Paragraph
Set Para1 = ActiveDocument.Paragraphs(1)
Set Para2a = Para1.Next
Set Para2b = Para1.Next.Next.Previous
If Para2a Is Para2b Then
    Debug.Print ("Para2a Is Para2b")
Else
    Debug.Print ("Para2a Is Not Para2b")
End If

然后我得到输出:

"Para2a Is Not Para2b"

这可能在物理上是正确的(不同的 COM 代理)但在逻辑上不是正确的。我需要能够比较这些段落并确定它们在逻辑上是否是相同的底层段落。

(我打算用 C# 编写加载项,但上面的 VBA 代码演示了在进行过多编码之前我需要克服的那种问题)。

对于上面的第 2 项和第 3 项,希望它们是不言自明的。假设我有一段(互操作代理)引用。我想弄清楚它在文档中的“位置”。它属于第 1 节吗?它在页脚中吗?如果没有这种能力,我唯一能做的就是在每次文档发生变化时重新扫描整个文档,这当然效率低得离谱,而且对应用程序用户来说也不够及时。

非常感谢任何想法!我很乐意根据需要发布其他信息。

最佳答案

在 COM Interop 的上下文中浏览引用相等性的细节总是一个有趣的练习。

我不知道 Paragraph.Next()Paragraph.Previous() 方法的实现细节,但是它们表现出的行为非常相似了解基于 COM 的集合在运行时可调用包装器创建方面的一般行为。

通常,如果可能,框架会避免创建新的 RCW 实例以响应对已初始化和分配了 RCW 的 COM 对象的其他引用。如果指向 IUnknown 的特定指针的 RCW 已经存在,则由该 RCW 维护的内部引用计数递增,然后返回 RCW。这允许框架避免增加实际 COM 对象的引用计数 (AddRef)。

基于 COM 的集合是具有实现 IEnumerable 的托管表示的 COM 对象,每次访问项目时似乎都会生成一个新的 RCW,即使该项目已在 session 期间被访问过.

例如:

Word.Document document = Application.ActiveDocument;
Paragraphs paragraphs = document.Paragraphs;

Paragraph first = paragraphs[1];
Paragraph second = paragraphs[1];

bool thisIsFalse = (first == second);

如果您想进行任何类型的“引用相等性”检查,您需要从基于 COM 的集合中转义,特别是在您的情况下:Paragraphs 对象。您可以简单地通过获取它的 child 并将它们存储在您自己的、纯托管和可预测的集合中来做到这一点,就像这样:

List<Paragraph> niceParagraphs = paragraphs.Cast<Paragraph>().ToList();

尽管将 LINQ 与 COM Interop 结合使用可能看起来有点可怕(如果你不觉得......它真的应该!)我相当确定上面的代码是安全的并且不会留下任何悬垂的引用,或其他任何讨厌的东西。但是,我没有对上述代码进行详尽的测试。

不要忘记在使用完这些资源后适本地释放它们,至少在您的要求需要这种审慎程度的情况下。

关于c# - 我如何比较 "reference equality"的 Word Interop 对象并确定某个段落所属的集合或父对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8548583/

相关文章:

c# - 下载图像并将其保存到 Application.persistentDataPath 会挂起应用程序

c# - .net 比 java 快

c# - 当应用程序使用对 Environment.FailFast 的调用退出时,会显示未知的硬错误消息

vba - MS Access 仅在更改特定方法时停止工作

vba - 字体颜色更改为白色而不是灰色

java - 如何使用apache-poi获取文件的全部内容?

c# - 获取 Facebook 的应用程序访问 token

javascript - Office.js 识别文档中的 ContentControl 位置

excel - VBA 在 Word 对象上使用 Excel 版本的“查找”?

excel - 根据组合框过滤列表框