lunedì 5 febbraio 2007
Tra gli esempi contenuti nel Windows Mobile 5.0 SDK per Pocket PC e per Smartphone ce n'è uno, molto interessante, che mostra come utilizzare il GPS in un'applicazione C#. Una delle classi di questo esempio, tuttavia, ha un piccolo bug: la descrizione del problema e la sua soluzione sono illustrati in questo post.
Qualche giorno fa ho parlato del CompactFormatter, una class library che aggiunge la serializzazione binaria al .NET Compact Framework. In questo momento lo sto utilizzando per un progetto ed ho riscontrato un problema: se tento di serializzare una classe ereditata, i campi della classe base non vengono serializzati. Facendo un'esecuzione passo-passo, si scopre che il problema risiede nella seguente riga di codice, contenuta nel file ClassInspector.cs:
FieldInfo[] array = type.GetFields(BindingFlags.Public| BindingFlags.NonPublic |
BindingFlags.Instance|BindingFlags.DeclaredOnly);
Il metodo
Type.GetFields, utilizzato per recuperare i campi della classe che si sta serializzando, è richiamato con il flag
BindingFlags.DeclaredOnly che, come riporta
MSDN,
search only the fields declared on the Type, not fields that were simply inherited. Di conseguenza, per ottenere una serializzazione di tutti i membri della classe, compresi quelli ereditati, è sufficiente eliminare questo tag, in modo che l'istruzione sopra riportata diventi:
FieldInfo[] array = type.GetFields(BindingFlags.Public| BindingFlags.NonPublic |
BindingFlags.Instance);
La gestione delle connessioni ricopre un ruolo fondamentale in ogni applicazione per dispositivi mobili: spesso è necessario sapere quali sono le reti disponibili e identificarne le caratteristiche. Purtroppo il .NET Compact Framework non offre un supporto nativo per questi task. In una situazione del genere ci viene in aiuto lo Smart Device Framework: esso, infatti, fornisce una serie di classi mediante le quali è possibile gestire le proprietà delle reti identificate, ricevere notifiche quando viene individuata una nuova connessione, ecc. A questo indirizzo è disponibile una breve introduzione all'argomento, corredata da un esempio scritto in VB .NET.
Cosa succede quando un metodo che prende in ingresso uno Stream termina la sua esecuzione? Lo stream deve rimanere aperto oppure essere chiuso? In alcuni casi, è corretto che esso venga chiuso: ad esempio, se lo stream in questione è un FileStream, in questo modo all'uscita del metodo si ha a disposizione un file correttamente salvato su disco. In altre situazioni, però, lo stream dovrebbe rimanere aperto, perché si vogliono fare alcune elaborazioni sui dati che sono stati riversati in esso; pensiamo al MemoryStream: dopo che il metodo vi ha copiato il suo output, si potrebbe voler accedere ad esso per recuperare l'array di byte corrispondente ed inviarlo, ad esempio, su una connessione TCP.
La seguente situazione, quindi, potrebbe essere fonte di problemi: si utilizza il metodo di una libreria di terze parti, di cui non si ha il codice sorgente, il quale prende in ingresso uno stream e lo chiude al termine della sua elaborazione, ma in realtà si avrebbe bisogno che rimanesse aperto. In un caso del genere, per aggirare il problema è possibile estendere il tipo contenente lo stream che si sta utilizzando, ridefinendo il suo metodo Close:
namespace System.IO
{
class ClosableMemoryStream : MemoryStream
{
private bool _closeable;
public bool Closeable
{
get { return _closeable; }
set { _closeable = value; }
}
public ClosableMemoryStream()
: base()
{
_closeable = true;
}
public override void Close()
{
if (_closeable)
base.Close();
}
public void ForceClose()
{
base.Close();
}
}
}
In questo esempio si tratta di un MemoryStream. La proprietà Closable specifica se lo stream deve essere chiuso quando si richiama il suo metodo Close. Per evitare che lo stream venga chiuso dal metodo della libreria, è sufficiente passare a quest'ultima un oggetto di tipo ClosableMemoryStream (anziché MemoryStream), dopo aver impostato la sua proprietà Closable su false: quando sarà richiamato il metodo Close, verrà eseguito il suo override, quindi lo stream in realtà rimarrà aperto. Dopo aver effettuato tutte le elaborazioni necessarie, per la chiusura vera e propria è necessario richiamare il metodo ForceClose.
A
questo indirizzo è disponibile un add-in per
Microsoft Word che consente di aprire e salvare documenti nel formato
Open Document (ODF). L'add-in richiede il .NET Framework 2.0 ed è compatibile con le versioni XP, 2003 e 2007 di Word.
Qualche giorno fa ho creato un nuovo progetto su CodePlex, ma ho preferito fare un paio di check-in prima di segnalarlo. Il progetto si chiama Windows Vista Controls for .NET 2.0 ed ha l'obiettivo di creare una Windows Control Library contenente un insieme di controlli che riproducono l'aspetto degli elementi grafici di Windows Vista, ad esempio pulsanti con l'icona dello scudo, TextBox con il cue banner e così via...
Come sempre, chiunque sia interessato può mandarmi una mail a marco.minerva@gmail.com per entrare a far parte del team di sviluppo.
Il progetto Speech Server .NET sta pian piano crescendo
. Con gli ultimi aggiornementi ho semplificato la procedura di scambio dei messaggi tra client e server, aumentandone la velocità, ed ho aggiunto il supporto per l'utilizzo di motori di TTS e ASR in lingue diverse dall'inglese. Inoltre, ho fatto qualche test con il riconoscimento vocale si Microsoft: utilizzando una grammatica, la percentuale di riconoscimento si è mantenuta sempre a livelli più che buoni. Il riconoscimento del parlato libero, invece, lascia un po' a desiderare, ma per adesso ho utilizzato solo il motore SAPI 5.1 con Windows XP, quindi con Windows Vista si dovrebbero ottenere risultati migliori.
Ho appena installato Microsoft Express Web. La prima impressione è quella di uno strumento veramente ben fatto: non è ancora ai livelli di Dreamweaver, ma rappresenta comunque un grande passo avanti rispetto a FrontPage. Inoltre, Expression Web consente di creare pagine HTML statiche, ASPX, Master page, fogli di stile, Web user control e molto altro ancora... Questa sera spero di potermi ritagliare un po' di tempo da dedicare a qualche prova più approfondita 
Se si tenta di serializzare una classe che contiene un evento, si ottiene un errore in fase di esecuzione: come è logico intuire, infatti, gli eventi non possono essere serializzati. Per risolvere il problema è sufficiente aggiungere l'attributo [field:NonSerialized] davanti alla dichiarazione dell'evento:
[field:NonSerialized]
public event EventHandler StatusChanged;
Questo significa che, dopo aver deserializzato la classe, è necessario registrarsi nuovamente sugli eventi da essa definiti.
Purtroppo l'attributo [field:NonSerialized] non è supportato da VB .NET: in questo caso, per serializzare oggetti che contengono eventi è necessaria una procedura più lunga, descritta in questo post.