2011-12-17 45 views
7

Me gustaría ser capaz de:¿Cómo puedo comparar objetos de interoperabilidad de Word para "igualdad de referencia" Y determinar la colección o el objeto primario al que pertenece, por ejemplo, un párrafo?

  1. comparar los proxies Palabra de interoperabilidad COM en una base de "igualdad de referencia"; y
  2. mapa de un objeto específico (por ejemplo un párrafo) a la colección que viene de, o al menos
  3. determinar si dos párrafos son de la misma sección y que se viene relativamente antes de la anterior

¿Por qué quiero hacer esto? Intento crear un Complemento de Word que actúe de manera similar a un corrector ortográfico en el sentido de que se ejecuta en segundo plano (por antecedentes, quiero decir robando regularmente el tiempo del hilo principal de Word utilizando SendMessage) y escanea el documento para asegurarse texto "tokens". Quiero ser capaz de mantener una colección de tokens y actualizarlos a medida que el documento cambia. Un ejemplo específico de esto es si el usuario edita un párrafo determinado, quiero volver a explorar el párrafo y actualizar mi estructura de datos que apunta a ese párrafo. Si no hay forma de mapear entre el párrafo editado por el usuario (es decir, el párrafo donde comienza el rango de selección) y un párrafo que he "almacenado" en una estructura de datos, no puedo hacer esto.


código de ejemplo para el punto 1, por encima de

Si escribo el siguiente código 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 

Entonces me estoy haciendo la salida:

"Para2a Is Not Para2b" 

Que es quizás físicamente verdadero (diferentes proxys COM) pero no lógicamente t ruda. Necesito poder comparar esos párrafos y determinar si son lógicamente el mismo párrafo subyacente.

(Estoy planeando escribir el complemento en C#, pero el código VBA anterior demuestra el tipo de problema que necesito superar antes de hacer demasiada codificación).

Para los elementos 2 y 3 anteriores, es de esperar que sean fáciles de entender. Supongamos que tengo una referencia de párrafo (proxy de interoperabilidad). Quiero averiguar "dónde" está en el documento. ¿Pertenece a la Sección 1? ¿Está en un pie de página? Sin esta capacidad, todo lo que puedo hacer razonablemente para obtener una idea de dónde vienen las cosas es volver a escanear todo el documento cada vez que cambie, lo que por supuesto es absurdamente ineficiente y no será lo suficientemente oportuno para el usuario de la aplicación.

¡Cualquier pensamiento muy apreciado! Me complace publicar información adicional según sea necesario.

+0

Sí, no cuente con recuperar el mismo objeto. Compara sus rangos. –

Respuesta

2

Navegar por los detalles de igualdad de referencia en el contexto de COM Interop es siempre un ejercicio interesante.

no estaría al tanto de los detalles de implementación de los métodos Paragraph.Next() y Paragraph.Previous(), sin embargo el comportamiento que exhiben es muy similar a la forma en colecciones basados ​​en COM actúan en general, en lo que respecta a la creación de tiempo de ejecución que se puede llamar la envoltura.

Normalmente, si es posible, el marco evita crear nuevas instancias de RCW en respuesta a las referencias adicionales que se hacen a los objetos COM que ya tienen un RCW inicializado y asignado.Si ya existe un RCW para un puntero en particular a IUnknown, se incrementa el conteo de referencia interna mantenido por ese RCW y luego se devuelve el RCW. Esto permite que el marco evite incrementar el recuento de referencias del objeto COM real (AddRef).

Las colecciones basadas en COM, que son objetos COM que tienen representaciones administradas que implementan IEnumerable, parecen generar un nuevo RCW cada vez que se accede a un elemento, incluso si ya se ha accedido a él durante la sesión.

Por ejemplo:

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

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

bool thisIsFalse = (first == second); 

Si desea hacer cualquier tipo de "igualdad de referencia" de cheques, lo que necesita para escapar de la colección basada en COM, específicamente en su caso: el objeto Paragraphs. Usted puede hacer esto simplemente por el acaparamiento de sus hijos y almacenarlos en su propio, puramente gestionados y recolección predecible, así:

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

Aunque el uso de LINQ con interoperabilidad COM puede parecer un poco de miedo (si no lo hace a usted ... ¡realmente debería!) Estoy bastante seguro de que el código anterior es seguro y no dejará ninguna referencia pendiente, ni nada desagradable. Sin embargo, no he probado el código anterior exhaustivamente.

No olvide liberar adecuadamente esos recursos cuando haya terminado con ellos, al menos si sus requisitos requieren ese nivel de prudencia.

+0

Por lo tanto, a veces los objetos se pasan, a través de eventos, etc. - ¿Hay alguna manera, ignorando que el RCW podría ser una instancia diferente - para meter debajo del capó y ver hacia dónde apunta el RCW? Así que, como quizás una versión más cara de la verificación '(first == second)' anterior, ¿pero eso es cierto? – BrainSlugs83

+1

Entonces, seguí googleando, y encontré, lo que creo, es un artículo que usted escribió, @Matt. Poniéndolo aquí, ya que responde a mi pregunta anterior: http://badecho.com/2010/09/outlook-com-interop-and-reference-equality-for-unique-runtime-callable-wrapper-objects/ – BrainSlugs83

Cuestiones relacionadas