Suchen English (United States)  Italiano (Italia) Deutsch (Deutschland)  Español (España, Alfabetización Internacional) Čeština (Česko)
Samstag, 17. Mai 2025 ..:: Projects » .NET » VB2008 - Gestione moduli Plugin ::.. registrieren  anmelden
 Download minimieren

  
 Gestione moduli plugin minimieren

DESCRIZIONE

Questa soluzione mostra come sia possibile realizzare un applicazione a moduli separati (DLL) indipendenti tra loro in cui ognuno dei quali possa assolvere ad un preciso compito. Un'elenco più dettagliato lo trovate nella sezione VANTAGGI, più sotto.

Premetto che il progetto di partenza non è opera mia ma di Luciano Bastianello, un veterano della community Visual Basic Tips&Tricks, purtroppo deceduto
Chi lo conosce, sa che la sua grande esperienza e professionalità è indiscussa. Mi sono permesso umilmente di prendere come base questo suo progetto, da lui pubblicato sul proprio blog, perchè l'ho ritenuto il più interessante ed idoneo allo scopo cui mi prefiggevo. Ringrazio Luciano per questo ottimo esempio.

La soluzione è costituita da 5 progetti:
- il progetto principale FormsLoader
- la libreria comune CommonObjects
- 3 moduli 'satellite': ModuloProva, Modulo2 e Modulo3

La cosa interessante di questa tecnica è che un modulo viene gestito esattamente come un 'plugin', ovvero il programma principale non sa assolutamente nulla del modulo, e nemmeno deve essere informato in anticipo di quanti e quali moduli devono/possono essere utilizzati. Al contrario è il modulo che deve 'esporre' determinati attributi (ovviamente predisposti) che il programma principale sarà in grado di interpretare.

E' sufficiente infatti che il file del modulo (DLL) si trovi fisicamente in una cartella da noi predisposta che, nel nostro caso, si chiama \PLUGIN.

Naturalmente, come scritto sopra, la cosa più importante di un applicazione a moduli è che questi possano dialogare insieme. 
Pensiamo ad esempio ad un modulo Fatture a cui sarà necessario comunicare l'ID del cliente, l'anno di esercizio, l'ID della azienda (nel caso in cui l'applicazione preveda la gestione multi-azienda, ecc.
In breve, una volta stabilite la modalità di gestione, potremo passare quanti parametri vogliamo. L'importante è che il modulo li sappia interpretare.

Al progetto iniziale ho inserito ulteriori caratteristiche come:

 

  • La creazione di un menu a run-time e di un un toolstrip con tutti i collegamenti per aprire i vari form presenti nei moduli.
  • Ho definito un overload al costruttore New() di ogni form che accetti i parametri da 'passare' tra applicazione principale e modulo secondario. 
    Non solo, come si vedrà nell'esempio, sarà anche possibile passare tali parametri tra moduli differenti. Vedi sotto.
  • Ho aggiunto altri progetti, uno dei quali contiene un form MDI con cui aprire le proprie finestre child, passando i parametri anche a quest'ultime.
    Ciò può consentire di creare complete applicazioni esterne che lavorano in sintonia con l'applicazione.
  • I moduli possono 'dialogare' tra loro, ovvero, sarà possibile accedere da un modulo esterno ad un altro modulo esterno, direttamente, senza essere
    costretti a passare per l'applicazione principale, anche qui passando gli opportuni parametri.
  • Ho aggiunto ulteriori attributi alla classe ProgramsAttribute
  • Ho crearo un menu Finestra impostandolo come MdiWindowListItem, per elencare le finestre figlie.
    Notare che tutte le finestre caricate dai moduli esterni, saranno correttamente elencate nel menu, ad esclusione della finestra del modulo MDI esterno, per ovvi motivi!

COME FUNZIONA

 

 

Il 'core' della gestione lo troviamo nel programma principale FormsLoader, nel form MainForm, in cui nell'evento Load viene eseguito il metodo CaricaAssembly per ogni modulo DLL trovato nella cartella \PLUGIN.
In ogni modulo vengono analizzati tutti i form, e quelli che sono stati 'decorati' con gli
Attributi (definiti nella classe ProgramsAttribute del progetto CommonObjects), saranno ritenuti idonei e verrà creato un riferimento in modo da poterli avviare all'occorrenza. 
Vediamo un esempio della gestione degli Attributi che 'decorano' le classi da caricare:

Nella classe ProgramsAttribute il costruttore New richiede 5 attributi:

Or AttributeTargets.Struct, AllowMultiple:=True)> _

Public Class ProgramsAttribute

Inherits Attribute

Private mGruppo As String

Private mModulo As String

Private mDescrizione As String

Private mNome As String

Private mAutore As String

Public Sub New(ByVal pGruppo As String, ByVal pModulo As String, ByVal pNome As String, ByVal pDescrizione As String, ByVal pAutore As String)

