Latest Posts
StructureMap è un maturo (apparentemente il più vecchio) IoC tool per .Net. Non è mia intenzione in questo post dimostrare come usarlo o spiegarne le funzionalità e neppure parlare di IoC o DI…per quello c’è Google. Piuttosto, mi interessa analizzare l’implementazione di un suo componente, il Registry DSL – riporto dal sito ufficiale:
“The Registry DSL is the recommended way to configure StructureMap, and creating Registry classes is the recommended way of using the Registry DSL. The Registry DSL is mostly a Fluent Interface with some Nested Closure usage. The intent of the Registry DSL is to make the configuration process as error free as possible by using "compiler safe" expressions and defensive programming to point out missing data. With the advent of .Net 3.5, the Registry DSL is now making use of Expressions as well.”
Perché il DSL Registry
La prima cosa che mi sono chiesto è se era necessario il Registry DSL. StructureMap funzionava anche prima che il DSL Registry fosse introdotto. Il suo core da IoC container era già presente e non è stato modificato con l’introduzione del DSL. Quello che il DSL ha introdotto, però, è un nuovo modo per me (utilizzatore) per configurare il Container. Per esempio, prima dovevo usare un file di configurazione o una sintassi fortemente legata all’implementazione interna del container (una command query api). Adesso, invece, posso usare un linguaggio molto più naturale, intuitivo e costruito nel mio linguaggio di sviluppo. Quindi, in altre parole, il nuovo DSL Registry rende la mia vita più facile.
Ok, tutto molto interessante, ma vediamo un po’ il codice.
Come punto di partenza, prendo questo snippet usato per registrare/configurare un classico repository:
public class DomainRegistry : Registry
{
public DomainRegistry()
{
...
ForRequestedType<IDiaryRepository>().TheDefault.Is.OfConcreteType<SqlDiaryRepository>()
.WithCtorArg("connectionString").EqualTo(connString);
}
}
Expression Builder
La classe Registry rappresenta la root del DSL; ne espone infatti tutta la grammatica.
ForRequestedType<T> è definito così in IRegistry:
// Registering Types -- BuildInstancesOf() and ForRequestedType() are Synonyms
CreatePluginFamilyExpression<PLUGINTYPE> ForRequestedType<PLUGINTYPE>();
CreatePluginFamilyExpression (che ha un nome che non mi piace per essere una classe) è uno dei diversi Expression Builders utilizzati dal DSL per configurare un mio servizio/componente che voglio registrare. Ho detto prima che questo DSL rende la vita di un utilizzatore più semplice, ma come? Attraverso a fluent interface over a normal command-query API, che è messa a disposizione proprio da un Expression Builder.
Un Expression Builder, in questo contesto, non ha nulla a che fare con le Linq Expressions. E’ piuttosto un gruppo di oggetti che espone una fluent interface che astrae o incapsula in una sintassi più chiara all’utilizzatore le reali funzionalità interne di una API già esistente.
ForRequestedType<T> è uno degli entry points per la grammatica.
public CreatePluginFamilyExpression<PLUGINTYPE> ForRequestedType<PLUGINTYPE>()
{
return new CreatePluginFamilyExpression<PLUGINTYPE>(this);
}
Come si può notare non fa altro che restituire una nuova di CreatePluginFamilyExpression, nel cui costruttore comincia la vera e propria fase di registrazione del PLUGINTYPE. Non ne riporto il codice ma vorrei far notare (vedi il parametro in input sul costruttore) come l’Expression Builder lavori sull’oggetto Registry e mantenga un suo stato interno che verrà man mano modificato dalla catena di chiamate successive. Questi side effects che in una classica implementazione sarebbero segni di bad design, sono caratteristiche comuni di un DSL come questo.
L’inizio della catena
“TheDefault” è una proprietà su CreatePluginFamilyExpression che ritorna un altro tipo di Expression Builder:
/// <summary>
/// Define the Default Instance for this PluginType
/// </summary>
public IsExpression<PLUGINTYPE> TheDefault
{
get { return new InstanceExpression<PLUGINTYPE>(i => registerDefault(i)); }
}
“IsExpression<PLUGINTYPE>” espone la grammatica per definire l’istanza di default del mio PLUGINTYPE ed inizia la catena di chiamate “fluent”.
Focus sulla sintassi
E’ interessante notare come “Is” si limiti ad arricchire la sintassi, non modificando affatto lo stato stato dell’expression.
IInstanceExpression<T> IsExpression<T>.Is
{
get { return this; }
}
Progressive Interface
La chiamata a “OfConcreteType<SqlDiaryRepository>()” finalmente mi permette di definire e configurare il tipo concreto che voglio mi sia restituito dal container quando viene richiesta l’interfaccia IDiaryRepository. Tale tipo è rappresentato dalla classe (questo nome mi piace) SmartInstance<T>. Questa classe è “smart” perchè mi permette di configurare il mio tipo in diversi modi (EnrichWith, WithCtorArg, WithProperty, …).
Ognuno di questi metodi è parte di una progressive interface, cioè una fluent interface che ritorna sempre lo stesso oggetto ad ogni passo delle catena, ma incapsulato in interfacce diverse. In questo modo la sequenza delle chiamate viene imposta dall’API e l’utilizzatore viene “forzato” ad effettuare solo chiamate legali, anche grazie all’Intellisense (defensive programming).
public PropertyExpression<SmartInstance<T>> WithCtorArg(string argumentName)
{
return new PropertyExpression<SmartInstance<T>>(this, argumentName);
}
Nel mio esempio configuro la connection string e l’ultima chiamata è a “EqualTo” che, intelligentemente restituisce di nuovo la SmartInstance<T> di prima, cosi che possa continuare a configurarla se necessario.
public T EqualTo(object propertyValue)
{
_instance.SetProperty(_propertyName, propertyValue.ToString());
return (T) _instance;
}
Il resto
Finora ho analizzato una semplice sequenza di chiamate. Il Registry DSL offre molto di più, ma in fondo i concetti usati sono quelli già visti. Degno di nota è l’utilizzo, in certi casi, di lambda expressions per effettuare static reflection, piuttosto che dinamyc reflection.
L’autore, nell’introduzione, menziona anche “nested closure”. Il termine è accattivante, ma, a meno che non mi sia sfuggito qualcosa, non sono altro che lambda functions intelligentemente utilizzate per isolare e ritardare certe esecuzioni.
Off Topic
La classe SpecificationExtensions non è direttamente legata al Registry DSL, ma credo sia interessante. Contiene tutta una serie di extensions methods che rendono la fase di Assert negli unit test molto leggibile a parer mio. Per esempio:
theClass.Services.Length.ShouldEqual(3);
Dove
public static object ShouldEqual(this object actual, object expected)
{
Assert.AreEqual(expected, actual);
return expected;
}
Elegante. Ancora una volta il “fluent pattern” che torna utile...in questo caso come si chiama però?? Fluent Extension? :)
Conclusione
Devo ammettere che appena ho aperto la solution di StructureMap ho preso un po’ paura. Il progetto è piuttosto maturo e il code base lo dimostra, certamente molto piu’ complesso di Funq che avevo analizzato nel post precedente. Anche per questo mi sono concentrato su un singolo componente.
Ho scelto il Registry DSL perché è basato su concetti che generalmente non uso, specifici dei DSL (dovrei chiarire che sono specifici degli internal DSL). Ne avevo sentito parlare e avevo letto qualcosa a proposito, ma vagamente, senza troppo impegno. E’ stato illuminante vederne alcuni applicati nella pratica.
Per l’utilizzatore, credo sia tangibile il vantaggio di avere a disposizione un DSL così, ma tutto ha un costo. IMHO, il costo più alto di una tale API è la perdita di chiarezza nell’implementazione dell’API stessa. Il codice non è facile da leggere e da seguire, visti anche i diversi side effects, la nomenclatura è strana quando la si guarda da dentro (cioè dal punto di vista dell’implementatore). Con questo non voglio dire che sia stata mal disegnata, credo piuttosto che sia una sua caratteristica (o un prezzo da pagare) difficile da eliminare.
Essendo questo semplicemente un post su un semplice blog, non ha nessuna pretesa di essere esaustivo sull’argomento, ma probabilmente, a qualcuno verrà la voglia di approfondire.
Implementa l’interfaccia IList, usa un array che dinamicamente aumenta la sua dimensione se richiesto.
Implementazioni:
IList
Osservazioni:
Non è garantito che gli elementi nell’ArrayList siano ordinati.
La capacità dell’ArrayList è in numero degli elementi che può tenere in memoria.
Se il numero di elementi aumenta, anche la dimensione dell’ArrayList aumenterà.
Se il numero degli elementi diminuisce, per ridimensionare l’ArrayList bisognerà chiamare il metodo TrimToSize o settando
la proprietà Capacity.
Possiamo accedere agli elementi dell’ArrayList tramite un’indice. L’indice parte da 0.
L’ArrayList accetta elementi null e due elementi possono essere uguali.
Thread Safety:
I members public static sono thread safe.
Per garantire le operazioni multi-thread, bisogna istanziare un array tramite il metodo ArrayList.Synchronized
Code Snippet
- // Creates and initializes a new ArrayList.
- ArrayList myAL = new ArrayList();
- myAL.Add("The");
- myAL.Add("quick");
- myAL.Add("brown");
- myAL.Add("fox");
- // Creates a synchronized wrapper around the ArrayList.
- ArrayList mySyncdAL = ArrayList.Synchronized(myAL);
- // Displays the sychronization status of both ArrayLists.
- Console.WriteLine("myAL is {0}.", myAL.IsSynchronized ? "synchronized" : "not synchronized");
- Console.WriteLine("mySyncdAL is {0}.", mySyncdAL.IsSynchronized ? "synchronized" : "not synchronized");
Durante l’enumerazione degli oggetti nella collection potremmo comunque incappare in un’eccezzione se altri thread modificano la collezione anche se questa è sincronizzata.
Per garantire anche l’accesso durante l’enumerazione bisogna lockare la collection durante l’operazione o catchare l’eccezione per notificare il cambio anche agli altri threads.
Questo è un post introduttivo per i post seguenti questo argomento.
DataContract - Serializzazione
L’attributo DataContract è uno dei primi con cui si ha a che fare nel momento in cui si inizierà a scrivere un servizio WCF.
All’interno di un servizio WCF i dati possono avere una certa complessità; quando, gli stessi, vengono spediti vengono rappresentati
tramite un XML Schema Definition (XSD).
DataContract è il mezzo usato da WCF per mappare i tipi .NET CLR con le loro rappresentazioni XSD.
Il decoratore [DataContract] è usato per specificare quale classe deve essere specificata nell’XSD e esposto nell’WSDL esposto dal servizio.
Il decoratore [DataMember] è usato invece per specificare quali membri della classe devono essere specificati nell’XSD.
A runtime la classe DataContractSerializer serializza l’oggetto in XML usanto le regole specificate con gli attributi [DataContract] e [DataMember].
Ecco un esempio, questa è la nostra classe:
Code Snippet
- [DataContract]
- public class CompositeType
- {
- bool boolValue = true;
- string stringValue = "Hello ";
- [DataMember]
- public bool BoolValue
- {
- get { return boolValue; }
- set { boolValue = value; }
- }
- [DataMember]
- public string StringValue
- {
- get { return stringValue; }
- set { stringValue = value; }
- }
- }
Questo l’WSDL ottenuto:
Code Snippet
- <GetDataUsingDataContractResponse xmlns="http://tempuri.org/">
- < GetDataUsingDataContractResult xmlns:a="http://schemas.datacontract.org/2004/07/WcfService1" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
- < a:BoolValue>false</a:BoolValue>
- < a:StringValue>Hello </a:StringValue>
- </ GetDataUsingDataContractResult>
- </ GetDataUsingDataContractResponse>
In definitiva, la classe DataContractAttribute == [DataContract] specifica o implementa il tipo dei dati da serializzare tramite un serializer, ad esempio tramite la classe DataContractSerializer.
Per Serializzazione solitamente si descrive il processo di conversione di un oggetto in un array di bytes; tale processo viene usato per salvare lo stato di un oggetto su un file o su un database,
copiare lo stato sul clipboard, per trasferire l’oggetto tra un’applicazione ad un’altra tramire un network e per migliorarne la mantenibilità.
Con WCF, serializzare, si intende come un oggetto .NET e mappato nell’XML Infosets.
WCF supporta 3 serializer: XmlSerializer, DataContractSerializer e NetDataContractSerializer.
Tutte e 3 hanno possiedono un algoritmo di mapping diverso, ma lo scopo è sempre lo stesso: mappare gli oggetti .NET in XML Infosets.
Encoding
Abbiamo appena finito di descrivere la Serializzazione ed adesso possiamo capire che distinzione fa WCF con l’Encoding.
Encoding è il termine usato per descrivere il processo di conversione di un messaggio in un array di bytes.
WCF supporta cinque tipi di formati di encoding:
- binary
- text
- Message Transmission Optimization Mechanism (MTOM)
- JavaScript Objeect Notation
- Plain-Old-XML (POX)
Quale di questi formati usare, dipende dal tipo di applicazione che stiamo sviluppando.
Ad esempio vorremmo usare il BinaryMessageEncoder per ottimizzare le performance tra le applicazioni, oppure usare TextMessageEncoder o MtomMessageEncoder per mantenere
l’interoperabilità basata sui vecchi servizi WS-* Web Services, o usare JsonMessageEncoder per AJAX
Se provaste a usare encodings diversi per scrivere lo stesso XML Infosets, otterrete N differenti byte streams, comunque rappresenterebbero gli stessi dati.
L’encoding non è considerato parte del contratto del servizio, ma piuttosto una configurazione dell’endpoint.
Conclusione
La separazione tra Serializzazione e Encoding rende possibile la creazione di applicazioni molto flessibili.
Questo è un cavallo di battaglia di WCF, perchè gli da la possibilità di configurarsi con qualsiasi scenario.
Se abbiamo bisogno di performance allora possiamo usare un encoder se invece necessitiamo di interoperabilità allora sceglieremo un formato testuale.
E’ ormai diventato un MUST l’uso di codici di verifica (CAPTCHA). Se occorre qualcosa di professionale e davvero ben fatto consiglio ReCaptcha!
Per abbonati MSDN, Technet e partners, verra’ rilasciato in contemporanea alla WPC09 (Worldwide Partner Conference)
Ho gia tre computers pronti per l’upgrade ;)
Windows 7 in RTM fra pochi giorni
Technorati Tags:
Windows,
7
Un ora fa ho scritto una mail al mio fornitore di hardware, chiedendo alcuni prezzi di box esterni per RAID sata. Dopo un’oretta vado a rivedere gmail per vedere se mi ha risposto. La risposta non è arrivata, ma vedo questo.
Secondo me è anche per questo che Google è veramente avanti.
alk.
.... le giornate in TSF Spa a parlare della Team Suite e di TFS nell'ottica di progetti enterprise sono state dense e professionalmente appaganti aver concentrato in 4 giornate il "mattone" ha richiesto un pò di resistenza fisica. Ieri abbiamo avuto come ospite lampo anche Microsoft.
Insomma sono contenta che la piattaforma sia piaciuta, dei feedback da macchinetta del caffè, un pò meno contenta per la pioggia pomeridiana e vabbè ma non si può avere tutto!
Ed ora ultime slide e demo :)
E’ online il nuovo portale Microsoft sulla sicurezza:
http://www.microsoft.com/security/portal/
E’ possibile seguire anche il relativo blog qui:
http://blogs.technet.com/mmpc/
Essendo una domanda ricorrente credo sia il caso di bloggarla: “Se il mio ViewModel espone una proprietà enumerativa, come posso bindarla ad un insieme di radio buttons ?”.
La risposta sta nell’utilizzo di un converter.
Partiamo dal ViewModel:
1: public enum Power {Low,Medium,High}
2:
3: public class TheViewModel
4: {
5: public Power PowerLevel { get; set; }
6: }
ora creiamo un converter che sfruttando la possibilità di ricevere un parametro ritorna true quando il valore della proprietà coincide col parametro passatogli:
1: public class PowerToBooleanConverter : IValueConverter
2: {
3: public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
4: {
5: Power power = (Power)value;
6: Power param = (Power)Enum.Parse(typeof(Power), parameter.ToString());
7: return (power == param);
8: }
9:
10: public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
11: {
12: Power valueToPush = (Power)Enum.Parse(typeof(Power), parameter.ToString());
13: return valueToPush;
14: }
15: }
A questo punto usiamo il ViewModel e relativo converter nello XAML:
1: <Window x:Class="WPFToEnum.Window1"
2: xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
3: xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
4: xmlns:this="clr-namespace:WPFToEnum"
5: Title="Window1" Height="300" Width="300">
6: <Window.Resources>
7: <this:TheViewModel x:Key="tvm" PowerLevel="Medium" />
8: <this:PowerToBooleanConverter x:Key="converter" />
9: </Window.Resources>
10: <StackPanel DataContext="{StaticResource tvm}">
11: <RadioButton IsChecked="{Binding PowerLevel, Converter={StaticResource converter}, ConverterParameter=Low}">Low</RadioButton>
12: <RadioButton IsChecked="{Binding PowerLevel, Converter={StaticResource converter}, ConverterParameter=Medium}">Medium</RadioButton>
13: <RadioButton IsChecked="{Binding PowerLevel, Converter={StaticResource converter}, ConverterParameter=High}">High</RadioButton>
14: </StackPanel>
15: </Window>
e il gioco è fatto… 
http://www.giornaleditreviglio.it/login.php?artID=1136762
Da notare che sulla versione cartacea la notizia è su 9 colonne… dei veri personaggi inutili… :-D
.m
I telefoni cellulari esistono da un bel po’ di tempo ormai ma in questi ultimi anni, diciamo almeno un paio, la sensazione è che la qualità delle comunicazioni (le telefonate in particolare) via cellulare siano drasticamente peggiorate.
Ora… la tecnologia ha fatto passi da gigante quindi l’unica spiegazione che mi do, si lo so sono sempre in malafede… ma si sa siamo italiani e siamo molto abituati ad essere presi per il c*lo, è che qualcuno investa molto in pubblicità ma un gran poco in infrastrutture, quindi il numero di terminali è cresciuto andando ben oltre quello che l’attuale rete è in grado di sopportare/gestire.
Semplici elucubrazioni personali… ma sta di fatto che parlare al cellulare è spesso un’impresa.
.m
Gli amici sono arrivati.
Arance, cannoli, arancine, mozzarelle in carrozza, caponatina, pani ca mivusa, cazzilli, mussu, pani e panelle, cassata, cannolo africano, iris con nutella e con ricotta,
pasta al forno, pasta tinnirumi e zucchina, parmigiana, gelsi, fichi, fichi d’india, limoni e stigghiola.
E’ realmente tutto pronto, forse mancano ancora un paio di sedie e le tovaglie di lino.
Ma le otri son piene del vino buono (Nero d’Avola, ovvio).
Adesso tocca a noi, bavaglini al collo e via di coltello e forchetta.
Buon appetito!!!
http://www.orangedotnet.org/
Leggere questo post di Janky mi ha davvero fatto piacere.
Ricordo le divergenze di opinione di qualche anno (!?!) fa, quando nacque il primo User Group “locale” su .NET (se non ricordo male, XeDotNet).
Forse l’opinione “pubblica” si trovava di fronte un concetto nuovo, probabilmente l’affetto per UGIdotNET faceva temere una “sovrapposizione”; fatto sta che oggi gli user group locali o tematici sono divenuti una realtà diffusa ed apprezzata.
Chi è residente a Milano o nelle vicine province, ha avuto la fortuna in questi anni di poter assistere ai workshop di UGIdotNET senza trasferte “epiche” (anche se comunque per fare quei 18 Km dalla SS36 a Segrate alle 9.00 in auto, ci si impiega ben più di un’ora) e di conseguenza non si è mai sentita la mancanza di uno user group locale perchè UGIdotNET stesso ne faceva le veci.
Di contro attualmente la situazione è un po’ cambiata. Escludendo i molteplici eventi after-hour (in effetti un ottimo connubio tra svago e “lavoro”), gli ottimi Community Days (multi-community) a cui partecipo sempre con soddisfazione e l’ultimo workshop a Predappio, si deve tornare al 13 dicembre 2007 per l’ultimo workshop UGIdotNET “tradizionale” svoltosi in Lombardia.
Intendiamoci, non è una critica, anzi ho già scritto in precedenza che lodo la scelta di tenere dei workshop UGIdotNET in giro per l’Italia, ma solo la constatazione che sento parecchio la mancanza di quei workshop, quell’appuntamento quasi trimestrale che ha cambiato completamente il mio modo di approcciare lo sviluppo software.
Non so come dirlo senza paura di “mancare di rispetto” (è la frase più “trasparente” che mi viene) ad UGIdotNET ed ancor più all’enorme lavoro costantemente svolto dal nostro Presidente, ma forse attualmente potrebbe essere davvero una buona idea almeno provare insieme ad organizzare un primo workshop “locale” di prova (Lecco? Monza? Milano?).
Che ne dite? Idea folle / sbagliata / inutile / interessante?
La classe BrowserInformation contenuta in System.Windows.Browser permette di ricavare informazioni sul browser corrente , di seguito vengono illustrati i membri principali e una loro breve descrizione
System.Windows.Browser
| Nome |
Descrizione |
| BrowserInformation |
Otteniamo la versione del browser corrente |
| CookiesEnabled |
Ottiene un valore che indica se il browser supporta i cookies |
| Name |
Ottiene il nome del browser in uso |
| UserAgent |
Ottiene la stringa dell'user agent del browser
|
Visualizzare le informazioni
Possiamo visualizzare le informazioni scrivendo semplicemente
HtmlPage.BrowserInformation.Proprietà
Esempio
HtmlPage.BrowserInformation.CookiesEnabled indica se il browser in uso supporta i cookies
HtmlPage.BrowserInformation.Platform indica la piattaforma corrente es.win32
Ecc...
Ho provato ad eseguire un piccola prova anche con linux debian 5.0 (eseguendo il componente silverlight con l'oramai noto componente Moonlight V1.0.1) ed ha funzionato benissimo . Prossimamente allegherò l'esempio che adesso non ho qui con me. Ma se siete curiosi potete scrivermi e per me sarà un piacere inviarvelo.
Un saluto e buon weekend a tutti
Come già anticipato in un mio precedente post, l’approccio basato su file XAML only per creare applicazioni con pattern MVVM che permettano una personalizzazione spinta dell’interfaccia, si scontra con l’impossibilità di inserire uno user control SENZA codebehind all’interno di una window (o di una page).
Tanto per intenderci, faccio un parallelo con ASP.net, essendo il concetto molto simile a quello che supporta i Web User Control (ascx).
In ASP.net ho una pagina, che contiene uno user control. Questo viene “registrato” in cima alla pagina con una “direttiva” del tipo:
1: <%@ Register TagPrefix="dnn" TagName="LANGUAGE" Src="~/Admin/Skins/Language.ascx" %>
2: ...
3: omissis
4: ...
5: <dnn:LANGUAGE runat="server" id="dnnLANGUAGE" showMenu="False" showLinks="True" />
In pratica, diciamo al compilatore di ASP.net: “quando compili la pagina, riferisciti a quel file sul disco e gestiscilo inserendo nella pagina il frammento di codice ASP.net che gli compete, agganciando tutti gli eventi nel code behind…”.
Questo concetto manca in WPF. Innanzitutto una precisazione è d’obbligo: gli UserControl sono praticamente identici ai controlli Utente Web, ma non possono essere usati senza avere una classe di code-behind compilata. Questo è dovuto al fatto che, per referenziare uno user control in una window o in una page, bisogna includere un riferimento all’assembly ed al namespace che lo contiene. Vediamo due snippets della pagina e dello User Control “Standard”:
1: <Window x:Class="WpfApplication1.Window1"
2: xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
3: xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
4: xmlns:my="clr-namespace:WpfApplication1"
5: Title="Window1" Height="300" Width="300">
6: <Grid>
7: <my:StandardUC/>
8: </Grid>
9: </Window>
1: <UserControl x:Class="WpfApplication1.StandardUC"
2: xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
3: xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
4: <StackPanel>
5: <TextBox x:Name="txtHello"></TextBox>
6: <Button x:Name="btnHello" Content="Click me!" Click="btnHello_Click"/>
7: </StackPanel>
8: </UserControl>
Quello che deve balzare agli occhi, è il riferimento xmlns:my=”clr-namespace:WpfApplication1” che indica dove trovare il controllo compilato, e non dice nulla riguardo alla parte XAML. Questo perchè in effetti, in fase di compilazione, la parte XAML viene tramutata in file .g (generated) e compilato come baml. A run time lo ritroveremo nel file .exe all’interno della sezione resources (Reflector rulez!)
Il punto è che, comunque, non c’è modo di specificare un riferimento ad un file fisico che verrà caricato dal disco a run-time. A questo punto sono d’obbligo un paio di citazioni: durante una chiacchierata virtuale con l’amico Andrea Boschin, e dopo aver parlato anche con il WPF-Guru Corrado Cavalli, è emersa una soluzione, che mi appresto a riportare.
Si tratta di creare una class CustomUserControl, la quale eredita da ContentControl, aggiungere una proprietà Source e sovrascrivere il metodo OnInitialize come si può vedere nel seguente snippet:
1: using System;
2: using System.Xml;
3: using System.Windows.Controls;
4: using System.Windows.Markup;
5:
6: namespace WpfApplication1
7: {
8: public class CustomUserControl : ContentControl
9: {
10: public string Source { get; set; }
11:
12: protected override void OnInitialized(EventArgs e)
13: {
14: base.OnInitialized(e);
15: XmlTextReader reader = new XmlTextReader(this.Source);
16: base.Content = XamlReader.Load(reader);
17: }
18: }
19: }
Ovviamente, questa diventa una specie di classe “base” per tutti i controlli Codebehind-less, per cui, quando li vorremo includere nella window dovremo fare come segue:
1: <Window x:Class="WpfApplication1.Window1"
2: xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
3: xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
4: xmlns:my="clr-namespace:WpfApplication1"
5: Title="Window1" Height="300" Width="300">
6: <Grid>
7: <my:CustomUserControl Source="UserControl1.xaml"/>
8: </Grid>
9: </Window>
Ovvero utilizzare il riferimento al namespace che contiene la classe base, impiegare il controllo CustomUserControl ed impostare il file XAML da caricare a run-time.
In questo modo è stato superato il limite degli User Control in applicazione MVVM che mantengono le interfacce XAML esterne rispetto al compilato. Nel caso di MVVM gli UserControl con adeguati comandi di binding possono essere utilizzati come DataTemplate in controlli list (ListBox e affini). Ringrazio ancora Andrea e Corrado per il supporto e l’ispirazione… è sempre un piacere potersi confrontare con voi!
Rappresenta una lista di oggetti accessibile tramite un indice.
Implementazioni:
ICollection<T>
IEnumerable<T>
IEnumerable
Osservazioni:
Implementa l’interfaccia generica ICollection<T>.
Thread Safety:
Definisce i metodi per manipola le collezioni generiche.
Implementazioni:
IEnumerable<T>
IEnumerable
Osservazioni:
La versione non generica ICollection definisce dimensioni, enumeratore e i metodi di sincronizzazione.
Le interfacce quali IDictionary<TKey, TValue> e IList<T> sono interfacce specializzate che implementano ICollection<T> e poi le rispettive classi
ne implementano la logica.
Mentre le classi come Queue<T> e Stack<T> implementano direttamente la ICollection<T>.
Thread Safety:
Complice un problema di salute che mi ha tenuto a riposo per svariati giorni…
con ritardo ma con estremo piacere dopo una settimana dalla cena di inaugurazione, posso dire insieme a tutti i ragazzi che mi hanno dato una mano… che siamo finalmente online! Ed abbiamo finalmente anche un nome! :-)
OrangeDotNet è il nome del primo user group siciliano orientato alle tecnologie .NET e dintorni!
Ecco qualche idea guida per le nostre future attività:
1. Contenuti tecnici. Useremo il nostro portale come contenitore di articoli, tips, interview, e cercheremo nei prossimi mesi di scrivere quanta più roba possibile su tutto quello che sarà l’universo Fx 4.0, Visual Studio 2010, e Visual Studio Team System.
2. Blog per i nostri membri. Post e libertà di forma per tutti i nostri membri.
3. Forum di discussione sulle attività della community. Ma per adesso non forum tecnici. Abbiamo notato che c’è troppa dispersione e già tanti forum in italia su cui interagire per problemi tecnici. Per cui continuiamo a frequentare i newsgroup microsoft, il forum ugidotnet e altri per i thread tecnici.
4. Eventi Live. Queste si che sono da sempre le attività più importanti di uno user group. L’interazione live! Puntiamo a eventi/meeting…e pensiamo fortemente ad un primo evento subito dopo l’estate…ovviamente in sicilia, e visto che il clima ci sorride…a settembre ci si può trovare ancora in spiaggia a fare sessioni!
Insomma le danze a questo punto sono iniziate.
Inoltre:
Un “certo” Dino Esposito, di fama internazionale si è anche proposto per fare un “botto” di sessioni, quindi speriamo che conosca anche il siciliano oltre che l’inglese. Volevamo comunicargli che stiamo già facendo il carico di dolci. Grazie Dino! :-)
Ma prima di partire….
Devo ringraziare una persona in particolare (che per giunta è pure estraneo alla community ma che ha promesso che darà contributi personali e possibilmente sarà anche lui uno tra quelli sul palco appena possibile) e cioè lo sciuro "Imperugo” che anche nei giorni in cui stavo male si è fatto in quattro per darmi una mano a tirare su il portale.
Un immenso grazie! Ti aspettiamo giù in riva al mare con il carico di arancini.
PS: Ugo e Dino…se volete fare cambio di “carichi” metterevi d’accordo tra di voi :-)
Dunque…questa è la home page.
Abbiamo scelto l’arancia rossa come logo (forse temporaneo…forse definitivo…bah), perche è un orgoglio tutto siciliano…:-)
Ragazzi siete tutti i benvenuti!
iscrivetevi qui in modo che possiate essere informati dalla newsletter.
Mi sono voluto scontrare di persona con il problema della compatibilità dei broswer e i css. L'uso dei Microsoft Conditional Comments non è in accordo con l'uso dei Themes. Ecco come ho risolto il problema. (continua)
Qualche settimana fa ho visto un documentario (se non ricordo male Ulisse il piacere della scoperta) dedicato hai numeri della vita ossia tutto ciò che mediamente un persona fa, consuma e produce nell’arco della propria esistenza. Mi aveva molto incoriusito tant’è che durante la puntata mi sono munito di carta e penna ed ho preso appunti che ora mi piacerebbe condividere anche perchè sono certo che è capitato a tutti voi di porsi qualche domanda del tipo, chissà nella vita quanto pane si mangia oppure quanta benzina si consuma o quanti km vengono percorsi a piedi. Ecco in questo post forse troverete alcune risposte.
Una piccola premessa prima di fare l’elenco. Il documentario è stato realizzato dalla BBC ed è basato su un Europeo del nord con una vita media di 75 anni. Si seguito l’elenco dei dati emersi :
Tutto quello che Mangiamo e Beviamo:
- 9.000 litri di latte;
- 4 Mucche;
- 21 Pecore;
- 15 Maiali;
- 1.200 Polli;
- 3.624 Uova;
- 2 Tonellate di Pane;
- 5.272 Mele;
- 10.000 Carote;
- 2 Tonellate di Pasta;
- 77 Kg di Fagioli;
- 24.000 tazzine di Caffè:
Tutto quello che di bello e di brutto il nostro corpo produce :
- 9 Mt di Capelli;
- 9,15 Mt di Barba;
- 286 cm di Unghie
- 61,5 Lt di lacrime;
- 36.0000 Lt di aria;
- 3 Tonellate di Feci;
Tutto quello che consumiamo e produciamo
- 3.000 Pannolini;
- 8,5 T di involucri per alimenti;
- 79.000 rotoli di carta igienica;
- 656 Saponette;
- 198 Lt di Shampo;
- 570 Kg di Prodotti Chimici;
- 3 Lavatrici;
- 3 Televisori;
- 40 T di Rifiuti;
- 8 Macchine;
- 136.000 Lt di Benzina;
- 30.000 Pastiglie;
Tutto quello che facciamo
- Conosciamo 1.700 nuove persone;
- Produciamo 123.000.000 di parole;
- Facciamo 7.163 Bagni x 1/2 Milione Lt di acqua;
- Cambiamo 10 partner sessuali;
- Abbiamo 4.239 rapporti sessuali;
- Ci innamoriamo 3 volte;
- Camminiamo per 24.887 Km;
- Laviamo i capelli 11.500 volte;
- Percorriamo in macchina 728.489 Km;
- Trascorriamo 2.944 giorni davanti alla TV;
- Andiamo 314 volte dal medico;
- 11,5 anni è la durata media del matrimonio;
- Sbattiamo 415.000.000 volte le ciglia;
Questa è solo una parte dei dati però sono sufficienti per rendere l’idea di cosa nella vita si fa per sopravvivere
.
Ovviamente alcuni numeri si potrebbero criticare ma non è l’intenzione di questo post anche perchè diventerebbe una statistica troppo individuale