2011-12-17 17 views
7

Tôi muốn có thể:Làm thế nào tôi có thể so sánh các đối tượng Word Interop cho "tham chiếu bình đẳng" VÀ xác định bộ sưu tập hoặc đối tượng cha mẹ mà nói, một đoạn thuộc về?

  1. so sánh Từ Interop COM proxy trên cơ sở "tham chiếu bình đẳng"; và
  2. bản đồ từ một đối tượng cụ thể (ví dụ một đoạn) đến việc thu thập nó xuất phát từ, hoặc ít nhất
  3. xác định xem hai đoạn là từ phần giống nhau và cái nào đến tương đối trước khi trước đó một

Tại sao tôi muốn làm điều này? Tôi đang cố gắng xây dựng một Word Add-In hoạt động tương tự như một trình kiểm tra chính tả theo nghĩa là nó chạy ở chế độ nền (theo nền tôi có nghĩa là thường xuyên lấy cắp thời gian từ chủ đề chính bằng cách sử dụng SendMessage) và quét tài liệu cho một số văn bản "mã thông báo". Tôi muốn có thể giữ một bộ sưu tập các mã thông báo xung quanh và cập nhật chúng khi các tài liệu thay đổi. Một ví dụ cụ thể về điều này là nếu người dùng chỉnh sửa một đoạn nhất định, tôi muốn quét lại đoạn văn và cập nhật cấu trúc dữ liệu của tôi trỏ đến đoạn đó. Nếu không có cách nào để ánh xạ giữa đoạn mà người dùng đã chỉnh sửa (tức là đoạn mà bắt đầu phạm vi lựa chọn) và một đoạn mà tôi đã "lưu trữ" trong cấu trúc dữ liệu, tôi không thể làm điều này.


Ví dụ Mã cho mụC# 1, trên

Nếu tôi viết mã VBA sau:

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 

Sau đó, tôi nhận được kết quả:

"Para2a Is Not Para2b" 

Đó có lẽ là sự thật (các proxy COM khác nhau) nhưng không hợp lý t rue. Tôi cần để có thể so sánh các đoạn văn đó và xác định xem chúng có cùng một đoạn văn bản giống nhau hay không.

(Tôi định viết bổ trợ trong C#, nhưng mã VBA ở trên thể hiện loại vấn đề tôi cần phải khắc phục trước khi viết quá nhiều mã).

Đối với các mục 2 và 3 ở trên, hy vọng chúng sẽ tự giải thích. Nói rằng tôi có một tham chiếu đoạn (interop proxy). Tôi muốn tìm ra "nơi" nó nằm trong tài liệu. Nó có thuộc về Phần 1 không? Nó có ở chân trang không? Nếu không có khả năng này, tất cả những gì tôi có thể làm một cách hợp lý để có được ý tưởng về việc mọi thứ đến từ đâu là quét lại toàn bộ tài liệu mỗi khi nó thay đổi, điều đó tất nhiên là không hiệu quả và sẽ không đủ kịp thời cho người dùng ứng dụng.

Bất kỳ suy nghĩ nào được đánh giá cao! Tôi rất vui khi đăng thông tin bổ sung nếu cần.

+0

Có, không tính vào việc nhận lại cùng một đối tượng. So sánh các phạm vi của chúng. –

Trả lời

2

Điều hướng các chi tiết về bình đẳng tham chiếu trong ngữ cảnh của COM Interop luôn là một bài tập thú vị.

Tôi sẽ không bảo mật chi tiết thực hiện của các phương pháp Paragraph.Next()Paragraph.Previous(), tuy nhiên hành vi mà chúng thể hiện rất giống với cách các bộ sưu tập dựa trên COM hoạt động nói chung liên quan đến tạo trình gọi thời gian chạy có thể gọi.

Thông thường, nếu có thể, khung sẽ tránh tạo các trường hợp RCW mới để đáp ứng các tham chiếu bổ sung được thực hiện cho các đối tượng COM đã được khởi tạo và gán RCW.Nếu một RCW đã tồn tại cho một con trỏ cụ thể để IUnknown, một số tham chiếu nội bộ được duy trì bởi RCW đó được tăng lên, và sau đó RCW được trả về. Điều này cho phép khuôn khổ tránh tăng số lượng tham chiếu của đối tượng COM thực tế (AddRef).

Bộ sưu tập dựa trên COM, là đối tượng COM có đại diện được quản lý triển khai IEnumerable, dường như tạo RCW mới mỗi lần một mục được truy cập, ngay cả khi mục đó đã được truy cập trong phiên.

Ví dụ:

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

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

bool thisIsFalse = (first == second); 

Nếu bạn muốn làm bất kỳ loại "bình đẳng tham khảo" kiểm tra, bạn cần phải thoát khỏi bộ sưu tập COM dựa, đặc biệt là trong trường hợp của bạn: đối tượng Paragraphs. Bạn có thể làm điều này chỉ đơn giản bằng cách lấy những đứa trẻ của mình và lưu trữ chúng trong riêng của bạn, hoàn toàn được quản lý và bộ sưu tập có thể dự đoán, như vậy:

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

Mặc dù sử dụng LINQ với COM Interop có thể nhìn một chút đáng sợ (nếu nó không đến bạn ... nó thực sự nên!) Tôi khá chắc chắn mã trên là an toàn và sẽ không để lại bất kỳ tài liệu tham khảo lủng lẳng trên mạng, hoặc bất cứ điều gì khác khó chịu. Tuy nhiên, tôi chưa thử nghiệm mã trên.

Đừng quên phát hành đúng các tài nguyên đó khi bạn làm xong chúng, ít nhất là nếu yêu cầu của bạn yêu cầu mức độ thận trọng đó.

+0

Vì vậy, đôi khi các đối tượng được truyền vào, thông qua các sự kiện, vv - Có anyway, bỏ qua rằng RCW có thể là một trường hợp khác nhau - để poke dưới mui xe và xem nơi RCW là chỉ? Vì vậy, giống như một phiên bản đắt tiền hơn của '(first == second)' kiểm tra ở trên, nhưng điều đó trả về đúng? – BrainSlugs83

+1

Vì vậy, tôi giữ googling, và tôi thấy, những gì tôi tin rằng, là một bài viết mà bạn đã viết, @ Matt. Đặt nó ở đây vì nó trả lời câu hỏi của tôi ở trên: http://badecho.com/2010/09/outlook-com-interop-and-reference-equality-for-unique-runtime-callable-wrapper-objects/ – BrainSlugs83

Các vấn đề liên quan