di .NET e di altre amenità

Experimenting Silverlight 3.0: Application Extensibility

Sometimes working with silverlight you need to have a sort of service, always available for global tasks or  working in background notifing the main thread when something happen. I've found this scenario many times during my work, as an example when I needed to poll a service to get periodic updates, or in another case with a caching service. Every time I developed this services using a static class or an instance of a class exposed by the Application, but the main problem is to manage the lifecycle to run or stop the service freeing the allocated resources when needed.

With Silverlight 3.0 this kind of services has been covered by a new tool named Application Services. An application Service is simply a class that implements the IApplicationService interface. This interface require two methods to be implemented by the Application Service class:

   1: public interface IApplicationService
   2: {
   3:     void StartService(ApplicationServiceContext context);
   4:     void StopService();
   5: }

This methods will be called by the Silverlight runtime when the service need to start during Application initialization and a few moments before the runtime terminate when the browser is closing or the user is navigating away. In the StartService() method the Application Service may run some code to begin his work, initializing variables, running threads and so on. On the other side the same service may notify threads to exit when the StopService() method is called by the runtime.

An Application Service class has to be registered in a specific section of the app.xaml. The application markup file is an ideal place to register this kind of classes. It a global location accessible by all the pages and controls, and the service instances may be simply configured with attributes mapping the class properties. Here is a sample of code showing how to register a FeedPollingService available in the sample source code:

 

   1: <Application xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   2:              xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
   3:              xmlns:local="clr-namespace:Elite.Silverlight3.AppExtensibility"
   4:              x:Class="Elite.Silverlight3.AppExtensibility.App">
   5:     <Application.Services>
   6:         <local:FeedPollingService x:Name="polling" 
   7:                                 FeedType="RSS20"
   8:                                 FeedUrl="http://blog.boschin.it/rss.aspx" 
   9:                                 Timeout="10000" />
  10:     </Application.Services>
  11: </Application>

First of all the "local" namespace is declared in the Application tag. The application service is registered in the <Application.Services> element. This element needs you specify a unique name for the service instance. This name may be used to reach the instance from every class in the application. The configured FeedPolllingService exposes a "Completed" event we need to handle to get notified of feed download:

   1: public Page()
   2: {
   3:     FeedPollingService service = Application.Current.Services["polling"] as FeedPollingService;
   4:     service.Completed += new EventHandler<CompletedEventArgs>(service_Completed);
   5:     InitializeComponent();
   6: }

 

This happen in the Page constructor. In the service_Compleded event handler we simply handle the incoming feed binding it to the user interface to show the content. My service contains a thread that poll a rss feed every configured timeout so in the completed event I need to marshal the thread context using the Dispatcher object.

   1: #region IApplicationService Members
   2:  
   3: private ManualResetEvent exitEvent = new ManualResetEvent(false);
   4:  
   5: public void StartService(ApplicationServiceContext context)
   6: {
   7:     ThreadStart start = new ThreadStart(Service_Thread);
   8:     Thread thread = new Thread(start);
   9:     thread.Start();
  10: }
  11:  
  12: public void StopService()
  13: {
  14:     exitEvent.Set();
  15: }
  16:  
  17: #endregion

The FeedPollingService implements the IApplicationContext interface. In the StartService method the service start a thread that do the recurrent polling to the feed. In the StopService method instead a ManualResetEvent is triggered to notify the thread procedure to exit gracefully.

The other part of the application is simply the use of syndication to deserialize the downloaded feed and the binding of the feed items to the interface. The attached source code is available to test the Application Services. Hoping you may find it useful to learn about this new feature, I attach also a full size screenshot of the application running

 

Download Code: (2,07 MB)

Demo Video: (676 KB)

 

ASP.NET 2.0: Pubblicare i file custom con Web Application Project

Se usate la feature di publish del Web Application Project, potreste accorgervi che alcuni file con estensioni custom non vengono pubblicati. Per ovviare a questo problema bisogna impostare la Build Action per i file incriminati a "Content". Semplice, ma se non lo sapete potreste perdere parecchio tempo...

IMHO 2.0: Application Architecure

Ho pubblicato un primo draft che descrive l'architettura di IMHO 2.0. Nel documento è presente uno schema a blocchi e vengono descritti abbastanza in dettaglio i vari componenti che partecipano al funzionamento dell'applicazione. Mi riservo di apportare ulteriori modifiche all'architettura qualora ne rilevi la necessità, anche in risposta a feedback che partano dai lettori.

Link: IMHO 2.0: Application Architecture

IMHO 2.0: Application Architecure

DOCUMENT VERSION

