martedì 11 ottobre 2011

Utilizzando MEF per il recupero di stringhe di connessione

In un recente articolo , ho parlato di come utilizzare il Framework Extension Managed (MEF) di selezionare dinamicamente la classe che si desidera utilizzare in fase di esecuzione. Mentre dinamicamente classi di carico suona molto esotica, è possibile utilizzare MEF per le attività molto prosaica, anche. Ogni volta che il codice deve fare una scelta a runtime tra i diversi componenti di applicazioni differenti, si dovrebbe considerare MEF. Ogni sito web o un'applicazione ASP.NET, ad esempio, deve selezionare la stringa di connessione a destra (anche se solo di scegliere tra il test e database di produzione). MEF permetterai che il tuo sito di selezionare automaticamente la stringa di connessione a destra da un pool disponibile all'avvio.
MEF supporta anche una "apposita configurazione sé". Applicazioni Piuttosto che dire al sito che stringa di connessione a raccogliere, il codice del sito raccoglierà le informazioni disponibili in runtime e utilizzare queste informazioni per selezionare la stringa di connessione corretto. Questo esempio utilizza un sito Web ASP.NET, ma dovrebbe funzionare anche in qualsiasi applicazione. Quando il codice al posto, tutto quello che avresti bisogno di fare per cambiare la stringa di connessione utilizzata da un sito è far cadere una nuova DLL nella cartella Bin del sito.
Costruire il quadro
comincio con l'aggiunta di una libreria di classi per la mia soluzione sito Web ASP.NET per contenere il codice per il mio quadro della stringa di connessione. La prima cosa che io aggiungo alla mia libreria di classi è un'interfaccia che saranno condivisi tra tutti gli oggetti di connessione mia stringa. Poiché tutti ho bisogno è un metodo che restituisce una stringa, che l'interfaccia è molto semplice:
Public Interface IConnectionString 

  Funzione GetConnectionString () As String 

  End Interface
Poi ho bisogno di creare classi che implementano la mia interfaccia: una classe per ogni stringa di connessione avrò bisogno. Queste classi possono essere parte di questa applicazione o in una DLL completamente separate.Indipendentemente da ciò, la biblioteca con queste classi avrà bisogno di un riferimento alla DLL System.ComponentModel.Composition per supportare MEF. Ciascuna di queste classi implementerà la mia interfaccia IConnectionString e hanno bisogno di un attributo di esportazione MEF per rendere la classe disponibile attraverso MEF.L'attributo di esportazione specifica il tipo di richiesta che questa classe in grado di soddisfare.
Questa è la classe per la stringa di configurazione del mio sistema di test, con un attributo che specifica di esportazione MEF che questa classe deve essere utilizzato ogni volta che un'applicazione ha bisogno di qualcosa che implementa la mia interfaccia IConnectionString:
Importazioni System.ComponentModel.Composition
<Export(GetType(ConnectionClasses.IConnectionString))> TestConnString Public Class Implementa IConnectionString
  GetConnectionString Funzione Pubblica () As String Implementa IConnectionString.GetConnectionString
    Ritorno "... stringa di connessione ..."
  End Function
End Class
Specificare l'interfaccia è solo l'inizio di assicurare che il mio sito seleziona il corretto oggetto stringa di connessione. Per fornire ulteriori informazioni sugli oggetti stringa di connessione, ho definire un'interfaccia che contiene le informazioni che la mia domanda è necessario, per selezionare l'oggetto stringa di connessione di cui ha bisogno. Dal momento che l'informazione è costituito dal nome del sito e se il sito è in test o produzione, la mia interfaccia ha una proprietà per ciascuno di questi pezzi di informazioni (io aggiungo questa interfaccia per la stessa classe con la mia altra interfaccia):
Public Interface IConnectionMetaData 

  ReadOnly sito di proprietà As String 

  Proprietà ReadOnly IsProd As Boolean 

  End Interface
Ho poi ritornare al mio classi connessione e aggiungere gli attributi ExportMetadata che specificano i valori per ciascuna proprietà mia interfaccia. La stringa di classe di connessione che ho creato per essere utilizzato sul sito Northwind quando è in modalità di prova ha attributi ExportMetadata in questo modo:
<Export(GetType(ConnectionClasses.IConnectionString))> 

  <ExportMetadata("Site", "/Northwind")> 

  <ExportMetadata("IsProd", False)> 

  TestConnString Public Class
Selezione della stringa di connessione
Voglio impostare la stringa di connessione il più presto possibile nella vita del mio sito, così ho aggiungere il codice per trovare la corda giusta connessione al metodo Start Application nel mio file Global.asax (che assicura che il sito si configurerà il prima volta che qualcuno richiede una pagina). Per supportare MEF, avrò bisogno di aggiungere sia un riferimento a System.ComponentModel.Composition e, a mio file Global.asax, questi tre importazioni:
<% @ Import Namespace = "System.ComponentModel.Composition"%> 

  <% @ Import Namespace = "System.ComponentModel.Composition.Hosting"%> 

  % @ Import Namespace =% "System.ComponentModel.Composition.AttributedModelServices"
