Partilhar via


Criação de conciliadores de portfólio

O reconciliador de documentos dá ao Briefcase os meios para reconciliar diferentes versões de um documento.

Sobre os Reconciliadores de Pastas

Um reconciliador de pasta combina diferentes versões de entrada de um documento para produzir uma única e nova versão de saída do documento. Talvez seja necessário criar um reconciliador de maleta para dar suporte ao seu tipo de documento. Esta visão geral descreve os reconciliadores de briefcase e explica como criá-los.

São abordados os seguintes tópicos:

Reconciliação

Um documento é uma coleção de informações que podem ser copiadas e alteradas. Um documento tem versões diferentes se o conteúdo de pelo menos duas cópias do documento for diferente. A reconciliação produz uma única versão de um documento a partir de duas ou mais versões iniciais. Normalmente, a versão reconciliada é uma combinação de informações das versões iniciais com as informações mais recentes ou mais úteis preservadas.

A reconciliação é iniciada pelo Briefcase quando determina que duas ou mais cópias do mesmo documento são diferentes. Pasta, que atua como iniciador neste contexto, localiza e inicia o reconciliador de pasta associado ao tipo de documento dado. O conciliador compara os documentos e determina quais partes dos documentos devem ser retidas. Alguns reconciliadores podem exigir a interação do usuário para concluir a reconciliação. Outros podem concluir a reconciliação sem interação do usuário. O reconciliador pode estar contido em um aplicativo ou ser uma extensão implementada como uma DLL.

Alguns reconciliadores de maletas podem criar resíduos. Um resíduo é um documento, geralmente com o mesmo tipo de arquivo que o documento inicial, que contém informações não salvas na versão mesclada. Os resíduos são normalmente usados para dar aos autores uma maneira rápida de determinar quais informações de seu documento original não estão na versão final mesclada. Se um reconciliador suportar resíduos, cria um resíduo para cada uma das versões originais do documento. Os resíduos não são criados a menos que o iniciador os solicite.

Alguns conciliadores de pasta trabalham com o Briefcase para permitir que o usuário encerre a reconciliação. Este é um recurso importante para um usuário que pode decidir que a reconciliação não deve prosseguir. Um reconciliador normalmente fornece um objeto de terminação quando a reconciliação requer interação do usuário e pode ser longa. Em alguns ambientes, um reconciliador pode permitir a reconciliação parcial, permitindo que um usuário suspenda temporariamente uma reconciliação e a retome mais tarde. A Briefcase não suporta atualmente a reconciliação parcial.

Criando um reconciliador de pasta de trabalho

Você cria um reconciliador de pasta implementando as interfaces de reconciliação. No mínimo, um reconciliador implementa as interfaces IReconcilableObject e IPersistStorage ou IPersistFile. Como iniciador, Briefcase determina quando a reconciliação é necessária e chama o IReconcilableObject::Reconcile método para iniciar a reconciliação.

Embora IReconcilableObject::Reconcile forneça um amplo conjunto de recursos de reconciliação, um reconciliador de pasta realiza apenas uma reconciliação mínima na maioria dos casos. Em particular, o Briefcase não exige que o reconciliador suporte a geração de resíduos ou o suporte do objeto de terminação. Além disso, o conciliador realiza uma única conciliação de cima para baixo e não deve devolver o valor REC_E_NOTCOMPLETE; ou seja, não deve tentar uma reconciliação parcial.

Briefcase fornece a interface IReconcileInitiator. O reconciliador de maleta pode usar o método IReconcileInitiator::SetAbortCallback para definir o objeto de terminação. Pasta de trabalho não usa identificadores de versão e, portanto, não pode fornecer versões anteriores de um documento caso um reconciliador os solicite usando os métodos correspondentes em IReconcileInitiator.

Maleta passa para IReconcilableObject::Reconciliar identificadores de arquivo que representam as versões do documento a ser reconciliado. O reconciliador de pastas obtém acesso às versões usando o método IMoniker::BindToObject ou IMoniker::BindToStorage. Este último é geralmente mais rápido e é recomendado. O reconciliador deve liberar quaisquer objetos ou armazenamento aos quais esteja vinculado.

