Ogni risorsa consumabile in Windows Phone e su qualsiasi piattaforma, viene in genere rappresentata da un URI, come ad esempio http://miosito/miarisorsa.txt, il quale si compone di varie parti:
- http: lo schema;
- la porta: 80 implicita per l'HTTP;
- miosito: il dominio;
- miarisorsa.txt: il path.
Facoltativamente si aggiungono poi la querystring e il fragment. Nel .NET Framework, e quindi anche in Windows Phone, quando si sfruttano le classi WebRequest o WebClient per scaricare una risorsa e proprio in virtù delle provenienza delle risorse, ogni schema determina il motore da utilizzare per ottenere una risposta: se HTTP occorre seguire un certo protocollo, se FTP un altro, se FILE invece occorre utilizzare le API di sistema, e così via.
E' possibile però registrare un proprio schema di propria invenzione, sia per implementare protocolli non supportati da Windows Phone, ma anche per aggiungere e centralizzare funzionalità aggiuntive da applicare ai protocolli già implementati. In questo script ad esempio si pone il semplice obiettivo di evitare, in modo centralizzato, di effettuare richieste HTTP in mancanza già a priori della rete internet, senza aspettare il timeout della richiesta.
In pratica, supponendo di inventare lo schema myhttp, quello che si vuole ottenere è poter scaricare la risorsa in questo modo:
WebClient client = new WebClient(); client.DownloadStringCompleted += new DownloadStringCompletedEventHandler(client_DownloadStringCompleted); client.DownloadStringAsync(new Uri("myhttps://www.aspitalia.com"));
Per farlo occorre prima registrare il prefisso con il relativo oggetto responsabile della creazione delle richieste.
WebRequest.RegisterPrefix("myhttp", new AutoWebRequestCreator());
La classe AutoWebRequestCreator implementa l'interfaccia IWebRequestCreate e compie una semplice scelta: se internet è presente effettua la normale chiamata HTTP, mentre in caso contrario restituisce una fittizia implementazione di WebRequest che non esegue alcuna operazione.
public class AutoWebRequestCreator : IWebRequestCreate { public WebRequest Create(Uri uri) { // Internet è presente if (NetworkInterface.GetIsNetworkAvailable()) { // Restituisco una richiesta HTTP cambiando lo schema return WebRequest.CreateHttp(uri.ToString().Replace("myhttp://", "http://")); } else return new DummyWebRequest(); } }
La classe DummyWebRequest sovrascrive i metodi BeginGetResponse e EndGetResponse per restituire a loro volta un finto IAsyncResult, oggetto che rappresenta l'operazione asincrona.
public class DummyWebRequest : WebRequest { public override IAsyncResult BeginGetResponse(AsyncCallback callback, object state) { // Risultato fittizio DummyAsyncResult ar = new DummyAsyncResult(state); // Chiamo subito il callback callback(ar); return ar; } public override WebResponse EndGetResponse(IAsyncResult asyncResult) { // L'operazione è stata cancellata throw new WebException("Cancelled", WebExceptionStatus.RequestCanceled); } }
Il DummyAsyncResult è invece implementato in modo da restituire costanti che indicano che l'operazione è già terminata.
public class DummyAsyncResult : IAsyncResult { public DummyAsyncResult(object state) { this.AsyncState = state; } public object AsyncState { get; private set; } public System.Threading.WaitHandle AsyncWaitHandle { get { return null; } } public bool CompletedSynchronously { get { return true; } } public bool IsCompleted { get { return true; } } }
I vantaggi che si ottengono con questo approccio sono molteplici. Per prima cosa si centralizzano una logica che, seppur semplice in questo esempio, è brutto e scomodo da replicare. Inoltre rende tutto piuttosto trasparente per quanto riguarda l'accesso alle risorse e infine permette di implementare scenari più evoluti. Ad esempio è possibile implementare una coda in modo da sequenzializzare le chiamate, oppure effettuare una cache sulle risorse web ed evitare di andare fisicamente sulla rete, recuperando il risultato dalla memoria o dall'isolated storage.
Commenti
Per inserire un commento, devi avere un account.
Fai il login e torna a questa pagina, oppure registrati alla nostra community.
Approfondimenti
Estrarre dati randomici da una lista di oggetti in C#
Creare una libreria CSS universale - Rotazione degli elementi
Ordine e importanza per @layer in CSS
Generare velocemente pagine CRUD in Blazor con QuickGrid
Fissare una versione dell'agent nelle pipeline di Azure DevOps
Recuperare App Service cancellati su Azure
Applicare un filtro per recuperare alcune issue di GitHub
Gestione file Javascript in Blazor con .NET 9
Loggare le query più lente con Entity Framework
Ordinare randomicamente una lista in C#
Popolare una classe a partire dal testo, con Semantic Kernel e ASP.NET Core Web API
Introduzione ai web component HTML