Status: draft

Author: Andrea Boschin
Last Update: 14/10/2005
Current Version: 1.0.0

ABSTRACT

Nel presente documento viene illustrata l'architettura dell'applicazione denominata IMHO codename "Pellestrina", allo scopo di definire l'ambiente in cui verranno collocati i moduli applicativi e l'interazione esistente tra essi. Nello stesso documento verranno anche definiti i punti di estensibilità presso i quali potranno agganciarsi eventuali moduli esterni sviluppati in seguito anche da terze parti.

OBBIETTIVI E SCELTE ARCHITETTURALI

La progettazione dell'architettura di IMHO codename "pellestrina" ha avuto essenzialmente due obbiettivi. Il primo di essi è stato la necessità di realizzare una piattaforma collaborativa che consentisse a postazioni distribuite di concorrere nella gestione di uno o più siti web (blog). Per risolvere questa esigenza si è scelto di suddividere l'applicazione in una parte server ed una client. La parte server avrà la responsabilità di consentire a diversi utenti l'accesso ai contenuti per la creazione di post, la loro categorizzazione, la schedulazione delle attività e la sincronizzazione con i siti veri e propri. Il client sarà la vera e propria interfaccia utente che permette la fruizione delle funzionalità in base ai permessi dell'utente e ai siti ad esso assegnati. La prima scelta architetturale quindi è stata quella di utilizzare .NET Remoting per consentire la comunicazione tra Client e Server.

La tecnologia .NET Remoting è parsa la più efficace e al tempo stesso anche quella più flessibile e adattabile alle esigenze applicative. In seguito a questa scelta e alla necessità di compiere attività sincrone e asincrone anche schedulate si è deciso di realizzare la parte server come un Windows Service che esponga da un lato una serie di "Remote Providers", ognuno dei quali deputato ad un certo ambito dell'applicazione, e dall'altro si occupi di effettuare le operazioni asincrone verso i siti web e di gestire le schedulazioni. In particolare la scelta di avere un certo numero di provider anzichè uno solo è data dalla necessità di ridurre al minimo il numero dei metodi esposti da un singolo oggetto per migliorare le performances del server.

Ulteriori considerazioni hanno consigliato l'adozione di una struttura a Provider anche per la parte di accesso ai dati che è rsidente completamente nella parte server. Tale struttura consente di migrare facilmente e rapidamente l'applicazione su diversi tipi di database. Infatti nonostante inizialmente l'applicazione sia basata su un database Microsoft Access, sarà opportuno in seguito consentire l'adozione di database più potenti quali Sql Server o Oracle. La scelta attuale di utilizzare un database Access è dovuta alla volontà di semplificare al massimo l'installazione del software e di esplorare innanzitutto il gradimento del prodotto prima di orientarsi a prodotti più complessi e costosi.

Il secondo obbiettivo cui l'architettura doveva rispondere era la necessaria espandibilità dell'applicazione, innanzitutto per consentire in futuro lo sviluppo di moduli aggiuntivi, realizzati per soddisfare esigenze specifiche, ma anche per consentire una più facile customizzazione e per spronare la realizzazione di estensioni di terze parti. Per raggiungere questo obbiettivo si è scelto di suddividere l'applicazione in moduli, ognuno dei quali viene caricato nella parte client al momento dell'avvio dell'applicazione. Ad ognuno dei moduli in fase di inizializzazione viene fornito un handle di una finestra host cui essi può agganciarsi con uno o più componenti dei quali in seguito intercetterà gli eventi. Al verificarsi di questi eventi i moduli applicativi, in completa autonomia si collegano al server ed espletano le proprie funzionalità usando i provider remoti definiti specificamente per il loro funzionamento oppure quelli di altri moduli da cui essi dipendono.

COMPONENTI ARCHITETTURALI

Nello schema qui sotto riportato sono definiti in dettaglio i componenti che danno vita all'architettura dell'applicazione e il rapporto che li lega. Lo schema è suddiviso innanzitutto nelle due parti che compongono l'applicazione, Il Client e il Server. Ecco a partire dall'alto quali sono i vari componenti e le funzionalità che essi espletano:

PLUGGABLE USER INTERFACE

L'interfaccia utente, è il fulcro attorno al quale ruota l'estensibilità dell'applicazione. Essa ha la caratteristica di poter acquisire nuove componenti, all'interno di una struttura ben definita, consentendo a tali componenti di vivere autonomamente e di comunicare con gli strati inferiori dell'applicazione. Questa struttura che sarà oggetto di un successivo articolo, espone delle aree entro le quali uno dei moduli applicativi possono agganciare componenti dai quali poi riceveranno notifica degli eventi cui si sono iscritti. L'interfaccia è composta da una form denominata host, che espone le seguenti aree:

  1. Group Bar
  2. Toolbar
  3. Status Bar
  4. Content Area

