SDK de Microsoft Information Protection: Observadores del SDK de archivos

El SDK de archivos contiene dos clases de observador. Los miembros del observador son virtuales y se pueden invalidar para controlar las devoluciones de llamada de los eventos.

Cuando finaliza una operación asincrónica, se llama a la función miembro de OnXxx() correspondiente para obtener el resultado. Algunos ejemplos de ello son OnLoadSuccess(), OnLoadFailure() y OnAddEngineSuccess() para mip::FileProfile::Observer.

Los ejemplos siguientes muestran el patrón de promesa/futuro, que también se usa en los ejemplos del SDK, y se puede ampliar para implementar el comportamiento de devolución de llamada deseado.

Implementación del observador del perfil de archivos

En el ejemplo siguiente, hemos creado una clase, ProfileObserver, que se deriva de mip::FileProfile::Observer. Las funciones miembro se han invalidado para usar el patrón futuro/promesa usado en los ejemplos.

Nota: Los ejemplos siguientes solo se implementan parcialmente y no incluyen invalidaciones para los observadores de mip::FileEngine relacionados.

profile_observer.h

En el encabezado, definimos ProfileObserver, que deriva de mip::FileProfile::Observer, y, a continuación, invalidamos cada una de las funciones miembro.

class ProfileObserver final : public mip::FileProfile::Observer {
public:
ProfileObserver() { }
  void OnLoadSuccess(const std::shared_ptr<mip::FileProfile>& profile, const std::shared_ptr<void>& context) override;
  void OnLoadFailure(const std::exception_ptr& error, const std::shared_ptr<void>& context) override;
  //TODO: Implement mip::FileEngine related observers.
};

profile_observer.cpp

En la propia implementación, definimos la acción que se debe realizar para cada función miembro del observador.

Cada miembro acepta dos parámetros. El primero es un puntero compartido a la clase que controlamos en la función. ProfileObserver::OnLoadSuccess esperaría recibir mip::FileProfile. ProfileObserver::OnAddEngineSuccess esperaría mip::FileEngine.

El segundo es un puntero compartido al contexto. En nuestra implementación, el contexto es una referencia a std::promise que se ha enviado a modo de referencia como std::shared_ptr<void>. La primera línea de la función convierte todo esto en std::promise y, a continuación, se almacena en un objeto denominado promise.

Por último, se prepara el futuro estableciendo el valor de promise->set_value() y pasando el objeto mip::FileProfile.

#include "profile_observer.h"
#include <future>

//Called when FileProfile is successfully loaded
void ProfileObserver::OnLoadSuccess(const std::shared_ptr<mip::FileProfile>& profile, const std::shared_ptr<void>& context) {
  //cast context to promise
  auto promise = 
  std::static_pointer_cast<std::promise<std::shared_ptr<mip::FileProfile>>>(context);
  //set promise value to profile
  promise->set_value(profile);
}

//Called when FileProfile fails to load
void ProfileObserver::OnLoadFailure(const std::exception_ptr& error, const std::shared_ptr<void>& context) {
  auto promise = std::static_pointer_cast<std::promise<std::shared_ptr<mip::FileProfile>>>(context);
  promise->set_exception(error);
}

//TODO: Implement mip::FileEngine related observers.

Cuando creemos instancias de cualquier clase del SDK o usemos una función que realice operaciones asincrónicas, pasaremos la implementación del observador al constructor de configuración o a la propia función asincrónica. Al crear una instancia del objeto mip::FileProfile::Settings, el constructor incorpora mip::FileProfile::Observer como uno de los parámetros. En el ejemplo siguiente se muestra el valor de ProfileObserver personalizado que se usa en un constructor mip::FileProfile::Settings.

Implementación del observador FileHandler

De forma similar al observador de perfil, mip::FileHandler implementa una clase mip::FileHandler::Observers para controlar las notificaciones de eventos asincrónicas durante las operaciones de archivos. La implementación es similar a la que detallamos anteriormente. A continuación, se define parcialmente FileHandlerObserver.

file_handler_observer.h

#include "mip/file/file_handler.h"

class FileHandlerObserver final : public mip::FileHandler::Observer {
public:
  void OnCreateFileHandlerSuccess(
      const std::shared_ptr<mip::FileHandler>& fileHandler,
      const std::shared_ptr<void>& context) override;

  void OnCreateFileHandlerFailure(
      const std::exception_ptr& error,
      const std::shared_ptr<void>& context) override;

  //TODO: override remaining member functions inherited from mip::FileHandler::Observer
};

file_handler_observer.cpp

Este ejemplo solo hace referencia a las dos primeras funciones, pero las funciones restantes usan un patrón similar a estos y a ProfileObserver.

#include "file_handler_observer.h"

void FileHandlerObserver::OnCreateFileHandlerSuccess(const std::shared_ptr<mip::FileHandler>& fileHandler, const std::shared_ptr<void>& context) {
    auto promise = std::static_pointer_cast<std::promise<std::shared_ptr<mip::FileHandler>>>(context);
    promise->set_value(fileHandler);
}

void FileHandlerObserver::OnCreateFileHandlerFailure(const std::exception_ptr& error, const std::shared_ptr<void>& context) {
    auto promise = std::static_pointer_cast<std::promise<std::shared_ptr<mip::FileHandler>>>(context);
    promise->set_exception(error);
}

//TODO: override remaining member functions inherited from mip::FileHandler::Observer