Quando o reconciliador de pasta usa IMoniker::BindToStorage, ele vincula-se ao armazenamento que é armazenamento plano (um fluxo) ou armazenamento estruturado definido pela OLE. Se o reconciliador espera armazenamento simples, ele deve usar IMoniker::BindToStorage para solicitar o IStream interface. Se o reconciliador espera armazenamento estruturado, ele deve solicitar o IStorage interface. Em ambos os casos, deve-se pedir acesso direto de leitura apenas (não transacionado) ao armazenamento; o acesso de leitura e escrita pode não estar disponível.

Um reconciliador de pasta mínimo normalmente olha diretamente para o armazenamento das outras versões e lida com objetos incorporados de uma maneira muito primitiva, como mesclar duas versões do objeto incluindo ambas as versões na versão de saída.

O iniciador localiza o reconciliador de pasta apropriado usando um subconjunto da lógica implementada pela função GetClassFile para determinar o tipo de um determinado arquivo e, em seguida, procura no registro a classe do reconciliador associada ao tipo de arquivo fornecido. Pasta de trabalho, como outros componentes do Shell, determina o tipo de um ficheiro somente pela extensão do nome de ficheiro. A extensão de um arquivo deve ter um tipo de arquivo registrado para que o Briefcase invoque um reconciliador para o arquivo. Você deve definir uma entrada de registro do seguinte formulário ao instalar o reconciliador.

CLSID
   {the file CLSID}
      Roles
         Reconciler
            (Default) = {the reconciler-classid}

A classe deve ser de carregamento rápido, deve ser designada _MULTIPLEUSE e, a menos que os marshalers sejam fornecidos para a interface de reconciliação, deve ser um servidor em processo (contido em uma DLL) em vez de um servidor local (implementado em um arquivo .exe).

Interação do usuário na reconciliação

Um reconciliador de maleta deve tentar realizar a reconciliação sem interação com o utilizador. Quanto mais automatizada for a conciliação, melhor será a perceção do usuário sobre o processo.

Em alguns casos, a intervenção do utilizador pode ser valiosa. Por exemplo, um sistema de documentos pode exigir que um usuário revise as alterações antes de aceitar a versão mesclada de um documento ou pode exigir comentários do usuário explicando as alterações que foram feitas. Nestes casos, o iniciador, e não o reconciliador de pastas, é responsável por consultar o utilizador e executar as instruções do utilizador.

Em outros casos, a intervenção do usuário pode ser necessária, por exemplo, quando duas versões foram editadas de maneiras incompatíveis. Nesses casos, o iniciador ou o reconciliador de pasta deve consultar o usuário para obter instruções sobre como resolver o conflito. Em geral, nenhum iniciador pode confiar na conclusão de uma reconciliação sem esperar alguma interação do usuário. Os reconciliadores, por outro lado, têm a opção de interagir com o usuário para resolver conflitos ou exigir que o iniciador o faça.

Reconciliando objetos incorporados

Ao reconciliar um documento, o próprio reconciliador de pasta pode tornar-se um iniciador se descobrir um objeto incorporado de um tipo que não pode ser reconciliado. Neste caso, o reconciliador precisa reconciliar recursivamente cada um dos objetos incorporados e assumir todas as responsabilidades de um iniciador.

Para realizar a recursão, o reconciliador de pasta carrega o objeto e consulta a interface apropriada. O manipulador para o objeto deve suportar a interface. Se qualquer método da interface retornar o valor OLE_E_NOTRUNNING, o reconciliador deverá executar o objeto para executar a operação. Como o código para objetos incorporados nem sempre está disponível, um reconciliador deve fornecer uma solução para essa condição. Por exemplo, o reconciliador pode incluir versões antigas e novas do objeto incorporado na versão reconciliada. O reconciliador não deve tentar conciliar entre conexões.