Anche nel mio file Global.asax, ho bisogno di una proprietà di tenere l'oggetto stringa di connessione. Perché voglio che il mio codice per selezionare l'oggetto giusto da tutti quelli disponibili, io decorare la classe con un ImportMany e dichiarare come IEnumerable (di Lazy). Ho definire ulteriormente Pigro come richiedono due interfacce: l'interfaccia delle classi che mi interessa e l'interfaccia che descrive le informazioni allegate a ciascuna classe. Il risultato assomiglia a questo:
<ImportMany()> 

  ConnStrings proprietà pubblica come IEnumerable (Of Lazy ( 

  Di ConnectionClasses.IConnectionString, 

ConnectionClasses.IConnectionMetaData))
A sostegno di questo codice, ho bisogno di un riferimento alla libreria di classi con le interfacce e le librerie di classi che contiene le mie lezioni di collegamento.
Ora sono pronto ad aggiungere il codice per il metodo Start Application per caricare gli oggetti stringa di connessione, selezionare quello giusto, e aggiornare il mio file di configurazione con questo codice. Ho intenzione di mantenere tutte le DLL con oggetti della stringa di connessione nella cartella Bin del sito. Per consentire MEF cercare una cartella per gli oggetti di corrispondenza, ho bisogno di creare un DirectoryCatalog e passarlo ad un CompositionContainer. Questo codice recupera il percorso della cartella bin del mio sito e costruisce una DirectoryCatalog per la cartella che passa poi ad un CompositionContainer:
Dim strPath = Server.MapPath ("Bin") 

  dirCat As New DirectoryCatalog (strPath) 

  con As CompositionContainer
Una volta costruito un CompositionContainer (che può contenere molti cataloghi), è possibile chiamare il metodo ComposteParts del contenitore. Che troverà tutte le proprietà contrassegnato con il ImportMany (o importazione) attributi, determina i requisiti di tali proprietà, poi cerca la Cataloghi associato con il contenitore per gli oggetti che soddisfano i requisiti delle proprietà. Questo codice chiama il mio CompositionContainer il metodo ComposeParts avere MEF cercare la cartella Bin per tutte le classi che implementano l'IConnectionString e interfacce IConnectionMetaData specificato sulla mia proprietà ConnStrings:
con = New CompositionContainer (dirCat) 

  con.ComposeParts (Me)
Tutti i miei oggetti ICconnectionString sarà ora associato alla proprietà ConnStrings, accanto, ho bisogno di selezionare la stringa di connessione giusto per il sito e la modalità (test o di produzione). Per selezionare la stringa di connessione a destra, il mio codice ha bisogno di raccogliere le informazioni per scegliere la corda giusta connessione. In primo luogo, posso accedere al file di configurazione del mio sito e determinare se il sito è in modalità debug (che mi dice se sto in modalità di prova o di produzione):
Cfg As configurazione 

  compilare As System.Web.Configuration.CompilationSection 

  cfg = System.Web.Configuration. 

  WebConfigurationManager.OpenWebConfiguration ("~") 

  compilare cfg.GetSection = ("system.web / compilation") 

  di debug As Boolean = true 
  Se la compilazione è niente OrElse 
  compile.Debug = False Then 
  di debug = False 
  End If

  
Io uso l'URL dell'oggetto Request per recuperare il mio nome del sito: 
SiteName As String 

  = siteName Me.Context.Request.Url.PathAndQuery
Sono pronto ora a controllare per trovare l'oggetto stringa di connessione attaccato alla mia proprietà che nel modo giusto, e per questo sito. Questo è ciò che questo codice, se non trovo un corrispondente oggetto stringa di connessione, ho un'eccezione (che, d'altro canto, potrebbe voler cercare qualche oggetto stringa di connessione predefinita):
Dim connStr = (Da connString In Me.ConnStrings 

  Dove connString.Metadata.IsProd <> debug E 

  siteName.StartsWith (connString.Metadata.Site) 

  Seleziona connString). FirstOrDefault 

  Se connStr Is Nothing Then 

  throw new Exception ("non configurabile Sito") 

  End If

  
Se trovo un oggetto corrispondente, estraggo la mia classe stringa di connessione da proprietà Value dell'oggetto

ConnectionString As 

  ConnectionClasses.IConnectionString = connStr.Value
Il resto del codice verifica solo per vedere se la stringa di connessione restituita da questo oggetto corrisponde a quello già presente, se non, riscrive il file di configurazione (dal riscrivere il file di configurazione innesca una ricompilazione del sito, I don ' t voglio fare questo più spesso di quanto devo.) 
Dim css Come ConnectionStringsSection 

  css = cfg.GetSection ("connectionStrings") 

  impostazione As New System.Configuration.ConnectionStringSettings 

  impostazione = css.ConnectionStrings ("SiteConnectionString")
Se l'impostazione Niente IsNot Poi Se setting.ConnectionString <> ConnectionString.GetConnectionString Poi setting.ConnectionString = ConnectionString.GetConnectionString cfg.Save () End If Else impostazione = New System.Configuration.ConnectionStringSettings ( "SiteConnectionString", ConnectionString.GetConnectionString) css.ConnectionStrings . Add (impostazione) cfg.Save () End If

In questo momento, di modificare le stringhe di connessione per un sito, mi piacerebbe aggiungere o rimuovere le DLL con oggetti stringa la connessione alla cartella Bin del sito e riavviare il sito. Un miglioramento potrebbe essere utile per mettere la stringa di codice di selezione connessione dietro un pulsante in un modulo, oltre al metodo di avviare l'applicazione. Ciò consentirebbe il sito per selezionare una nuova stringa di connessione, senza dover essere esplicitamente riavviato. Un'altra opzione è quella di estendere questo framework per il supporto delle opzioni di configurazione (ad esempio gli estremi per i servizi Web richiesta dal sito, i valori nelle impostazioni dell'applicazione) con l'aggiunta di altri metodi per l'interfaccia IConnectionString. Ma in questo momento, solo lasciando che il sito gestire le proprie stringhe di connessione stessa è una vittoria abbastanza grande per me. 


Corso Visual Studio - Corsi Visual Studio
Corso .Net- Corso Dot.Net - Corso Vb.net
Corso C# - Corso PHP - Corso Joomla

Nessun commento:

Posta un commento