e pure affascinante :-)throw new ServiceException( "Error sending e-mail, but e-mail sent successfully" );
.m
The journey is the most important thing, not the destination. Find your next destination and start travelling again.
e pure affascinante :-)throw new ServiceException( "Error sending e-mail, but e-mail sent successfully" );
trovo che sia decisamente produttivo, in particolare per la platea, partecipare ad un corso dove la docenza è in pair, con 2 docenti, con un background tecnico paragonabile, ma con un background lavorativo diverso perchè porta un arricchimento non da poco.…torniamo “in topic” che è meglio :-)
il tutto viene gestito dal fido Castle quindi quel costruttore per me è decisamente friction-less, in ottica design time data però quella cosa è decisamente scomoda principalmente per 2 motivi:sealed class SubjectsListViewModel : ItemsListViewModel<ISubjectsListView, Subject, Subject, Subject>, ISubjectsListViewModel { public SubjectsListViewModel( IDispatcher dispatcher,
ISubjectsListView view,
IMessageBroker broker,
IDataContextFactory dataContextFactory,
ISubjectsManagementService subjectsService,
IUserInteractionService uiService ) : base( dispatcher, view, broker, SelectionType.Extended ) {
...
}
}
quella classe “Sample” è così definita, scroccando un po’ di sintassi a Fluent NHibernate:<Window x:Class="SubjectsListViewDocument" xmlns:design="http://schemas.topics.it/wpf/subjects/design" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d design"> <Window.Resources> <design:Sample x:Key="sample" /> Window.Resources> <Grid d:DataContext="{StaticResource sample}">
e quello che mi resta da fare è limitarmi a fare quello che farei di solito (funziona perfettamente anche nei vari “property editor” di Blend):public class Sample : DesignTimeHost<ISubjectsListViewModel> { public Sample() { this.Expose( o => o.Items ) .WithValue( new EntityView<Subject>( new List<Subject>() { new Person(){ FirstName = "Mauro", LastName = "Servienti" }, new Company(){ CompanyName = "topics.it" } } ) ) .AsReadOnly(); } }
Ottenendo il risultato di cui sopra, comodo semplice e definibile addirittura in un assembly separato. Complicandomi la vita ho cercato di esporre come design time data un modello ben più complesso (un master detail con un grafo decisamente ostico) incappando nei “soliti” non pochi problemi che però stavolta possono essere brillantemente risolti:<ListView ItemsSource="{Binding Path=Items}"...
utilizzando un tool di mocking, del resto siamo a design time, e producendo di fatto qualcosa di editabile in maniera umana, molto umana:var address1 = MockRepository.GenerateStub<IAddressViewModel>(); address1.Street = "sample street 1"; var address2 = MockRepository.GenerateStub<IAddressViewModel>(); address2.Street = "sample street 2"; this.Expose( e => e.Addresses ) .AsReadOnly() .WithValue( new EntityView<IAddressViewModel>( new List<IAddressViewModel>() { address1, address2 } ) );
Nonostante quel “pannello di warning” sia così definito:<design:Sample x:Key="sample" DesignTimeAreDisplayedDataStale="[False]/[True]" />
Quella proprietà “DesignTimeAreDisplayedDataStale” non esiste sul modello, e quindi non esisterebbe per il tool di mocking, ma esiste per il DesignTimeHost<Border Grid.Row="0" Background="#FFFFFB9C" Visibility="{Binding AreDisplayedDataStale, Converter={StaticResource boolVisConv}}" BorderBrush="#FFFFF630" BorderThickness="1"
Quindi:public sealed class Sample : DesignTimeHost<ISubjectsListViewModel> { public Sample() { this.Expose( o => o.Items ) .WithValue( new EntityView<Subject>( new List<Subject>() { new Person(){ FirstName = "Mauro", LastName = "Servienti" }, new Company(){ CompanyName = "topics.it" } } ) ) .AsReadOnly(); this.Expose( o => o.AreDisplayedDataStale )
.BoundTo( this, s => s.DesignTimeAreDisplayedDataStale )
.WithLiveValue( () => this.DesignTimeAreDisplayedDataStale ) .AsReadOnly(); } private Boolean _designTimeAreDisplayedDataStale = false; public Boolean DesignTimeAreDisplayedDataStale { get { return this._designTimeAreDisplayedDataStale; } set { if( value != this.DesignTimeAreDisplayedDataStale ) { this._designTimeAreDisplayedDataStale = value; this.OnPropertyChanged( e => e.AreDisplayedDataStale ); } } } }
Secondo me è un grave errore pensare che la differenza tra n-layer e n-tier stia solo nel fatto che il boundary è diverso. Non è possibile pensare di scrivere uin’applicazione n-layer e migrarla a n-tier piazzando un po’ qua e un po’ la Wcf e una facility per Castle.Pensate a questo scenario:
IDataContextFactory è un wrapper per la session factory di NHibernate, nulla di trascendentale, il codice esplicita molto bene quello che succede. La IDataContextFactory viene iniettata con Castle Windsor. Adesso immaginamo che:using( var dc = this.dataContextFactory.Create() ) { using( var tx = dc.BegingTransaction( IsolationLevel.Serializable ) ) { dc.Insert( entity ); dc.FlushChanges(); tx.Commit(); } }
il supporto per INotifyPropertyChanged è veramente tedioso da scrivere e ad esempio in un’applicazione Wpf basata su M-V-VM lo scrivere decinaia e decinaia di volte :-)private String _myValue = null; public String MyValue { get { return this._myValue; } set { if( value != this.MyValue ) { this._myValue = value; this.OnPropertyChanged( () => this.MyValue ); } } }
Le 2 cose degne di nota sono la sezione “Declarations”:xml version="1.0" encoding="UTF-8"?> <CodeSnippets xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet"> <CodeSnippet Format="1.0.0"> <Header> <Title>Creates a Property with PropertyChanged Support using lambda expressions.Title> <Author>topics.itAuthor> <Description>Description> <Shortcut>ppclShortcut> <SnippetTypes> <SnippetType>ExpansionSnippetType> SnippetTypes> Header> <Snippet> <Declarations> <Literal Editable="true"> <ID>PropertyNameID> <Default>PropertyNameDefault> Literal> <Literal Editable="true"> <ID>PropertyFieldID> <Default>propertyFieldDefault> Literal> <Literal Editable="true"> <ID>PropertySystemTypeID> <Default>System.ObjectDefault> Literal> <Literal Editable="true"> <ID>PropertyDefaultValueID> <Default>nullDefault> Literal> Declarations> <Code Language="csharp"> private $PropertySystemType$ _$PropertyField$ = $PropertyDefaultValue$; public $PropertySystemType$ $PropertyName$ { get { return this._$PropertyField$; } set { if( value != this.$PropertyName$ ) { this._$PropertyField$ = value; this.OnPropertyChanged( () => this.$PropertyName$ ); } } }$end$]]> Code> Snippet> CodeSnippet> CodeSnippets>
che serve per aggiungere elementi editabili durante la fase di editing, appunto :-), dello snippet, usando il tabulatore sarà possibile “navigare” tra i vari elementi all’interno dell’editor, e la sezione “Code”:<Declarations> <Literal Editable="true"> <ID>PropertyNameID> <Default>PropertyNameDefault> Literal> Declarations>
In cui inserire il blocco di codice che vogliamo snippettare :-)<Code Language="csharp"> private $PropertySystemType$ _$PropertyField$ = $PropertyDefaultValue$; public $PropertySystemType$ $PropertyName$ { get { return this._$PropertyField$; } set { if( value != this.$PropertyName$ ) { this._$PropertyField$ = value; this.OnPropertyChanged( () => this.$PropertyName$ ); } } }$end$]]> Code>
…l’inghippo purtroppo è che chi ha pensato le categorie evidentemente non le ha mai usate perchè per taggare una singola mail perdete ben più di un quarto d’ora… :-/Rules rulez
Windows Registry Editor Version 5.00Se provate a creare quella chiave di registro, senza metterci nulla basta che esista, e poi provate ad editare/creare una Search Folder… tada!:
[HKEY_CURRENT_USER\Software\Microsoft\Office\14.0\Outlook\QueryBuilder]
(Funziona su tutte le versioni di Outlook, basta sostituire a 14.0 il vostro numero di versione)
…Per quanto mi riguarda, non la conoscevo e ne sono rimasto da un lato affascinato, nel senso che, porsi degli obiettivi da 25 minuti non è affatto complesso, e rimanere concentrati per 25 minuti è una cosa fattibile…L’esperienza di queste 2 settimane mi fa dire che:
un dev è un professionista come tanti altri, medici o idraulici ad esempio, e quello che mi aspetto da un medico o da un idraulico è che abbia una buona conoscenza, ma soprattutto confidenza, dei suoi strumenti… quindi come è normale che un idraulico sappia cosa è un sifone mi aspetto che un dev sappia cosa è metticiunpoquellochevuoi di Visual Studio; non mi aspetto che lo sappia usare ma mi aspetto che la curiosità l’abbia spinto almeno a dargli un’occhiata.Detto questo vediamo di affrontare un altro nodo molto importante nell’organizzazione di un qualsiasi progetto software. Nel mio piccolo tendo ad essere un po’ allergico al Class View, non chiedetemi perchè semplicemente faccio fatica ad usarlo e preferisco di gran lunga interfacciarmi con il Solution Explorer.
Purtroppo sempre più spesso consto che questo è molto lontano dalla realtà di tutti i giorni. Che opinione si farebbe un paziente di un dentista che litiga con uno specillo?… e non ditemi che non sapete cosa sia uno specillo… no non è uno specchietto :-)
tralasciate il design che è tutto tranne che importante adesso e nello specifico probabilmente è pure errato ;-) ma non ci interessa quello… come distribuireste gli elementi di cui sopra nella solution? così:interface IEngine { Boolean IsActive { get; } } interface IEngine: IEngine { EngineOperationResult OperateOn( T data ); } enum EngineOperationResult { Success, Aborted, Denied }