简体   繁体   English

如何比较 Word Interop 对象的“引用相等性”并确定某个段落所属的集合或父对象?

[英]How can I compare Word Interop objects for "reference equality" AND determine collection or parent object to which, say, a paragraph belongs?

I would like to be able to:我希望能够:

  1. compare Word Interop COM proxies on a "reference equality" basis;在“引用相等”的基础上比较 Word Interop COM 代理; and
  2. map from a specific object (say a paragraph) to the collection it comes from, OR at least从特定对象(例如段落)映射到它来自的集合,或者至少
  3. determine whether two paragraphs are from the same section and which one comes relatively before the previous one确定两段是否来自同一部分,哪一段相对在前一段之前

Why do I want to do this?我为什么要这样做? I am trying to build a Word Add-In that acts similarly to a spell-checker in the sense that it runs in the background (by background I mean by regularly stealing time from the main Word thread using SendMessage) and scans the document for certain text "tokens".我正在尝试构建一个 Word 插件,它的作用类似于拼写检查器,因为它在后台运行(后台我的意思是使用 SendMessage 从主 Word 线程中定期窃取时间)并扫描文档以确定文本“令牌”。 I want to be able to keep a collection of the tokens around and update them as the document changes.我希望能够保留一组令牌并在文档更改时更新它们。 A specific example of this is if the user edits a given paragraph, I want to rescan the paragraph and update my data structure which points to that paragraph.一个具体的例子是,如果用户编辑了一个给定的段落,我想重新扫描该段落并更新指向该段落的数据结构。 If there is no way to map between the paragraph the user edited in (ie the paragraph where the start of the selection range is) and a paragraph that I have "stored" in a data structure, I can't do this.如果无法在用户编辑的段落(即选择范围开始所在的段落)和我“存储”在数据结构中的段落之间进行映射,我就不能这样做。


Example Code for item #1, above上面第 1 项的示例代码

If I write the following VBA code:如果我编写以下 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

Then I am getting the output:然后我得到输出:

"Para2a Is Not Para2b"

Which is perhaps physically true (different COM proxies) but not logically true.这可能在物理上是正确的(不同的 COM 代理),但在逻辑上不正确。 I need to be able to compare those paragraphs and determine if they are logically the same underlying paragraph.我需要能够比较这些段落并确定它们在逻辑上是否是相同的底层段落。

(I am planning to write the add-in in C#, but the above VBA code demonstrates the kind of problem I need to overcome before doing too much coding). (我打算用 C# 编写插件,但上面的 VBA 代码演示了在进行过多编码之前我需要克服的问题)。

For items 2 and 3 above, hopefully they will be self-explanatory.对于上面的第 2 项和第 3 项,希望它们是不言自明的。 Say I have a paragraph (interop proxy) reference.假设我有一个段落(互操作代理)参考。 I want to figure out "where" it is in the document.我想弄清楚它在文档中的“位置”。 Does it belong to Section 1?它属于第 1 节吗? Is it in a footer?它在页脚中吗? Without this ability, all I can reasonably do to obtain an idea of where things come from is rescan the entire document every time it changes, which is of course absurdly inefficient and won't be timely enough for the app user.如果没有这种能力,我所能做的就是在每次更改时重新扫描整个文档,以了解事物的来源,这当然效率低下并且对应用程序用户来说不够及时。

Any thoughts greatly appreciated!任何想法都非常感谢! I'm happy to post additional information as needed.我很乐意根据需要发布其他信息。

Navigating the particulars of reference equality in the context of COM Interop is always an interesting exercise.在 COM Interop 的上下文中导航引用相等的细节总是一个有趣的练习。

I wouldn't be privy to the implementation details of the Paragraph.Next() and Paragraph.Previous() methods, however the behavior they exhibit is very similar to how COM-based collections act in general in regards to Runtime Callable Wrapper creation.我不会知道Paragraph.Next()Paragraph.Previous()方法的实现细节,但是它们表现出的行为与基于 COM 的集合在运行时可调用包装器创建方面的一般行为非常相似。

Typically, if possible, the framework avoids creating new RCW instances in response to additional references being made to COM objects that already have an RCW initialized and assigned.通常,如果可能,框架会避免创建新的 RCW 实例以响应对已初始化并分配了 RCW 的 COM 对象的其他引用。 If an RCW already exists for a particular pointer to IUnknown , an internal reference count maintained by that RCW is incremented, and then the RCW is returned.如果指向IUnknown的特定指针的 RCW 已经存在,则由该 RCW 维护的内部引用计数增加,然后返回 RCW。 This allows the framework to avoid incrementing the actual COM object's reference count ( AddRef ).这允许框架避免增加实际 COM 对象的引用计数 ( AddRef )。

COM-based collections, which are COM objects that have managed representations implementing IEnumerable , seem to generate a new RCW each time an item is accessed, even if that item has already been accessed during the session.基于 COM 的集合是具有实现IEnumerable托管表示的 COM 对象,每次访问项目时似乎都会生成一个新的 RCW,即使该项目在会话期间已被访问。

For example:例如:

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

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

bool thisIsFalse = (first == second);

If you want to do any sort of "reference equality" checking, you need to escape from the COM based collection, specifically in your case: the Paragraphs object.如果您想进行任何类型的“引用相等性”检查,您需要从基于 COM 的集合中转义,特别是在您的情况下: Paragraphs对象。 You can do this simply by grabbing its kids and storing them in your own, purely managed and predictable collection, like so:你可以简单地通过抓住它的孩子并将它们存储在你自己的、纯粹管理和可预测的集合中来做到这一点,如下所示:

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

Although using LINQ with COM Interop may look a bit scary (if it doesn't to you...it really should!) I'm fairly certain the above code is safe and will not leave any dangling references out there, or anything else nasty.尽管将 LINQ 与 COM Interop 一起使用可能看起来有点吓人(如果它对您来说不是……它真的应该!)但我相当确定上面的代码是安全的,不会在那里留下任何悬空引用或其他任何东西可恶的。 I have not tested the above code exhaustively, however.但是,我还没有详尽地测试上述代码。

Don't forget to properly release those resources when you are done with them, at least if your requirements require that level of prudence.不要忘记在完成这些资源后正确释放它们,至少在您的需求需要这种谨慎级别的情况下。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Word Interop:如何确定Word文档选择中是否包含段落标记? - Word Interop: How can I determine if a Word document selection includes a paragraph mark? 如何比较Office互操作对象的相等性? - How to compare Office interop objects for equality? 如何确定此Outlook互操作代码(OlItemType.olMailItem)中缺少哪个引用? - How can I determine which reference I'm missing in this Outlook interop code (OlItemType.olMailItem)? 父对象的集合成员的对象是否也应该引用父对象? - Should objects of a collection member of parent object also reference the parent object? 如何使用c#确定MS Word文档中的段落和行缩进? - How can I determine paragraph and line indents in MS Word documents with c#? 如何确定哪个值在我的收藏中出现最多? - How can I determine which value occurs the most in my collection? 如何仅将一个属于两个对象的函数用于一个对象? - How can I use one function, which belongs to two objects, for only one objects? 比较引用类型对象的集合是否相等,忽略集合中项目的顺序 - Comparing a collection of reference type objects for equality ignoring order of items in collection 如何展平对象的集合(而对象又包含集合)? - How can I flatten a collection of objects (which in turn contain collections)? 在调试时确定两个对象在不同范围内的引用相等性 - Determine reference equality of two objects in different scopes while debugging
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM