Creación de reconciliadores de maletín
Un reconciliador de maletín proporciona a maletín los medios para conciliar diferentes versiones de un documento.
Acerca de los reconciliadores de maletín
Un reconciliador en maletín combina diferentes versiones de entrada de un documento para generar una única versión de salida nueva del documento. Es posible que tenga que crear un reconciliador de maletín para admitir el tipo de documento. En esta introducción se describen los reconciliadores de maletín y se explica cómo crearlos.
Se tratan los temas siguientes:
- Conciliación
- Creación de un reconciliador de maletín
- Interacción del usuario en conciliación
- Conciliación de objetos incrustados
- Residuos
Conciliación
Un documento es una colección de información que se puede copiar y cambiar. Un documento tiene versiones diferentes si el contenido de al menos dos copias del documento son diferentes. La conciliación genera una única versión de un documento a partir de dos o más versiones iniciales. Normalmente, la versión reconciliada es una combinación de información de las versiones iniciales con la información más reciente o más útil conservada.
La conciliación se inicia en maletín cuando determina que dos o más copias del mismo documento son diferentes. Maletín, que actúa como iniciador en este contexto, localiza e inicia el reconciliador de maletín asociado al tipo de documento especificado. El reconciliador compara los documentos y determina las partes de los documentos que se van a conservar. Algunos reconciliadores pueden requerir la interacción del usuario para completar la conciliación. Otros podrían completar la conciliación sin interacción del usuario. El reconciliador se puede contener dentro de una aplicación o ser una extensión implementada como un archivo DLL.
Algunos reconciliadores de maletín pueden crear residuos. Un residuos es un documento, que normalmente tiene el mismo tipo de archivo que el documento inicial, que contiene información que no se guarda en la versión combinada. Los residuos se suelen usar para proporcionar a los autores una manera rápida de determinar qué información de su documento original no está en la versión combinada final. Si un reconciliador admite residuos, crea un residuos para cada una de las versiones originales del documento. Los residuos no se crean a menos que el iniciador los solicite.
Algunos reconciliadores de maletín funcionan con Maletín para permitir que el usuario finalice la conciliación. Esta es una característica importante para un usuario que puede decidir que la conciliación no debe continuar. Normalmente, un reconciliador proporciona un objeto de finalización cuando la conciliación requiere interacción del usuario y puede ser larga. En algunos entornos, un reconciliador podría permitir la conciliación parcial, lo que permite a un usuario suspender temporalmente una conciliación y reanudarla más adelante. Sin embargo, el maletín no admite actualmente la conciliación parcial.
Creación de un reconciliador de maletín
Para crear un reconciliador de maletín, implemente las interfaces de conciliación. Como mínimo, un reconciliador implementa la interfaz IReconcilableObject y la interfaz IPersistStorage o IPersistFile . Como iniciador, Briefcase determina cuándo se necesita la conciliación y llama al método IReconcilableObject::Reconcile para iniciar la conciliación.
Aunque IReconcilableObject::Reconcile proporciona un amplio conjunto de funcionalidades de conciliación, un reconciliador de maletín solo lleva a cabo una conciliación mínima en la mayoría de los casos. En particular, el maletín no requiere que el reconciliador admita la generación de residuos o que admita el objeto de terminación. Además, el reconciliador lleva a cabo una única conciliación de arriba a abajo y no debe devolver el valor de REC_E_NOTCOMPLETE; es decir, no debe intentar la conciliación parcial.
El maletín proporciona la interfaz IReconcileInitiator . El reconciliador de maletín puede usar el método IReconcileInitiator::SetAbortCallback para establecer el objeto de terminación. El maletín no usa identificadores de versión y, por lo tanto, no puede proporcionar versiones anteriores de un documento si un reconciliador los solicita mediante los métodos correspondientes en IReconcileInitiator.
El maletín pasa a los monikers de archivo IReconcilableObject::Reconcile que representan las versiones del documento que se van a conciliar. El reconciliador de maletín obtiene acceso a las versiones mediante el método IMoniker::BindToObject o IMoniker::BindToStorage . Este último suele ser más rápido y se recomienda. El reconciliador debe liberar los objetos o el almacenamiento al que se enlaza.
Cuando el reconciliador de maletín usa IMoniker::BindToStorage, se enlaza al almacenamiento que es almacenamiento plano (una secuencia) o almacenamiento estructurado definido por OLE. Si el reconciliador espera almacenamiento plano, debe usar IMoniker::BindToStorage para solicitar la interfaz IStream . Si el reconciliador espera almacenamiento estructurado, debe solicitar la interfaz IStorage . En ambos casos, debe solicitar acceso directo de solo lectura (no transtranste) al almacenamiento; Es posible que el acceso de lectura y escritura no esté disponible.
Normalmente, un reconciliador de maletín mínimo examina directamente el almacenamiento de las demás versiones y trata con objetos incrustados de forma muy primitiva, como combinar dos versiones del objeto incluyendo ambas versiones en la versión de salida.
El iniciador busca el reconciliador de maletín adecuado mediante un subconjunto de la lógica implementada por la función GetClassFile para determinar el tipo de un archivo determinado y, a continuación, busca en el Registro la clase reconciliadora asociada con el tipo de archivo especificado. Maletín, al igual que otros componentes de Shell, determina el tipo de un archivo únicamente mediante la extensión de nombre de archivo. La extensión de un archivo debe tener un tipo de archivo registrado para que El maletín invoque un reconciliador para el archivo. Debe establecer una entrada del Registro del siguiente formulario al instalar el reconciliador.
CLSID
{the file CLSID}
Roles
Reconciler
(Default) = {the reconciler-classid}
La clase debe ser de carga rápida, debe designarse _MULTIPLEUSE y, a menos que se proporcionen serializadores para la interfaz de conciliación, debe ser un servidor en proceso (contenido en un archivo DLL) en lugar de un servidor local (implementado en un archivo .exe).
Interacción del usuario en conciliación
Un reconciliador de maletín debe intentar realizar la conciliación sin interacción del usuario. Cuanto más automatizada sea la conciliación, mejor será la percepción del usuario del proceso.
En algunos casos, la intervención del usuario puede ser valiosa. Por ejemplo, un sistema de documentos podría requerir que un usuario revise los cambios antes de aceptar la versión combinada de un documento o podría requerir comentarios del usuario que expliquen los cambios realizados. En estos casos, el iniciador, no el reconciliador de maletín, es responsable de consultar al usuario y llevar a cabo las instrucciones del usuario.
En otros casos, la intervención del usuario podría ser necesaria, por ejemplo, cuando se han editado dos versiones de maneras incompatibles. En tales casos, el iniciador o el reconciliador de maletín deben consultar al usuario para obtener instrucciones sobre cómo resolver el conflicto. En general, ningún iniciador puede confiar en completar una conciliación sin esperar alguna interacción del usuario. Por otro lado, los reconciliadores tienen la opción de interactuar con el usuario para resolver conflictos o requerir que el iniciador lo haga.
Conciliación de objetos incrustados
Al reconciliar un documento, el propio reconciliador de maletín puede convertirse en iniciador si detecta un objeto incrustado de un tipo que no puede conciliar. En este caso, el reconciliador debe conciliar de forma recursiva cada uno de los objetos incrustados y asumir todas las responsabilidades de un iniciador.
Para llevar a cabo la recursividad, el reconciliador de maletín carga el objeto y las consultas de la interfaz adecuada. El controlador del objeto debe admitir la interfaz . Si algún método de la interfaz devuelve el valor OLE_E_NOTRUNNING, el reconciliador debe ejecutar el objeto para llevar a cabo la operación. Dado que el código de los objetos incrustados no siempre está disponible, un reconciliador debe proporcionar una solución para esta condición. Por ejemplo, el reconciliador podría incluir versiones anteriores y nuevas del objeto incrustado en la versión reconciliada. El reconciliador no debe intentar conciliarse entre vínculos.
El iniciador almacena las versiones del documento que se combinan. En muchos casos, el iniciador tiene acceso al almacenamiento de cada versión y guarda el resultado de la conciliación mediante un almacenamiento similar. A veces, sin embargo, el iniciador podría tener un objeto en memoria para el que no hay ninguna versión persistente disponible. Esta situación puede producirse cuando un documento que contiene objetos incrustados abiertos debe conciliarse antes de guardarse. En tales casos, el iniciador guarda el resultado de la conciliación en la versión que se encuentra en la memoria.
El iniciador usa la interfaz IPersistStorage para enlazar (cargar) la versión combinada. El iniciador usa el método IPersistStorage::Load si ya se ha creado una versión inicial y usa el método IPersistStorage::InitNew para la versión inicial. Cuando se carga la versión combinada, el iniciador usa QueryInterface para recuperar la dirección de la interfaz IReconcilableObject . Esta interfaz proporciona al iniciador acceso al almacenamiento de los residuos existentes y le da una manera de crear almacenamiento para los residuos nuevos. A continuación, el iniciador dirige la interfaz para llevar a cabo la conciliación. El iniciador realmente consulta la interfaz IPersistFile antes de IPersistStorage. Si el reconciliador admite IPersistFile, el iniciador manipula la réplica a través de IPersistFile en lugar de los métodos IPersistStorage. Esto permite la conciliación de archivos que no se almacenan como documentos compuestos.
Una vez completada la conciliación, el iniciador puede guardar la versión combinada mediante la interfaz IPersistStorage o IPersistFile . Durante la conciliación, el reconciliador de maletín crea residuos según sea necesario y escribe sus bits persistentes en el almacenamiento. Si la versión combinada es una secuencia, la interfaz IStorage pasada a IPersistStorage::Load contiene una secuencia denominada "Contents" con su estado de almacenamiento establecido en STATEBITS_FLAT. (Puede establecer los bits de estado mediante el método IStorage::Stat ). Después de la combinación, el iniciador guarda la versión combinada escribiendo los datos de forma adecuada. Debe asegurarse de que STATEBITS_FLAT se establezca según corresponda para el almacenamiento.
Residuos
El iniciador indica si quiere residuos estableciendo el parámetro pstgNewResidues en una dirección válida al llamar al método IReconcilableObject::Reconcile . Si el reconciliador no admite la creación de residuos, debe devolver inmediatamente el valor de REC_E_NORESIDUES, a menos que el parámetro dwFlags especifique el valor RECONCILEF_NORESIDUESOK .
El reconciliador de maletín devuelve residuos al iniciador mediante la creación de nuevos elementos de almacenamiento y su copia en la matriz a la que apunta pstgNewResidues. En el caso de los residuos de almacenamiento estructurados, el reconciliador copia una interfaz IStorage y, para los residuos de almacenamiento plano, copia una interfaz IStream o IStorage con el conjunto de marcas STATEBITS_FLAT. El reconciliador usa IStorage para crear el almacenamiento necesario, usando IStorage::CreateStream para crear almacenamiento plano para un residuos que es una secuencia e IStorage::CreateStorage para crear almacenamiento estructurado.
El iniciador prepara pstgNewResidues para que no contenga ningún elemento en la parte no atendida del espacio de nombres IStorage . El reconciliador de maletín coloca cada residuos en un elemento cuyo nombre corresponde al orden de su versión inicial. Por ejemplo, el primer residuos se encuentra en "1", el segundo en "2", etc. Si el propio objeto reconciliado produce un residuos, se encuentra en el elemento denominado "0".
El reconciliador de maletín confirma cada uno de los elementos recién creados individualmente, lo que garantiza que el iniciador tenga acceso a la información. Sin embargo, el reconciliador no confirma pstgNewResidues . El iniciador es responsable de confirmarlo o eliminarlo de otro modo.
Referencia del reconciliador de maletín
Esta sección contiene información sobre las interfaces de conciliación. Al controlar errores, un método solo puede devolver los valores de error que se definen explícitamente como valores devueltos posibles. Además, el método debe establecer todas las variables cuyas direcciones se pasan como parámetros a NULL antes de devolver el error.
Interfaces y métodos del reconciliador en maletín