Me.Gruppo = pGruppo

Me.Modulo = pModulo

Me.Nome = pNome

Me.Descrizione = pDescrizione

Me.Autore = pAutore

End Sub

End Class

Nei form che voglio sia caricato all'avvio, devo assegnare il relativo valore ad ogni attributo:

Imports CommonObjects

Imports System.Windows.Forms

 

Public Class Form1

' implementazione di metodi, funzioni, ecc.

End Class

Se mancano gli attributi, il form non sarà caricato. Cosa vuol dire? Che io posso creare un modulo con un numero di form, ma caricarne 1 o 2, ed è proprio ciò che avviene ad esempio nel Modulo3 in cui carico solo il frmMain (MDI) ma non il frmChild, che invece sarà gestito all'interno del frmMain. Insomma, il modulo può essere proprio una applicazione completa! 
Il MainForm.vb, al Load, andrà a caricare solo i form, di ogni modulo DLL, in cui avremo 'decorato' la classe con gli attributi richiesti, vediamo il pezzo di codice:

Dim atr() As Attribute = CType(t.GetCustomAttributes(GetType(ProgramsAttribute), True), Attribute())

If atr.Length <> 0 Then

    'ricavo gli attributi per impostare i miei oggetti (menu, toolstrip, ecc.)

    'che userò per avviare i singoli programmi.

End If

La parte 'finale' è quella che permette di avviare i programmi/form contenuti nei moduli, di cui riporto solo la parte cruciale, ovvero quella che serve ad aprire il form passando i parametri che desideriamo. 
Ne ho definiti 2: NomeAzienda e IDAzienda.

Il metodo StartProgramFromMenuOrToolbar richiede

Private Sub StartProgramFromMenuOrToolbar(ByVal pObj As Object)

' ... codice ...

' converte il parametro pObj al tipo Form. Notare che il pObj non è altro che la proprietà

' Tag dell'Item (che abbiamo precedentemente valorizzato nel metodo CaricaAssembly)

Dim tipoForm As Type = DirectCast(pObj, Type)

' ... codice ...

' creo l'istanza, passando i parametri che ho definito

frm = DirectCast(Activator.CreateInstance(tipoForm, mAnno, mNomeAzienda, mIDAzienda), Form)

' ... codice ...

End Sub

Naturalmente, nel form chiamato si dovrà avere il relativo costruttore che accetta i parametri:

Public Class Form1

Dim mAnno As String

Dim mNomeAzienda As String

Dim mIDAzienda As Long

Private Sub New()

InitializeComponent()

End Sub

Public Sub New(ByVal pAnno As String, ByVal pNomeAzienda As String, ByVal pIDAzienda As Long)

InitializeComponent()

mAnno = pAnno

mNomeAzienda = pNomeAzienda

mIDAzienda = pIDAzienda

End Sub

' implementazione di metodi, funzioni, ecc.

End Class

 

VANTAGGI

  • Riprendo quanto indicato da Luciano, sui vantaggi possibili di una tale implementazione:
  • Avere sviluppatori diversi che si occupano ciascuno di una parte del progetto senza conflitti con gli altri progetti
  • Possibilità di utilizzare per lo sviluppo di ciascun modulo uno qualsiasi dei linguaggi .NET.
  • Gestire delle personalizzazioni in parole povere al posto della libreria standard utilizzare un’altra libreria modificando 'ad hoc' la libreria standard in tutto o in parte.
  • Avere la possibilità di diversificare e specializzare l’applicativo (verticalizzazione), tenere riservate alcune librerie che vengono attivate solo in funzione di altri fattori
  • Avere la possibilità di rendere modulare il proprio applicativo, nel senso che è possibile 'rilasciare' uno o più moduli in funzione del livello di licenza acquistata dal cliente.
  • Aggiornare e distribuire solo le librerie che per un qualsiasi motivo devono essere aggiornate e/o modificate
  • Realizzare una compilazione più veloce
  • Gestire test e validazioni solo sugli oggetti modificati

Ora credo sia importante dalle parole passare ai fatti e provare la soluzione in questione,

fermo restando che essa vuole essere solo un esempio su cui ci sono ancora alcune cose da mettere a punto, ma mi sembra una buona base di partenza.

AVVERTENZA

Quando apportate modifiche ad un modulo satellite, ricordate che occorre compilare la DLL e copiarla

nella cartella dei PLUGIN, ovvero: ...\Modulare\FormsLoader\bin\Debug\plugin, altrimenti verrà usata sempre quella vecchia.

 


  
Copyright (c) 2002-2021 Giorgio Brausi (aka gibra)   Nutzungsbedingungen  Datenschutzerklärung
DotNetNuke® is copyright 2002-2025 by DotNetNuke Corporation