All'interno di queste aree un modulo può agganciare dei controlli che derivano da opportune classi, che forniscono un subset minimo di funzioni per l'accesso all'interfaccia. La registrazione di queste componenti avviene nel momento dell'istanziazione del modulo sottostante che sfrutta i metodi dell'interfaccia IHost che riceve come unico parametro nel costruttore.

MODULES

Il "Modulo" è l'unità minima che concorre al funzionamento dell'applicazione. Esso viene istanziato dinamicamente sulla base di alcune informazioni che vengono reperite nell'elenco dei moduli installati presente nel file di configurazione. In questo modo chiunque è in grado di registrare un nuovo modulo semplicemente realizzando una classe che estende la classe astratta ImhoModule. In un'architettura 3-tier il modulo è lo strato intermedio che si interpone tra interfaccia e datalayer. L'applicazione definisce al suo interno un certo numero di moduli qui elencati:

  1. Membership Management
  2. Site Management
  3. Post Management
  4. ...

(l'elenco dei moduli deve essere completato)

All'atto della propria creazione un modulo registra presso l'applicazione host i propri controlli e contestualmente si iscrive agli eventi che questi espongono. Per alcuni casi specifici l'host esporra alcuni metodi che consentono la condivisione di componenti di interfaccia anche tra moduli diversi (da valutare). Il modulo accede agli strati inferiori dell'applicazione per mezzo del Controller, sia esso quello standard o uno custom. I moduli inoltre utilizzano il meccanismo dei Principal per determinare quali sono le azioni che possono essere compiute da ogni utente.

CONTROLLER

Scopo primario del controller è quello di mascherare alle parti superiori dell'applicazione le presenza dei provider remoti. Esso a tutti gli effetti si comporta come una façade istanziando i provider remoti e di chiamandone i metodi per ottenerne i risultati in modo del tutto trasparente per gli strati superiori. Inoltre esso è un Singleton, e quindi è accessibile da parte di qualunque modulo senza che la sua referenza debba essere passata da un module ad un altro.

COMMUNICATION SINKS

La comunicazione tra il client e il server avviene per mezzo dei comuni protocolli di rete attraverso messaggi http o tcp in formato binario o SOAP. Questo tipo di comunicazione, unita alla scelta di usare la modalità "Single Call" per i provider remoti fa si che da un lato sia necessario proteggere il canale di comunicazione che altrimenti potrebbe essere facilmente intercettato e dall'altro che sia obbligatorio stabilire un modo per evitare di ripetere l'autenticazione ad ogni chiamata. I channel sinks assolvono proprio a queste esigenze. Primo fra essi, il SessionSink-Client, di occupa di affiancare ad ogni messaggio tra client e server un GUID che rappresenta la sessione corrente. La controparte server del Server del SessionSink rilevata la presenza del GUID verifica la corrispondenza con una sessione nella cache oppure la ricostruisce interrogando la base dati. La cache delle sessioni ha lo scopo di minimizzare l'accesso alla base dati nei momento di intenso utilizzo da parte del client. Assieme alla sessione sul server viene ricostruito anche il Principal all'interno del thread che sta eseguendo la chiamata, per propagare la gestione dei parmessi anche al server. Il secondo sink, denominato Encryption Sink usa una chiave condivisa tra client e server per crittare e decrittare i messaggi in transito tra le due controparti. Al momento la chiave è memorizzata all'interno del file di configurazione sia sul client che sul server, ma è auspicabile che essa possa essere specificata dall'utente al momento della prima registrazione del server sul client.

REMOTE PROVIDERS

Il provider remoto è una classe che estende MarshalByRefObject, il cui compito è di eseguire sul server i metodi chiamati dal client. Nella maggior parte dei casi il provider remoto dovrà accedere alla base dati e lo farà per mezzo del provider dati discusso nel prossimo paragrafo. Tuttavià il provider remoto può anche compiere operazioni differenti dall'accesso ai dati come a titolo esemplificativo: Impartire comandi di controllo al server, interfacciarsi ad altre componenti dell'architettura, etc...  In sostanza il provider è il mezzo con cui il client potrà operare sui dati e sull'engine centrale dell'applicazione. E' possibile registrare ulteriori provider "custom", inserendo le loro caratteristiche all'interno del file di configurazione. In questo modo chiunque potrà sviluppare providers a supporto delle componenti custom registrate negli strati superiori dell'applicazione.

DATA PROVIDER

Il data provider ha lo scopo di astrarre la base dati utilizzata e di contenere al suo interno le chiamate al database esponendole per mezzo di metodi. L'architettura di imho prevede che per l'accesso ai dati e il mapping su oggetti si faccia uso della libreria ORM iBatis. Tale libreria utilizza uno o più file xml che determinano le query da compiere per ottenere i dati. Questo file è parte integrante del dataprovider e deve essere contenuto in esso come embedded resource.

RELEASE HISTORY

Date Description Author
16/10/2005 Rilascio al pubblico Andrea Boschin

Composite UI Application Block CTP2

Da un blog su msdn ho notato che è stata rilasciata la CTP2 di un application block che pare davvero interessante. Si tratta di una serie di classi che dovrebbe aiutare a sviluppare interfacce a componenti, consentendo lo sviluppo e il test separato delle varie componenti per poi arrivare ad un assemblamento finale. Ho solo visto qualche spezzone di codice, ma quello che ho visto mi ha parecchio incuriosito. Chissà se sono riusciti a superare la fastidiosa complessità dell UIP.

Link: Composite UI Application Block Home

powered by IMHO 1.3

Exception Management Application Block

In edicola trovate da alcuni giorni Computer Programming che pubblica il secondo articolo della serie sugli Application Blocks. In questo numero si parla di Exception Management Application Block, un utile libreria per gestire in modo semplice lapubblicazione delle eccezioni. L'articolo può essere anche utile per comprendere la filosofia della Microsoft Enterprise Library 1.0 che riprende ed estende questo application block.

L'esempio di codice illustra un Publisher per inviare via net send le eccezioni generate da una applicazione, senza dover intervenire sul codice della stessa.

Affrettatevi che va a ruba!!!

powered by IMHO

 

Updater Application Block 2.0 Released

Segnalo che è stata pubblicata una nuova release del Updater Application Block, che Lorenzo aveva sostanzialmente "stroncato" nel workshop dello scorso dicembre. Ora bisogna vedere se i limiti che egli aveva segnalato sono stati in qualche modo superati.

Fonte: Check out latest drop of Updater Application Block!

Workspace GotDotNet: http://www.gotdotnet.com/workspaces/workspace.aspx?id=83c68646-befb-4586-ba9f-fdf1301902f5

powered by IMHO

Data Access Application Block - Il primo della serie

Su cortese segnalazione di Lorenzo, vi annuncio che è in edicola il primo dei miei articoli appartenenti alla serie sugli Application Blocks, pubblicati da Infomedia su Computer Programming. Questo mese si parla di Data Access, con un utile esempio su come creare un piccolo ORM homemade che fa uso di reflection e stored-procedures oltre che naturalmente dell'Application Block.

Guai a chi non lo compra!

powered by IMHO

IsolatedStorage provider per Configuration Management Application Block

Sviluppando le nuove feature di IMHO, mi sono trovato a dover estendere il Configuration Management Application Block di Microsoft. L'estensione che ho creato permette di utilizzare L'IsolatedStorage per rendere persistenti le informazioni di configurazione in formato XML, anche crittato e firmato.

Ho pubblicato la libreria e il relativo sorgente all'interno del progetto IMHO, presso Sourceforge. La libreria consta di una classe IsolatedXmlFileStorage realizzata come un provider di storage per l'application block. Essa può essere facilmente collegata ad una applicazione semplicemente modificandone il file di configurazione.

Ecco uno spezzone di codice:

<applicationConfigurationManagement defaultSection="configFile">
    <configSection 
name="configFile">
        <configProvider 
            
assembly="Elite.ApplicationBlocks.ConfigurationManagement,Version=1.0.1833.0,Culture=neutral,PublicKeyToken=null"
            
type="Elite.ApplicationBlocks.ConfigurationManagement.IsolatedXmlFileStorage"
            
file="app.config"
            
signed="true"
            
encrypted="true"/>
        <protectionProvider
            
assembly="Microsoft.ApplicationBlocks.ConfigurationManagement,Version=1.0.0.0,Culture=neutral,PublicKeyToken=null" 
            
type="Microsoft.ApplicationBlocks.ConfigurationManagement.DataProtection.DPAPIDataProtection"
            
hashKey="Ae5+5644aB=" />
    <
/configSection>
<
/applicationConfigurationManagement>

Non appena il sito http://www.imhoproject.org sarà pronto, questa libreria e le altre saranno spostate in una apposita sezione del sito.

La licenza per la libreria è la Common Creative Public License

powered by IMHO 1.1