O iniciador armazena as versões do documento que estão sendo mescladas. Em muitos casos, o iniciador tem acesso ao armazenamento de cada versão e salva o resultado da reconciliação usando armazenamento semelhante. Às vezes, no entanto, o iniciador pode ter um objeto na memória para o qual nenhuma versão persistente está disponível. Essa situação pode ocorrer quando um documento contendo objetos incorporados abertos deve ser reconciliado antes de ser salvo. Nesses casos, o iniciador salva o resultado da reconciliação na versão encontrada na memória.

O iniciador usa a interface IPersistStorage para vincular (carregar) a versão mesclada. O iniciador usa o método IPersistStorage::Load se uma versão inicial já tiver sido criada e usa o método IPersistStorage::InitNew para a versão inicial. Quando a versão integrada é carregada, o iniciador usa QueryInterface para recuperar o endereço da interface IReconcilableObject. Esta interface dá ao iniciador acesso ao armazenamento dos resíduos existentes e dá-lhe uma forma de criar armazenamento para quaisquer novos resíduos. Em seguida, o iniciador direciona a interface para realizar a reconciliação. Na verdade, o iniciador consulta a interface IPersistFile antes de IPersistStorage. Se o reconciliador oferecer suporte a IPersistFile, o iniciador manipulará a réplica por meio do IPersistFile em vez dos métodos IPersistStorage. Isso permite a reconciliação de arquivos que não são armazenados como documentos compostos.

Quando a reconciliação estiver concluída, o iniciador poderá salvar a versão mesclada usando o IPersistStorage ou interface IPersistFile. Durante a reconciliação, o reconciliador de pasta cria resíduos conforme necessário e grava seus bits persistentes no armazenamento. Se a versão mesclada for um fluxo, a interface IStorage passada para IPersistStorage::Load conterá um fluxo chamado "Contents" com seu estado de armazenamento definido como STATEBITS_FLAT. (Você pode definir os bits de estado usando o método IStorage::Stat.) Após a mesclagem, o iniciador salva a versão mesclada gravando os dados de maneira apropriada. Deve assegurar que STATEBITS_FLAT é configurado de maneira adequada para o armazenamento.

Resíduos

O iniciador indica se deseja resíduos definindo o parâmetro pstgNewResidues para um endereço válido ao chamar o método IReconcilableObject::Reconcile. Se o reconciliador não suportar a criação de resíduos, ele deve retornar imediatamente o valor REC_E_NORESIDUES, a menos que o parâmetro dwFlags especifique o valor RECONCILEF_NORESIDUESOK.

O reconciliador de mala retorna resíduos ao iniciador criando novos elementos de armazenamento e copiando-os para a matriz apontada por pstgNewResidues. Para resíduos de armazenamento estruturados, o reconciliador copia uma interface IStorage e, para resíduos de armazenamento planos, copia um IStream ou uma interface IStorage com o sinalizador STATEBITS_FLAT ativado. O reconciliador usa IStorage para criar o armazenamento necessário, usando IStorage::CreateStream para criar armazenamento simples para um resíduo que é um fluxo e IStorage::CreateStorage para criar armazenamento estruturado.

O iniciador prepara pstgNewResidues para que ele não contenha elementos na parte não reservada do espaço de nomes IStorage. O conciliador de maletas coloca cada resíduo num elemento cujo nome corresponde à sequência da sua versão original. Por exemplo, o primeiro resíduo está contido em "1", o segundo em "2", e assim por diante. Se o próprio objeto reconciliado produz um resíduo, ele é encontrado no elemento chamado "0".

O reconciliador de pastas regista cada um dos elementos recém-criados individualmente, garantindo que o iniciador tenha acesso às informações. O reconciliador, no entanto, não se compromete pstgNewResidues si mesmo. O iniciador é responsável por cometer isto ou eliminá-lo de outra forma.

Referência do conciliador de maleta

Esta seção contém informações sobre as interfaces de reconciliação. Ao manipular erros, um método pode retornar apenas os valores de erro que são explicitamente definidos como possíveis valores de retorno. Além disso, o método deve definir todas as variáveis cujos endereços são passados como parâmetros para NULL antes de retornar do erro.

Interfaces e Métodos do Reconciliador de Pastas