Depois de terminadas as férias (incluindo as férias mentais), está na altura de recomeçar a escrever sobre coisas mais técnicas, como os plugins.

O próximo passo vai permitir que o primeiro grande objectivo se aproxime: permitir que os plugins adicionem elementos à interface usando a ‘Shell’, que representa a aplicação vista pelos olhos dos plugins. A partir desta classe vai ser possível adicionar elementos aos forms, abrir novos documentos, lançar eventos para outros plugins, etc:

   1: public Shell(IMainForm mainForm)
   2: {
   3:     lock(typeof(Shell))
   4:     {
   5:         if(_instance != null)
   6:             throw new InvalidOperationException();
   7:         _mainForm = mainForm;
   8:         _pluginManager = new PluginManager();
   9:         _documents = new Documents(this);
  10:         _instance = this;
  11:     }
  12:     _dataAccess = new DataAccess();
  13:     InitializePlugins();
  14:     Events.SafeFire(Initialized, this, new ShellEventArgs(this));
  15: }

As classes descritas até agora (parte 1 e parte 2) estão num projecto sem qualquer acesso a forms, não incluindo o ‘System.Windows.Forms’ nem qualquer assembly parecida. Por isso o construtor da ‘Shell’ recebe um objecto do tipo IMainForm, que será o ponto de passagem para o mundo real ou, no neste caso, o form.

Depois de garantir que apenas uma instância da classe é inicializada – pois não seria desejável que os plugins pudessem inicializar Shell’s a gosto – iniciamos uma série de classes que irão tratar de diferentes aspectos da aplicação: Acesso a dados, gestão dos documentos, etc, acabando com a inicialização dos plugins e acabando a lançar um evento, representando o final da inicialização da ‘Shell’.

Sendo que as outras classes serão descritas posteriormente, resta mostrar o que se faz na inicialização dos plugins:

   1: private void InitializePlugins()
   2: {
   3:     _loadedPlugins = _pluginManager.LoadPlugins();
   4:     foreach (IPlugin plugin in _loadedPlugins)
   5:     {
   6:         plugin.Initialize(_instance);
   7:         try
   8:         {
   9:             plugin.Initialize(_instance);
  10:         }
  11:         catch (Exception)
  12:         {
  13:             //Could not initialize plugin
  14:             //TODO: report back result of process.
  15:         }
  16:     }
  17: }

Como no PluginManager, em que ao invocar o plugin se tinha o cuidado de apanhar qualquer excepção, aqui, ao chamar o método de inicialização, apanhamos qualquer excepção que possa ocorrer de modo a salvaguardar a aplicação. Novamente, fica por fazer alguma forma de conseguir mostrar ao utilizador que houve plugins que falharam mas isso será feito posteriormente, assim que o código nos mostrar como.

Finalmente, também temos de actualizar a interface do IPlugin:

   1: public interface IPlugin
   2: {
   3:     void Initialize(Shell shell);
   4: }

E, deixando assim, o código quase que compila e, melhor que tudo, quase que corre! O próximo passo será realmente colocar o código a correr e com um plugin a introduzir qualquer coisa no ecrã!