<?xml version='1.0' encoding='UTF-8'?><rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearchrss/1.0/" xmlns:blogger="http://schemas.google.com/blogger/2008" xmlns:georss="http://www.georss.org/georss" xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr="http://purl.org/syndication/thread/1.0" version="2.0"><channel><atom:id>tag:blogger.com,1999:blog-5601714198208780275</atom:id><lastBuildDate>Wed, 07 Mar 2018 20:47:49 +0000</lastBuildDate><category>Entwicklung</category><category>VSTO</category><category>OpenXml SDK</category><category>Architektur</category><category>Word 2007</category><category>Design Pattern</category><category>StructureMap</category><category>Continuous Integration</category><category>Office 2007</category><category>Community</category><category>OpenXml</category><category>Sharepoint Server 2010</category><category>ASP.NET</category><category>Artikel</category><category>AOP</category><category>Agile</category><category>CAB</category><category>Fluent NHibernate</category><category>MEF</category><category>MVVM Light</category><category>NHibernate</category><category>Scrum</category><category>TFS</category><category>WPF</category><category>Webcast</category><category>offline</category><title>Attic...</title><description>Dies und Das aus dem .NET Entwicklerleben - www.codegemini.net</description><link>http://jcselke.blogspot.com/</link><managingEditor>noreply@blogger.com (Jan Christian Selke)</managingEditor><generator>Blogger</generator><openSearch:totalResults>63</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><item><guid isPermaLink="false">tag:blogger.com,1999:blog-5601714198208780275.post-3714964356134476950</guid><pubDate>Tue, 30 Aug 2011 12:40:00 +0000</pubDate><atom:updated>2011-08-30T05:40:51.059-07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">ASP.NET</category><category domain="http://www.blogger.com/atom/ns#">Community</category><title>ASP.NET Skillscamp 2011–Der Tag danach</title><description>&lt;p&gt;Das war es also, das erste &lt;a href=&quot;http://skillscamp.de/&quot; target=&quot;_blank&quot;&gt;ASP.NET Skillscamp&lt;/a&gt; (&lt;a href=&quot;http://twitter.com/#!/skillscamp&quot; target=&quot;_blank&quot;&gt;@Skillscamp&lt;/a&gt;) 2011 in Köln und gleichzeitig das erste Community Event, an dem ich teilgenommen habe. Alles in allem kann ich, zumindest für mich, eine positive Bilanz ziehen: Ich durfte interessante Personen kennen lernen, deren Bilder und Artikel ich bisher nur kannte, und an vielen, zum Teil spannenden Gesprächen teilnehmen.&lt;/p&gt;&lt;p&gt;Hier folgt nun meine kurze, persönliche Zusammenfassung der Tage.&lt;/p&gt;&lt;h2&gt;Freitag - Das Vorspiel&lt;/h2&gt;&lt;p&gt;Der Freitag Abend begann um 19.00h in Peters Brauhaus in der Kölner Altstadt und &lt;a href=&quot;http://der-albert.com/&quot; target=&quot;_blank&quot;&gt;Albert Weinert&lt;/a&gt; (seines Zeichens der Organisator) nahm die Teilnehmer in Empfang. Nach und nach (je nach Verspätung der öffentlichen Verkehrsmittel) trudelten die Meisten bis auf wenige Ausnahmen auch ein. Mit zunehmenden Kennenlernen (wobei sich viele der üblichen Verdächtigen bereits kannten), ersten Gesprächen und auch den ersten Kölsch kamen die Themen für den Open Space Samstag zusammen. Es kristallisierte sich relativ schnell heraus, dass ein großer Schwerpunkt auf Javascript und den verschiedenen Frameworks, vor allem Knockout.js, Backbone.js und Node.js, liegen würde. Nicht Fehlen durften natürlich auch Themen wie ASP.NET MVC, HTML5 und REST mit WCF.&lt;/p&gt;&lt;p&gt;Mein persönliches (Negativ-)Highlight des abends hatte allerdings nicht primär mit der Veranstaltung zu tun, sondern dem Chaos und Anarchie ÖPNV. Der hat dafür gesorgt, dass ich nachts die Strecke vom Kölner Bahnhof nach Bonn-Beuel im Fabelrekord von unglaublichen &lt;strong&gt;2,75 Stunden &lt;/strong&gt;(in Worten: zwei Stunden und fünfundvierzig Minuten) zurückgelegt habe. Vielen Dank noch an dieser Stelle für die unglaubliche Unterstützung des VRS, ohne den diese Leistung nie möglich gewesen wäre!&lt;/p&gt;&lt;h2&gt;&lt;/h2&gt;&lt;h2&gt;Samstag - Der Open Space&lt;img style=&quot;display: inline; float: right&quot; align=&quot;right&quot; src=&quot;http://s3.amazonaws.com/twitpic/photos/large/382759849.jpg?AWSAccessKeyId=AKIAJF3XCCKACR3QDMOA&amp;amp;Expires=1314622985&amp;amp;Signature=aNo3WZ3QQ%2FncT%2FVCuZPRqCkxVrM%3D&quot; /&gt;&lt;/h2&gt;&lt;p&gt;Samstag morgen standen wir erst einmal mit versammelter Mannschaft vor verschlossener Tür, weil irgendein Spaßvogel die Tür zufallen lassen hat. Macht nix, wir standen schließlich fast alle draußen &lt;img style=&quot;border-bottom-style: none; border-right-style: none; border-top-style: none; border-left-style: none&quot; class=&quot;wlEmoticon wlEmoticon-winkingsmile&quot; alt=&quot;Zwinkerndes Smiley&quot; src=&quot;http://lh5.ggpht.com/-4UzHRkLNIkQ/TlzWSitK95I/AAAAAAAAANY/6lnYgK9bJis/wlEmoticon-winkingsmile%25255B2%25255D.png?imgmax=800&quot; /&gt;.&amp;#160; &lt;/p&gt;&lt;p&gt;Nach der Begrüßung und allgemeinen Vorrede zum Skillscamp durch Albert, wurde der Session Plan, vorerst nur für den Vormittag, zusammen gestellt. Aufgrund des allgemeinen Interesses und der relativ kleinen Zahl an Teilnehmern, gab es dann morgens auch nur eine erste Session zum Thema Javascript Frameworks - die auch gleich den größten der bereitstellten Räume der GFU sprengte. Diese erste Session war dann vor allem durch die Ausführungen von Albert geprägt.&lt;/p&gt;&lt;p&gt;Die zweite Session konnte auf zwei Slots aufgeteilt werden. Für die Einen gab es Node.js, für die Anderen Html5 (darüber kann ich leider nichts berichten). Der Versuch in der zweiten Session, unter der Schirmherrschaft von &lt;a href=&quot;http://lennybacon.com/default.aspx&quot; target=&quot;_blank&quot;&gt;Daniel Fisher&lt;/a&gt;, IISNode.js auf dem IIS zum Laufen zu bringen, scheiterte leider. Es war zwar relativ schnell eine lauffähige Version anhand des Blogs von &lt;a href=&quot;http://tomasz.janczuk.org/2011/08/hosting-nodejs-applications-in-iis-on.html&quot; target=&quot;_blank&quot;&gt;Tomek&lt;/a&gt; (der die letzten Tage ziemlich Kreise gelaufen hat) aufgesetzt, der Versuch eine eigene Seite anzuzeigen scheiterte jedoch. Und leider nicht nur das: Abgesehen davon, dass der Webserver einen 503er Fehler generierte, wurden zudem keinerlei brauchbare Loginformationen in die Logdatei oder das Eventlog geschrieben. Damit war relativ schnell (vorerst) der Stempel “noch nicht produktionstauglich” vergeben (Vielleicht war es aber auch nur die lang überfällige Zigarettenpause &lt;img style=&quot;border-bottom-style: none; border-right-style: none; border-top-style: none; border-left-style: none&quot; class=&quot;wlEmoticon wlEmoticon-winkingsmile&quot; alt=&quot;Zwinkerndes Smiley&quot; src=&quot;http://lh5.ggpht.com/-4UzHRkLNIkQ/TlzWSitK95I/AAAAAAAAANY/6lnYgK9bJis/wlEmoticon-winkingsmile%25255B2%25255D.png?imgmax=800&quot; /&gt; ! Mittlerweile ist ein Lösungsansatz von &lt;a href=&quot;http://twitter.com/#!/lennybacon&quot; target=&quot;_blank&quot;&gt;LennyBacon&lt;/a&gt; bei &lt;a href=&quot;http://www.hanselman.com/blog/InstallingAndRunningNodejsApplicationsWithinIISOnWindowsAreYouMad.aspx?utm_source=feedburner&amp;amp;utm_medium=feed&amp;amp;utm_campaign=Feed:+ScottHanselman+(Scott+Hanselman+-+ComputerZen.com)&quot; target=&quot;_blank&quot;&gt;Scott Hanselman&lt;/a&gt; gefunden worden)…     &lt;br /&gt;Weiter ging es zur Lokalisation mit ASP.NET MVC in Session 3, der letzten vor dem Mittagessen. Hier war es mal wieder Daniel Fisher, der, auf eine konkrete Frage zur Lokalisation von &lt;a href=&quot;http://blog.thomasbandt.de/39/de/blog.html&quot; target=&quot;_blank&quot;&gt;Thomas Bandt&lt;/a&gt; hin, alle Möglichkeiten der Lokalisierung vom Server bis zum Client vorstellte.&lt;/p&gt;&lt;p&gt;Nach dem Mittagessen, wurde die Planung des Nachmittags vorgenommen. Schon etwas auffällig war, dass Daniel Fisher einen sehr unruhigen Arm hat, wenn es um die Frage geht, wer mit einer bestimmten Technologie/einem bestimmten Framework bereits Erfahrung hat und darüber auch berichten möchte/kann. Dementsprechend wurde der Nachmittag wieder vor allem durch Albert und Daniel geprägt, insgesamt fand aber viel mehr Interaktion statt als noch am Vormittag. Grund war sicherlich auch, dass das erste Thema nach dem Mittag “Best-Practices in MVC” war und fast jeder in Form von Erfahrungen oder aber konkreter Fragen dazu beitragen konnte.&lt;/p&gt;&lt;p&gt;Auf den Themenkomplex REST und WCF wurde bewusst verzichtet. Der einzige, der zu diesem Thema aktiv mitgestalten konnte/wollte, war, wie konnte es auch mal wieder anders sein: Daniel Fisher… Und da er seine Meinung als nicht unbedingt massenkompatibel bezeichnete und Alexander Zeitler kurzfristig abgesagt hatte, wurde das Thema fallen lassen (kleiner Wink mit dem Zaunpfahl an dieser Stelle an Alexander Zeitler!).&lt;/p&gt;&lt;p&gt;Den Abschluss des Tages bildete schließlich ein Rundflug durch das Javascript-Tooling und sämtliche Javascript Frameworks, die von den Teilnehmern schon einmal eingesetzt wurden (für besondere Erheiterung sorgte: &lt;a href=&quot;http://www.zurb.com/playground/jquery-raptorize&quot; target=&quot;_blank&quot;&gt;raptorize your screen&lt;/a&gt;&amp;#160;&lt;img style=&quot;border-bottom-style: none; border-right-style: none; border-top-style: none; border-left-style: none&quot; class=&quot;wlEmoticon wlEmoticon-smile&quot; alt=&quot;Smiley&quot; src=&quot;http://lh5.ggpht.com/-itjUsMNK_WE/TlzWTuMWIUI/AAAAAAAAANc/6Lc4SmFiCBw/wlEmoticon-smile%25255B2%25255D.png?imgmax=800&quot; /&gt;) mit einer kleinen Vorstellung über Inhalt und Funktionsweise. Hier kam wirklich fast alles mal kurz auf den Tisch, ich könnte bestimmt nur noch die Hälfte nennen…&lt;/p&gt;&lt;h2&gt;Das Nachspiel&lt;/h2&gt;&lt;h2&gt;&lt;/h2&gt;&lt;p&gt;Den abendlichen Nachgesang konnte ich dann aus persönlichen Gründen nicht mehr aktiv miterleben (gut unterrichteten Quellen war aber zu entnehmen, dass es bis spät in die Nacht ging). Ich habe mir aber für das nächste Mal vorgenommen auch hier dabei zu sein.&lt;/p&gt;&lt;p&gt;Zum Schluss bleibt mir nur noch anzumerken, dass es mir persönlich sehr gefallen hat. Allein schon deshalb, dass man Gesicherten und Texten reale Personen zuordnen und diese kennen lernen konnte. Organisatorisch hätte mir persönlich eine Aufteilung in kleinere Gruppen besser gefallen, da das mit Sicherheit eine intensivere, tiefer gehende Diskussion in der einzelnen Session erlaubt hätte, als es letztlich in den/der großen Gruppe möglich gewesen ist. Und ansonsten ließe sich sicher auch die eine oder Andere kleine Optimierung finden. Entgegen des häufig geäußerten Wunsches von Albert, dass sich alle in die Runde einbringen, lief es doch zu Teil zu sehr auf ein reines konsumieren hinaus. Alles in allem war es aber aus meiner Sicht ein gelungenes &lt;strong&gt;erstes&lt;/strong&gt; (Wink an Albert!) Skillscamp und ich freue mich schon auf die Fortsetzung.&lt;/p&gt;&lt;p&gt;Sollte ich etwas vergessen haben, könnt ihr mich gerne anschreiben und ergänzen oder einfach selbst noch einmal etwas dazu schreiben.&lt;/p&gt;&lt;p&gt;Es bleibt mir nur noch einmal Albert Weinert herzlich für die Idee, Planung/Organisation und Durchführung zu Danken und ebenso allen Sponsoren, die das erste Skillscamp überhaupt möglich gemacht haben. Bis zum nächsten Mal!&lt;/p&gt;</description><link>http://jcselke.blogspot.com/2011/08/aspnet-skillscamp-2011der-tag-danach.html</link><author>noreply@blogger.com (Jan Christian Selke)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh5.ggpht.com/-4UzHRkLNIkQ/TlzWSitK95I/AAAAAAAAANY/6lnYgK9bJis/s72-c/wlEmoticon-winkingsmile%25255B2%25255D.png?imgmax=800" height="72" width="72"/><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-5601714198208780275.post-6480759005153966722</guid><pubDate>Tue, 19 Jul 2011 19:35:00 +0000</pubDate><atom:updated>2011-07-19T12:35:09.145-07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">ASP.NET</category><category domain="http://www.blogger.com/atom/ns#">Entwicklung</category><title>jQuery auf Koffein</title><description>&lt;p&gt;Der Name CoffeeScript geistert schon eine Weile umher. Viele haben bereits in Verbindung mit Node.js damit gearbeitet. Da ich in letzter Zeit weder selbige noch große Lust hatte mir ein Ubuntu oder eine andere Linux Distribution meines Vertrauens zu installieren, habe ich es einfach vorerst ignoriert… Jetzt habe ich vor kurzem &lt;a href=&quot;http://www.mindscapehq.com/products/web-workbench&quot; target=&quot;_blank&quot;&gt;Mindscapes Web Workbench&lt;/a&gt; entdeckt.&lt;/p&gt;&lt;p&gt;Die Web Workbench ist eine Visual Studio 2010 Erweiterung zur Integration von LESS, SASS und Coffee Script. Und gerade das letzte, ohne die Notwendigkeit Node.js installieren zu müssen. Jetzt doch etwas neugierig habe ich es von &lt;a href=&quot;http://visualstudiogallery.msdn.microsoft.com/2b96d16a-c986-4501-8f97-8008f9db141a&quot; target=&quot;_blank&quot;&gt;Microsoft&lt;/a&gt; heruntergeladen, installiert und losgelegt.&lt;/p&gt;&lt;p&gt;Zum ersten Herumspielen musste einfach eine ASP.NET MVC Anwendung herhalten. Die Anwendung blieb soweit unverändert und gleich erstmal eine CoffeeScript Datei hinzufügen. Wie man in der folgenden Abbildung sehen kann, werden nun drei neue Dateitypen angeboten: sass SCSS Style Sheet, Less Style Sheet und CoffeeScript File.&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;http://lh4.ggpht.com/-rKsyIKi2Wsk/TiXbfJJCd4I/AAAAAAAAAM8/P5yndjlAT54/s1600-h/CoffeeScript4.png&quot;&gt;&lt;img style=&quot;background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px&quot; title=&quot;CoffeeScript&quot; border=&quot;0&quot; alt=&quot;CoffeeScript&quot; src=&quot;http://lh3.ggpht.com/-_SZYtOOKcdQ/TiXbgZ3I5iI/AAAAAAAAANA/gM2VOKzc_Ic/CoffeeScript_thumb2.png?imgmax=800&quot; width=&quot;837&quot; height=&quot;470&quot; /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Also letzteres hinzugefügt und es erscheinen in dem Projekt zwei neue Dateien. Eine Datei mit der Endung &lt;strong&gt;.coffee&lt;/strong&gt; und eine mit der Endung &lt;strong&gt;.js&lt;/strong&gt;. Die .coffee Datei ist natürlich die Datei, die das Coffee Script enthalten wird. Die .js Datei enthält den automatisch aus dem Coffee Script erzeugten Javascript Code.&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;http://lh6.ggpht.com/-3zw4GiquYw8/TiXbg9T5ADI/AAAAAAAAANE/TFObKZ5kVWs/s1600-h/CoffeeScriptFiles%25255B4%25255D.png&quot;&gt;&lt;img style=&quot;background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px&quot; title=&quot;CoffeeScriptFiles&quot; border=&quot;0&quot; alt=&quot;CoffeeScriptFiles&quot; src=&quot;http://lh4.ggpht.com/-FY82o1anbjI/TiXbhd_BniI/AAAAAAAAANI/d-jLy0IV1Ck/CoffeeScriptFiles_thumb%25255B2%25255D.png?imgmax=800&quot; width=&quot;266&quot; height=&quot;381&quot; /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Als einfaches, kurzes Beispiel wollte ich einfach eine Slideshow mit jQuery erstellen und laufen lassen. Meine &lt;em&gt;Index.cshtml&lt;/em&gt; habe ich dazu um die für die Slideshow notwendigen Basis-Divs erweitert. Da ich erst einmal nur ein Gefühl dafür bekommen wollte, wurde ein div zu drei…&lt;/p&gt;&lt;div class=&quot;csharpcode&quot;&gt;&lt;pre class=&quot;alt&quot;&gt;&lt;span class=&quot;lnum&quot;&gt;   1:  &lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;html&quot;&gt;div&lt;/span&gt; &lt;span class=&quot;attr&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;=&amp;quot;slideShow&amp;quot;&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;&amp;gt;&lt;/span&gt; &lt;/pre&gt;&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;   2:  &lt;/span&gt;    &lt;span class=&quot;kwrd&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;html&quot;&gt;div&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;&amp;gt;&lt;/span&gt; &lt;/pre&gt;&lt;pre class=&quot;alt&quot;&gt;&lt;span class=&quot;lnum&quot;&gt;   3:  &lt;/span&gt;        &lt;span class=&quot;kwrd&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;html&quot;&gt;img&lt;/span&gt; &lt;span class=&quot;attr&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;=&amp;quot;@Url.Content(&amp;quot;&lt;/span&gt;~/&lt;span class=&quot;attr&quot;&gt;public&lt;/span&gt;/&lt;span class=&quot;attr&quot;&gt;images&lt;/span&gt;/&lt;span class=&quot;attr&quot;&gt;SlideShowPicture&lt;/span&gt;.&lt;span class=&quot;attr&quot;&gt;png&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;&amp;quot;)&amp;quot;&lt;/span&gt; &lt;span class=&quot;attr&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;=&amp;quot;200&amp;quot;&lt;/span&gt; &lt;/pre&gt;&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;   4:  &lt;/span&gt;            &lt;span class=&quot;attr&quot;&gt;height&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;=&amp;quot;200&amp;quot;&lt;/span&gt; &lt;span class=&quot;attr&quot;&gt;alt&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;=&amp;quot;Ein Park&amp;quot;&lt;/span&gt; &lt;span class=&quot;kwrd&quot;&gt;/&amp;gt;&lt;/span&gt; &lt;/pre&gt;&lt;pre class=&quot;alt&quot;&gt;&lt;span class=&quot;lnum&quot;&gt;   5:  &lt;/span&gt;        &lt;span class=&quot;kwrd&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;html&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;&amp;gt;&lt;/span&gt; &lt;/pre&gt;&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;   6:  &lt;/span&gt;            Hier ist ein schönes Sommerbild&lt;span class=&quot;kwrd&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;html&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;&amp;gt;&lt;/span&gt; &lt;/pre&gt;&lt;pre class=&quot;alt&quot;&gt;&lt;span class=&quot;lnum&quot;&gt;   7:  &lt;/span&gt;        &lt;span class=&quot;kwrd&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;html&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;&amp;gt;&lt;/span&gt; &lt;/pre&gt;&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;   8:  &lt;/span&gt;            Dieser Park war ein schöner Spielplatz für alle Kinder. &lt;/pre&gt;&lt;pre class=&quot;alt&quot;&gt;&lt;span class=&quot;lnum&quot;&gt;   9:  &lt;/span&gt;        &lt;span class=&quot;kwrd&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;html&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;&amp;gt;&lt;/span&gt; &lt;/pre&gt;&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;  10:  &lt;/span&gt;    &lt;span class=&quot;kwrd&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;html&quot;&gt;div&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;&amp;gt;&lt;/span&gt; &lt;/pre&gt;&lt;pre class=&quot;alt&quot;&gt;&lt;span class=&quot;lnum&quot;&gt;  11:  &lt;/span&gt;    &lt;span class=&quot;kwrd&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;html&quot;&gt;div&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;&amp;gt;&lt;/span&gt; &lt;/pre&gt;&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;  12:  &lt;/span&gt;        &lt;span class=&quot;kwrd&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;html&quot;&gt;img&lt;/span&gt; &lt;span class=&quot;attr&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;=&amp;quot;@Url.Content(&amp;quot;&lt;/span&gt;~/&lt;span class=&quot;attr&quot;&gt;public&lt;/span&gt;/&lt;span class=&quot;attr&quot;&gt;images&lt;/span&gt;/&lt;span class=&quot;attr&quot;&gt;SlideShowPicture&lt;/span&gt;.&lt;span class=&quot;attr&quot;&gt;png&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;&amp;quot;)&amp;quot;&lt;/span&gt; &lt;span class=&quot;attr&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;=&amp;quot;200&amp;quot;&lt;/span&gt; &lt;/pre&gt;&lt;pre class=&quot;alt&quot;&gt;&lt;span class=&quot;lnum&quot;&gt;  13:  &lt;/span&gt;            &lt;span class=&quot;attr&quot;&gt;height&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;=&amp;quot;200&amp;quot;&lt;/span&gt; &lt;span class=&quot;attr&quot;&gt;alt&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;=&amp;quot;Ein Park&amp;quot;&lt;/span&gt; &lt;span class=&quot;kwrd&quot;&gt;/&amp;gt;&lt;/span&gt; &lt;/pre&gt;&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;  14:  &lt;/span&gt;        &lt;span class=&quot;kwrd&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;html&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;&amp;gt;&lt;/span&gt; &lt;/pre&gt;&lt;pre class=&quot;alt&quot;&gt;&lt;span class=&quot;lnum&quot;&gt;  15:  &lt;/span&gt;            Hier ist ein schönes Sommerbild&lt;span class=&quot;kwrd&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;html&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;&amp;gt;&lt;/span&gt; &lt;/pre&gt;&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;  16:  &lt;/span&gt;        &lt;span class=&quot;kwrd&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;html&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;&amp;gt;&lt;/span&gt; &lt;/pre&gt;&lt;pre class=&quot;alt&quot;&gt;&lt;span class=&quot;lnum&quot;&gt;  17:  &lt;/span&gt;            Dieser Park war ein schöner Spielplatz für alle Kinder. &lt;/pre&gt;&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;  18:  &lt;/span&gt;        &lt;span class=&quot;kwrd&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;html&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;&amp;gt;&lt;/span&gt; &lt;/pre&gt;&lt;pre class=&quot;alt&quot;&gt;&lt;span class=&quot;lnum&quot;&gt;  19:  &lt;/span&gt;    &lt;span class=&quot;kwrd&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;html&quot;&gt;div&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;&amp;gt;&lt;/span&gt; &lt;/pre&gt;&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;  20:  &lt;/span&gt;    &lt;span class=&quot;kwrd&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;html&quot;&gt;div&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;&amp;gt;&lt;/span&gt; &lt;/pre&gt;&lt;pre class=&quot;alt&quot;&gt;&lt;span class=&quot;lnum&quot;&gt;  21:  &lt;/span&gt;        &lt;span class=&quot;kwrd&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;html&quot;&gt;img&lt;/span&gt; &lt;span class=&quot;attr&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;=&amp;quot;@Url.Content(&amp;quot;&lt;/span&gt;~/&lt;span class=&quot;attr&quot;&gt;public&lt;/span&gt;/&lt;span class=&quot;attr&quot;&gt;images&lt;/span&gt;/&lt;span class=&quot;attr&quot;&gt;SlideShowPicture&lt;/span&gt;.&lt;span class=&quot;attr&quot;&gt;png&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;&amp;quot;)&amp;quot;&lt;/span&gt; &lt;span class=&quot;attr&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;=&amp;quot;200&amp;quot;&lt;/span&gt; &lt;/pre&gt;&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;  22:  &lt;/span&gt;            &lt;span class=&quot;attr&quot;&gt;height&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;=&amp;quot;200&amp;quot;&lt;/span&gt; &lt;span class=&quot;attr&quot;&gt;alt&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;=&amp;quot;Ein Park&amp;quot;&lt;/span&gt; &lt;span class=&quot;kwrd&quot;&gt;/&amp;gt;&lt;/span&gt; &lt;/pre&gt;&lt;pre class=&quot;alt&quot;&gt;&lt;span class=&quot;lnum&quot;&gt;  23:  &lt;/span&gt;        &lt;span class=&quot;kwrd&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;html&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;&amp;gt;&lt;/span&gt; &lt;/pre&gt;&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;  24:  &lt;/span&gt;            Hier ist ein schönes Sommerbild&lt;span class=&quot;kwrd&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;html&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;&amp;gt;&lt;/span&gt; &lt;/pre&gt;&lt;pre class=&quot;alt&quot;&gt;&lt;span class=&quot;lnum&quot;&gt;  25:  &lt;/span&gt;        &lt;span class=&quot;kwrd&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;html&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;&amp;gt;&lt;/span&gt; &lt;/pre&gt;&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;  26:  &lt;/span&gt;            Dieser Park war ein schöner Spielplatz für alle Kinder. &lt;/pre&gt;&lt;pre class=&quot;alt&quot;&gt;&lt;span class=&quot;lnum&quot;&gt;  27:  &lt;/span&gt;        &lt;span class=&quot;kwrd&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;html&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;&amp;gt;&lt;/span&gt; &lt;/pre&gt;&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;  28:  &lt;/span&gt;    &lt;span class=&quot;kwrd&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;html&quot;&gt;div&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;&amp;gt;&lt;/span&gt; &lt;/pre&gt;&lt;pre class=&quot;alt&quot;&gt;&lt;span class=&quot;lnum&quot;&gt;  29:  &lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;html&quot;&gt;div&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;&amp;gt;&lt;/span&gt; &lt;/pre&gt;&lt;/div&gt;&lt;style type=&quot;text/css&quot;&gt;.csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, &quot;Courier New&quot;, courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt  { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;br /&gt;&lt;p&gt;Jetzt nur noch das entsprechende Coffee Script für einen einfachen Slideshow Aufruf schreiben. Dabei habe ich mich wirklich nicht überfordert und den folgenden Einzeiler geschrieben.&lt;/p&gt;&lt;div class=&quot;csharpcode&quot;&gt;&lt;pre class=&quot;alt&quot;&gt;&lt;span class=&quot;lnum&quot;&gt;   1:  &lt;/span&gt;$(&lt;span class=&quot;str&quot;&gt;&#39;#slideShow&#39;&lt;/span&gt;).cycle &lt;/pre&gt;&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;   2:  &lt;/span&gt;  fx:    &lt;span class=&quot;str&quot;&gt;&#39;scrollRight&#39;&lt;/span&gt;,&lt;/pre&gt;&lt;pre class=&quot;alt&quot;&gt;&lt;span class=&quot;lnum&quot;&gt;   3:  &lt;/span&gt;  delay: -2000 &lt;/pre&gt;&lt;/div&gt;&lt;style type=&quot;text/css&quot;&gt;.csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, &quot;Courier New&quot;, courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt  { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;br /&gt;&lt;p&gt;Meine Neugier trieb mich gleich in die Javascript Datei uns siehe da: es war bereits umgewandelt.&lt;/p&gt;&lt;div class=&quot;csharpcode&quot;&gt;&lt;pre class=&quot;alt&quot;&gt;&lt;span class=&quot;lnum&quot;&gt;   1:  &lt;/span&gt;(&lt;span class=&quot;kwrd&quot;&gt;function&lt;/span&gt;() {&lt;/pre&gt;&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;   2:  &lt;/span&gt;  $(&lt;span class=&quot;str&quot;&gt;&#39;#slideShow&#39;&lt;/span&gt;).cycle({&lt;/pre&gt;&lt;pre class=&quot;alt&quot;&gt;&lt;span class=&quot;lnum&quot;&gt;   3:  &lt;/span&gt;    fx: &lt;span class=&quot;str&quot;&gt;&#39;scrollRight&#39;&lt;/span&gt;,&lt;/pre&gt;&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;   4:  &lt;/span&gt;    delay: -2000&lt;/pre&gt;&lt;pre class=&quot;alt&quot;&gt;&lt;span class=&quot;lnum&quot;&gt;   5:  &lt;/span&gt;  });&lt;/pre&gt;&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;   6:  &lt;/span&gt;}).call(&lt;span class=&quot;kwrd&quot;&gt;this&lt;/span&gt;);&lt;/pre&gt;&lt;/div&gt;&lt;style type=&quot;text/css&quot;&gt;.csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, &quot;Courier New&quot;, courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt  { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;br /&gt;&lt;p&gt;Nun noch schnell die Javascript Datei in die Webseite eingebunden und schnell F5 gedrückt. Nach einem kurzen Augenblick zeigte sich dann die Standard Webseite – aber um eine von links nach rechts durchschiebende Slideshow reicher…&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;http://lh6.ggpht.com/-WuuYEoBVsoc/TiXbiAygQDI/AAAAAAAAANM/KkQDfZR2EPc/s1600-h/FertigeSlideShow4.png&quot;&gt;&lt;img style=&quot;background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px&quot; title=&quot;FertigeSlideShow&quot; border=&quot;0&quot; alt=&quot;FertigeSlideShow&quot; src=&quot;http://lh5.ggpht.com/-gq9yC9d5U4M/TiXbjDNr1ZI/AAAAAAAAANQ/H6ZJQihmlTo/FertigeSlideShow_thumb2.png?imgmax=800&quot; width=&quot;493&quot; height=&quot;390&quot; /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Was kann man zu so einem Beispiel schon groß sagen? Es funktioniert einwandfrei und erfüllt in diesem Einfachstbeispiel seinen Zweck. Inwiefern komplexere Anwendungen damit entwickelt werden können, wird sich noch zeigen.&lt;/p&gt;&lt;p&gt;Es ist aber definitiv eine interessante Alternative… und ich kann endlich mit Coffee Script arbeiten. Mit Kaffee arbeitet es sich einfach besser &lt;img style=&quot;border-bottom-style: none; border-right-style: none; border-top-style: none; border-left-style: none&quot; class=&quot;wlEmoticon wlEmoticon-winkingsmile&quot; alt=&quot;Zwinkerndes Smiley&quot; src=&quot;http://lh4.ggpht.com/-ChoSwTeMfE8/TiXbjX8db6I/AAAAAAAAANU/2xM-a-UrE6c/wlEmoticon-winkingsmile%25255B2%25255D.png?imgmax=800&quot; /&gt;.&lt;/p&gt;</description><link>http://jcselke.blogspot.com/2011/07/jquery-auf-koffein.html</link><author>noreply@blogger.com (Jan Christian Selke)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh3.ggpht.com/-_SZYtOOKcdQ/TiXbgZ3I5iI/AAAAAAAAANA/gM2VOKzc_Ic/s72-c/CoffeeScript_thumb2.png?imgmax=800" height="72" width="72"/><thr:total>2</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-5601714198208780275.post-1537891319297759795</guid><pubDate>Mon, 04 Jul 2011 10:46:00 +0000</pubDate><atom:updated>2011-07-04T03:46:54.164-07:00</atom:updated><title>Alles neu macht der Mai</title><description>&lt;p&gt;Es ist zwar nicht mehr Mai, aber die Schatten ziehen sich noch immer etwas.&lt;/p&gt;  &lt;p&gt;Nachdem ich Ende Mai meinen Arbeitgeber gewechselt habe, hat sich auch meine berufliche Fokussierung etwas gewandelt. Damit einhergehend wird sich in Zukunft mein Schwerpunkt immer weiter weg von VSTO und OpenXml Themen verschieben.&lt;/p&gt;  &lt;p&gt;Ich freue mich auch darauf, denn etwas von dem, was ich gelernt habe ist: Automatisierte Dokumentgenerierung mit einfachen, überschaubaren Dokumenten ist durchaus möglich – Aber komplexe Dokumentstrukturen auf Basis des Office OpenXml kann einen in den Wahnsinn treiben. Es ist schon schwer genug die Dokumentstruktur beherrschen zu wollen, aber die zum Teil sehr eigenen Verhaltensweisen von Word können für psychotische Schübe sorgen... Ich sage nur Fußnoten, Tabellen und/oder Abschnittswechsel (auch in Verbindung mit unsichtbarem Text).&lt;/p&gt;  &lt;p&gt;Ich bin auf jeden Fall gespannt, was die nähere Zukunft mit sich bringt…&lt;/p&gt;  </description><link>http://jcselke.blogspot.com/2011/07/alles-neu-macht-der-mai.html</link><author>noreply@blogger.com (Jan Christian Selke)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-5601714198208780275.post-8702323141447660472</guid><pubDate>Sat, 09 Apr 2011 11:00:00 +0000</pubDate><atom:updated>2011-04-09T04:00:24.769-07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Architektur</category><category domain="http://www.blogger.com/atom/ns#">Design Pattern</category><category domain="http://www.blogger.com/atom/ns#">Entwicklung</category><title>Alle Bälle in der Luft halten</title><description>&lt;p&gt;Die magischen Buchstaben, wenn es darum geht Anwendungen mit Benutzeroberflächen zu entwickeln, kennt wohl jeder: &lt;strong&gt;MVP.&lt;/strong&gt;&amp;#160; Und wer sie nicht kennt, sollte sich schnellstmöglich damit vertraut machen! Es gibt viele schöne Beispiele hierzu, eines ist sicherlich auch das von &lt;a href=&quot;http://blog.aztec-project.org/2010/02/16/beispiel-model-view-presenter-winforms/&quot; target=&quot;_blank&quot;&gt;Stefan Kölle&lt;/a&gt;. Woran es, meiner Meinung nach, aber wie die meisten Beispiele auch krankt, ist die Steuerung zwischen den einzelnen Views/Presenters.&lt;/p&gt;&lt;p&gt;Besonders deutlich wurde mir dieser Mangel, als ich vor Kurzem folgenden Quellcodeauszug sah:&lt;/p&gt;&lt;div style=&quot;padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px&quot; id=&quot;scid:f32c3428-b7e9-4f15-a8ea-c502c7ff2e88:14309f74-6204-4547-9c21-a36edd0b83c0&quot; class=&quot;wlWriterEditableSmartContent&quot;&gt;&lt;pre class=&quot;brush: c#;&quot;&gt;public class MyClass&lt;br /&gt;{&lt;br /&gt;   ...&lt;br /&gt;   public void ShowOtherForm()&lt;br /&gt;   {&lt;br /&gt;      using(MyPresenter presenter = new MyPresenter())&lt;br /&gt;      {&lt;br /&gt;         presenter.Initialize();&lt;br /&gt;      }&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public class MyPresenter()&lt;br /&gt;{&lt;br /&gt;   public void Initialize()&lt;br /&gt;   {&lt;br /&gt;      ...&lt;br /&gt;      this.View.Show();&lt;br /&gt;   }&lt;br /&gt;}&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;&lt;em&gt;Don’t do this at home, kids!&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;Den Presenter direkt im Code zu erzeugen bereitet mir schon ein Gefühl von Unbehagen, aber den View dann auch noch im Initialize anzuzeigen – das bereitet mir Magenschmerzen. Auf der Suche nach eleganteren Lösungen ist mir aufgefallen, dass viele Beispiele gerade in diesem Kontext Ihre Schwächen haben. Aber wie kann eine Lösung hierzu sehen? &lt;/p&gt;&lt;p&gt;Meine Antwort lautet: ApplicationController. Martin Fowler &lt;a href=&quot;http://martinfowler.com/eaaCatalog/applicationController.html&quot; target=&quot;_blank&quot;&gt;hats&lt;/a&gt; und Microsoft hat es &lt;a href=&quot;http://msdn.microsoft.com/en-us/library/ff648170.aspx&quot; target=&quot;_blank&quot;&gt;auch&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;Der ApplicationController enthält die Logik, welche View anzuzeigen ist, die vorher über die verschiedenen Presenter verteilt war. Zum Einen wird so die Logik zentralisiert zum Anderen werden damit aber auch etwaige Quellcode Dopplungen aufgehoben.&lt;/p&gt;&lt;p&gt;Wenn nun zwei Presenter die gleiche View anzeigen sollen, erhalten diese Presenter nur noch eine Abhängigkeit zum ApplicationController und rufen darauf eine gemeinsame Methode auf. So wird der anwendungsweite Ablauf nur noch über eine zentrale Komponente kontrolliert.&lt;/p&gt;&lt;p&gt;Ich habe eine Weile darüber nachgedacht, wie ich das Kind am besten beim Namen nennen kann. Dabei entstand u.a. die Idee ViewNavigator, aber letztlich trifft es der Name &lt;strong&gt;ViewConductor&lt;/strong&gt; am besten. Und so sieht mein erster Versuch eines ViewConductors aus.&lt;/p&gt;&lt;div style=&quot;padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px&quot; id=&quot;scid:f32c3428-b7e9-4f15-a8ea-c502c7ff2e88:b3489eb8-9ffb-44d9-9896-b02d9810f5ec&quot; class=&quot;wlWriterEditableSmartContent&quot;&gt;&lt;pre class=&quot;brush: c#;&quot;&gt;public class ViewConductor : IViewConductor&lt;br /&gt;{&lt;br /&gt;   private readonly IMainView _mainView;&lt;br /&gt;   private readonly IMainViewService _mainViewService;&lt;br /&gt;   private readonly IPresenterFactory _presenterFactory;&lt;br /&gt;&lt;br /&gt;   public ViewConductor(IMainView mainView, IMainViewService mainViewService, IPresenterFactory   presenterFactory)&lt;br /&gt;   {&lt;br /&gt;      _mainView = mainView;&lt;br /&gt;      _mainViewService = mainViewService;&lt;br /&gt;      _presenterFactory = presenterFactory;&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   public void OpenView&amp;lt;TPresenterType&amp;gt;() where TPresenterType : IPresenter&lt;br /&gt;   {&lt;br /&gt;      var presenter = this._presenterFactory.CreatePresenter&amp;lt;TPresenterType&amp;gt;();&lt;br /&gt;      presenter.Activate();&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   public void ShowPersonDetails()&lt;br /&gt;   {&lt;br /&gt;      this.OpenView&amp;lt;IPersonDetailPresenter&amp;gt;();&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public class PersonDetailPresenter : IPersonDetailPresenter&lt;br /&gt;{&lt;br /&gt;   private IPersonService _personService;&lt;br /&gt;&lt;br /&gt;   public PersonDetailPresenter(IPersonDetailView personDetailView, IPersonService personService)&lt;br /&gt;   {&lt;br /&gt;      this._personService = personService;&lt;br /&gt;      this.View = personDetailView;&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   public IPersonDetailView View { get; private set; }&lt;br /&gt;&lt;br /&gt;   public void Activate()&lt;br /&gt;   {&lt;br /&gt;      this.View.Presenter = this;&lt;br /&gt;      this.View.Show();&lt;br /&gt;   }&lt;br /&gt;}&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Ja, es ist die Anwendung eines MVP Patterns, aber müssen deshalb die Komponenten auch danach benannt werden? Ich nenne meinen Hund auch nicht Hund (oder Mr. Hund &lt;img style=&quot;border-bottom-style: none; border-right-style: none; border-top-style: none; border-left-style: none&quot; class=&quot;wlEmoticon wlEmoticon-winkingsmile&quot; alt=&quot;Zwinkerndes Smiley&quot; src=&quot;http://lh5.ggpht.com/_6MDRCGJmRdA/TZ9ppd3s8gI/AAAAAAAAALE/PFwGfIDpR1Q/wlEmoticon-winkingsmile%5B2%5D.png?imgmax=800&quot; /&gt;). Ist es vielleicht nicht sinnvoller die einzelnen Komponenten nach ihrer Verwendung zu benennen? Aus meiner Sicht unterstützt das zudem ein Presenter-First Vorgehen, weil der Ablauf dadurch offensichtlicher wird.&lt;/p&gt;&lt;p&gt;Hier werde ich mit meinem nächsten Beitrag wieder ansetzen.&lt;/p&gt;</description><link>http://jcselke.blogspot.com/2011/04/alle-balle-in-der-luft-halten.html</link><author>noreply@blogger.com (Jan Christian Selke)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh5.ggpht.com/_6MDRCGJmRdA/TZ9ppd3s8gI/AAAAAAAAALE/PFwGfIDpR1Q/s72-c/wlEmoticon-winkingsmile%5B2%5D.png?imgmax=800" height="72" width="72"/><thr:total>2</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-5601714198208780275.post-5390922756272264795</guid><pubDate>Thu, 07 Apr 2011 14:03:00 +0000</pubDate><atom:updated>2011-04-07T07:03:05.862-07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Design Pattern</category><category domain="http://www.blogger.com/atom/ns#">Entwicklung</category><title>Gedankengang zur IoC Container Registrierung</title><description>&lt;p&gt;Das folgenden Beispiel hat vermutlich (fast) jeder schon mal gesehen – so, oder so ähnlich zumindest, sieht eine landläufige Registrierung von Typen in einem IoC Container aus…&lt;/p&gt;&lt;div style=&quot;padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px&quot; id=&quot;scid:f32c3428-b7e9-4f15-a8ea-c502c7ff2e88:9d8046db-58dc-4de1-bff7-4f9151bce0dd&quot; class=&quot;wlWriterEditableSmartContent&quot;&gt;&lt;pre class=&quot;brush: c#;&quot;&gt;public TestRegistry()&lt;br /&gt;{&lt;br /&gt;   Scan(x =&amp;gt;&lt;br /&gt;   {&lt;br /&gt;      x.AssembliesFromApplicationBaseDirectory();&lt;br /&gt;      x.TheCallingAssembly();&lt;br /&gt;   });&lt;br /&gt;&lt;br /&gt;   ForSingletonOf&amp;lt;HttpContextBase&amp;gt;().Use(() =&amp;gt; new HttpContextWrapper(HttpContext.Current));&lt;br /&gt;   For&amp;lt;IMyView&amp;gt;().Use&amp;lt;MyDRYView&amp;gt;();&lt;br /&gt;   For&amp;lt;IService&amp;gt;().Use&amp;lt;SuperService&amp;gt;();&lt;br /&gt;   For&amp;lt;IRepository&amp;gt;().Use&amp;lt;WhatSoEverRepository&amp;gt;();&lt;br /&gt;}&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Es werden mehr oder viele Projekte angelegt, um eine saubere Trennung zwischen Schichten und Verantwortlichkeiten zu gewährleisten. Es dürfen alle Schichten nur über Kontrakte miteinander kommunizieren. Eine der typischen Abbildungen, die in diesem Zusammenhang häufig zu sehen ist, ist die schematische DIP Darstellung von &lt;a href=&quot;http://www.objectmentor.com/resources/articles/dip.pdf&quot; target=&quot;_blank&quot;&gt;Uncle Bob&lt;/a&gt;, die dem folgenden entspricht.&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;http://lh3.ggpht.com/_6MDRCGJmRdA/TZ3BGr3vtkI/AAAAAAAAAK0/ZqbmopzW9YI/s1600-h/ClassDiagram1%5B12%5D.png&quot;&gt;&lt;img style=&quot;background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px&quot; title=&quot;ClassDiagram1&quot; border=&quot;0&quot; alt=&quot;ClassDiagram1&quot; src=&quot;http://lh4.ggpht.com/_6MDRCGJmRdA/TZ3BHaop43I/AAAAAAAAAK4/AA-ahJjeQGA/ClassDiagram1_thumb%5B10%5D.png?imgmax=800&quot; width=&quot;567&quot; height=&quot;285&quot; /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Jede Schicht kommuniziert mit der unterliegenden über Kontrakte, die Abhängigkeiten werden wasserfallartig nach unten durchgereicht. Was passiert aber durch eine solche Registrierung? Die Isolation der einzelnen Schichten wird dahin gehend konterkariert, dass wir eine Über-Topschicht haben, die ALLE unterliegenden kennt.&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;http://lh6.ggpht.com/_6MDRCGJmRdA/TZ3BIHEYkvI/AAAAAAAAAK8/1s8iL-jivzM/s1600-h/ClassDiagram1%20-%20Copy%5B4%5D.png&quot;&gt;&lt;img style=&quot;background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px&quot; title=&quot;ClassDiagram1 - Copy&quot; border=&quot;0&quot; alt=&quot;ClassDiagram1 - Copy&quot; src=&quot;http://lh5.ggpht.com/_6MDRCGJmRdA/TZ3BI3osnDI/AAAAAAAAALA/wMlc9OetvKs/ClassDiagram1%20-%20Copy_thumb%5B2%5D.png?imgmax=800&quot; width=&quot;567&quot; height=&quot;285&quot; /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Die erste Frage, die sich mir stellt: Warum trenne ich dann überhaupt in verschiedene Projektdateien? Diese Trennung ist doch schließlich ohnehin nur eine logische, die durch die Aufteilung in verscheidene Projektdateien nur unterstützt werden soll. Interessant wird eine solche Trennung erst dann, wenn das Entwicklerteam groß genug ist, dass isoliert an verschiedenen Komponenten gearbeitet wird oder aber verteilt gearbeitet wird.&lt;/p&gt;&lt;p&gt;Ich aber habe diese Struktur nun schließlich gewählt, also warum dann nicht die Registrierung zumindest auf die Komponenten aufteilen. Jede Komponente registriert Typen der ihr untergeordneten Komponente. Es gilt ohnehin als best-practice die Registrierung inhaltlich auf verschiedene Teilregistrierungen aufzuteilen – warum dann nicht auch auf die Komponenten?&lt;/p&gt;&lt;p&gt;Die Mechanism-Schicht wird also sie Registrierung für die Utility-Schicht beinhalten, die Policy-Schicht enthält die Informationen über die Mechanism-Schicht. Aufgrund der auto-discovery Mechanismen der verschiedenen Container sollte dies damit keine großes Problem darstellen.&lt;/p&gt;&lt;p&gt;In Zukunft werden die Registrierungen dann anders aussehen - oder aber die Anzahl der Projekte einfach eingedampft.&lt;/p&gt;&lt;div style=&quot;padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px&quot; id=&quot;scid:f32c3428-b7e9-4f15-a8ea-c502c7ff2e88:6cf1b59f-846e-4af1-9641-d5c46ca20b7f&quot; class=&quot;wlWriterEditableSmartContent&quot;&gt;&lt;pre class=&quot;brush: c#;&quot;&gt;public WebRegistry()&lt;br /&gt;{&lt;br /&gt;   Scan(x =&amp;gt;&lt;br /&gt;   {&lt;br /&gt;      x.AssembliesFromApplicationBaseDirectory();&lt;br /&gt;      x.TheCallingAssembly();&lt;br /&gt;      x.LookForRegistries();&lt;br /&gt;   });&lt;br /&gt;&lt;br /&gt;   ForSingletonOf&amp;lt;HttpContextBase&amp;gt;().Use(() =&amp;gt; new HttpContextWrapper(HttpContext.Current));&lt;br /&gt;   For&amp;lt;IMyView&amp;gt;().Use&amp;lt;MyDRYView&amp;gt;();&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public ServiceRegistry()&lt;br /&gt;{&lt;br /&gt;   Scan(x =&amp;gt;&lt;br /&gt;   {&lt;br /&gt;      x.AssembliesFromApplicationBaseDirectory();&lt;br /&gt;      x.TheCallingAssembly();&lt;br /&gt;   });&lt;br /&gt;&lt;br /&gt;   For&amp;lt;IService&amp;gt;().Use&amp;lt;SuperService&amp;gt;();&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public DataRegistry()&lt;br /&gt;{&lt;br /&gt;   Scan(x =&amp;gt;&lt;br /&gt;   {&lt;br /&gt;      x.AssembliesFromApplicationBaseDirectory();&lt;br /&gt;      x.TheCallingAssembly();&lt;br /&gt;   });&lt;br /&gt;&lt;br /&gt;   For&amp;lt;IRepository&amp;gt;().Use&amp;lt;WhatSoEverRepository&amp;gt;();&lt;br /&gt;}&lt;/pre&gt;&lt;/div&gt;</description><link>http://jcselke.blogspot.com/2011/04/gedankengang-zur-ioc-container.html</link><author>noreply@blogger.com (Jan Christian Selke)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh4.ggpht.com/_6MDRCGJmRdA/TZ3BHaop43I/AAAAAAAAAK4/AA-ahJjeQGA/s72-c/ClassDiagram1_thumb%5B10%5D.png?imgmax=800" height="72" width="72"/><thr:total>2</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-5601714198208780275.post-628183699114210160</guid><pubDate>Sun, 03 Apr 2011 16:58:00 +0000</pubDate><atom:updated>2011-04-03T10:01:51.235-07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Architektur</category><category domain="http://www.blogger.com/atom/ns#">Entwicklung</category><category domain="http://www.blogger.com/atom/ns#">Sharepoint Server 2010</category><category domain="http://www.blogger.com/atom/ns#">VSTO</category><title>Javascript aus WebParts für Sharepoint und Web Projekte registrieren</title><description>&lt;p&gt;Javascript, wie etwa JQuery,&amp;#160; aus WebParts heraus zu rendern ist eine häufige Anforderung. Wie so etwas, beispielsweise mit Hilfe eines DelegateControls, gelöst werden kann, zeigt ein Artikel von &lt;a href=&quot;http://dotnet-forum.de/blogs/thorstenhans/archive/2010/06/29/sharepoint-2010-advanced-theming.aspx&quot; target=&quot;_blank&quot;&gt;Thorsten Hans&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;Nun stand ich aber vor der Anforderung den WebPart in Sharepoint sowie eine WebForms Seite einzubinden. Grundsätzlich ist dies auch mit dem DelegateControl zu realisieren. Mein Vorgehen ist aber etwas Quellcode-zentrischer und ich möchte alles Renderverhalten in einem WebPart aus dem Quellcode heraus steuern.&lt;/p&gt;&lt;p&gt;Für Sharepoint gibt es hierfür die Klasse &lt;em&gt;ScriptLink, &lt;/em&gt;in Web Projekten hingegen wird aber der &lt;em&gt;ScriptManager&lt;/em&gt; verwendet. Um dennoch beide bedienen zu können habe ich einen Kontrakt &lt;em&gt;IScriptRegistrar&lt;/em&gt; erstellt, der nur eine Methode &lt;em&gt;RegisterScript&lt;/em&gt; beinhaltet.&lt;/p&gt;&lt;div style=&quot;padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px&quot; id=&quot;scid:f32c3428-b7e9-4f15-a8ea-c502c7ff2e88:915d3f56-8b88-4e6d-bf45-f95b8d49bab8&quot; class=&quot;wlWriterEditableSmartContent&quot;&gt;&lt;pre class=&quot;brush: c#;&quot;&gt;public interface IScriptRegistrar&lt;br /&gt;{&lt;br /&gt;    void RegisterScript(IScriptRegistrationParameters registrationParameters);&lt;br /&gt;}&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Als Parameter wird eine Klasse erwartet, die die zur Registrierung des Skripts notwendigen Informationen beinhaltet. Der Kontrakt dazu sieht wie folgt aus.&lt;/p&gt;&lt;div style=&quot;padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px&quot; id=&quot;scid:f32c3428-b7e9-4f15-a8ea-c502c7ff2e88:716c4043-eb6c-436f-9067-4cc23bace16c&quot; class=&quot;wlWriterEditableSmartContent&quot;&gt;&lt;pre class=&quot;brush: c#;&quot;&gt;public interface IScriptRegistrationParameters&lt;br /&gt;{&lt;br /&gt;    Page Page { get; set; }&lt;br /&gt;    Type Type { get; set; }&lt;br /&gt;    string Key { get; set; }&lt;br /&gt;    string Url { get; set; }&lt;br /&gt;    bool Localizable { get; set; }&lt;br /&gt;}&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In dem Sharepoint Projekt wird nun die konkrete Implementierung &lt;em&gt;SharepointScriptRegistrar&lt;/em&gt; mit der Klasse &lt;em&gt;ScriptLink&lt;/em&gt; hinzugefügt.&lt;/p&gt;&lt;div style=&quot;padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px&quot; id=&quot;scid:f32c3428-b7e9-4f15-a8ea-c502c7ff2e88:94d062d2-ec14-48e0-89bf-a9cb7c5e8c89&quot; class=&quot;wlWriterEditableSmartContent&quot;&gt;&lt;pre class=&quot;brush: c#;&quot;&gt;public class SharepointScriptRegistrar : IScriptRegistrar&lt;br /&gt;{&lt;br /&gt;    public void RegisterScript(IScriptRegistrationParameters registrationParameters)&lt;br /&gt;    {&lt;br /&gt;        ScriptLink.Register(&lt;br /&gt;        registrationParameters.Page, &lt;br /&gt;        registrationParameters.Url, &lt;br /&gt;        registrationParameters.Localizable);&lt;br /&gt;    }&lt;br /&gt;}&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Das Webprojekt dagegen erhält eine weitere Klasse &lt;em&gt;WebScriptRegistrar&lt;/em&gt;, die das Skript mit Hilfe des &lt;em&gt;ScriptManagers&lt;/em&gt; registriert.&lt;/p&gt;&lt;div style=&quot;padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px&quot; id=&quot;scid:f32c3428-b7e9-4f15-a8ea-c502c7ff2e88:e474b51e-4638-43d4-880b-d6342b8ee033&quot; class=&quot;wlWriterEditableSmartContent&quot;&gt;&lt;pre class=&quot;brush: c#;&quot;&gt;public class WebScriptRegistrar : IScriptRegistrar&lt;br /&gt;{&lt;br /&gt;    public void RegisterScript(IScriptRegistrationParameters registrationParameters)&lt;br /&gt;    {&lt;br /&gt;        var scriptManager = registrationParameters.Page.ClientScript;&lt;br /&gt;        scriptManager.RegisterClientScriptInclude(&lt;br /&gt;        registrationParameters.Type,&lt;br /&gt;        registrationParameters.Key,&lt;br /&gt;        registrationParameters.Url);&lt;br /&gt;    }&lt;br /&gt;}&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Der Aufruf des jeweiligen &lt;em&gt;Registrars &lt;/em&gt;erfolgt kontextabhängig durch einen IoC Container. So halte ich das Wissen über die Implementierung aus dem WebPart raus und die Registrierung erfolgt nur in der Konfiguration des Containers. Als IoC Tool nutze ich in diesem Fall StructureMap.&lt;/p&gt;&lt;p&gt;So beschreibt der folgende Ein-Zeiler die Konfiguration innerhalb des Sharepoint Projekts.&lt;/p&gt;&lt;div style=&quot;padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px&quot; id=&quot;scid:f32c3428-b7e9-4f15-a8ea-c502c7ff2e88:81bf3378-0d6e-40d0-815b-30c2e8a42127&quot; class=&quot;wlWriterEditableSmartContent&quot;&gt;&lt;pre class=&quot;brush: c#;&quot;&gt;For&amp;lt;IScriptRegistrar&amp;gt;().Use&amp;lt;SharepointScriptRegistrar&amp;gt;();&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Die Registrierung für das Web Projekt sieht dem entsprechend angepaßt aus.&lt;/p&gt;&lt;div style=&quot;padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px&quot; id=&quot;scid:f32c3428-b7e9-4f15-a8ea-c502c7ff2e88:1f568280-301a-4bb9-bbfd-043993359886&quot; class=&quot;wlWriterEditableSmartContent&quot;&gt;&lt;pre class=&quot;brush: c#;&quot;&gt;For&amp;lt;IScriptRegistrar&amp;gt;().Use&amp;lt;WebScriptRegistrar&amp;gt;();&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Mit Hilfe eines ServiceLocators wird dann der registrierte IScriptRegistrar aus dem Container geholt und die Skriptregistrierung mit dem Aufruf &lt;em&gt;RegisterScript&lt;/em&gt; ausgeführt.&lt;/p&gt;&lt;div style=&quot;padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px&quot; id=&quot;scid:f32c3428-b7e9-4f15-a8ea-c502c7ff2e88:afa9daac-c0a6-4b9e-a970-affc3a461d61&quot; class=&quot;wlWriterEditableSmartContent&quot;&gt;&lt;pre class=&quot;brush: c#;&quot;&gt;var scriptRegistrar = ServiceLocator.Get&amp;lt;IScriptRegistrar&amp;gt;();&lt;br /&gt;IScriptRegistrationParameters scriptRegistrationParameters = new ScriptRegistrationParameters&lt;br /&gt;{&lt;br /&gt;    Page = this.Page,&lt;br /&gt;    Type = this.GetType(),&lt;br /&gt;    Key = &quot;javascript&quot;,&lt;br /&gt;    Url = &quot;necrtt/jsgantt.js&quot;,&lt;br /&gt;    Localizable = false&lt;br /&gt;};&lt;br /&gt;scriptRegistrar.RegisterScript(scriptRegistrationParameters);&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Falls es noch andere Ideen gibt, wie dieses Szenario auch umgesetzt werden könnte, bin ich immer daran interessiert…&lt;/p&gt;</description><link>http://jcselke.blogspot.com/2011/04/javascript-aus-webparts-fur-sharepoint.html</link><author>noreply@blogger.com (Jan Christian Selke)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-5601714198208780275.post-4927123028601609770</guid><pubDate>Wed, 30 Mar 2011 10:03:00 +0000</pubDate><atom:updated>2011-03-30T03:03:26.435-07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">offline</category><title>Einfach mal abschalten</title><description>&lt;p&gt;Es gibt etwas sehr wichtiges, dass vor einiger Zeit von mir viel zu sträflich vernachlässigt wurde: &lt;strong&gt;disconnecting&lt;/strong&gt;.&lt;/p&gt;  &lt;p&gt;Rob Conery und Scott Hanselman berichten über Ihre “ungewöhnliche” Erfahrung in &lt;a href=&quot;http://thisdeveloperslife.com/&quot; target=&quot;_blank&quot;&gt;This Developers Life&lt;/a&gt;. Jeder, der es noch nicht kennt und/oder von sich der Meinung ist, er arbeite (zu) viel, sollte es sich mal anhören. Ich für meinen Teil konnte mich in einigem davon wiederfinden…&lt;/p&gt;  &lt;p&gt;Meiner Meinung nach wertvolle, auf jeden Fall aber auch unterhaltsame 54 Minuten.&lt;/p&gt; &lt;object height=&quot;325&quot; width=&quot;325&quot;&gt;&lt;param name=&quot;allowScriptAccess&quot; value=&quot;always&quot; /&gt;&lt;param name=&quot;allowFullScreen&quot; value=&quot;true&quot; /&gt;&lt;param name=&quot;movie&quot; value=&quot;http://player.wizzard.tv/player/o/i/x/129982892076/config/k-27721e9f4e6ff19c/uuid/null/episode/k-28f28350a5c361b6&quot; /&gt;&lt;embed src=&quot;http://player.wizzard.tv/player/o/i/x/129982892076/config/k-27721e9f4e6ff19c/uuid/null/episode/k-28f28350a5c361b6&quot; name=&quot;movie&quot; menu=&quot;false&quot; type=&quot;application/x-shockwave-flash&quot; AllowScriptAccess=&quot;always&quot; AllowFullScreen=&quot;true&quot; width=&quot;325&quot; height=&quot;325&quot; /&gt;&lt;/object&gt;  </description><link>http://jcselke.blogspot.com/2011/03/einfach-mal-abschalten.html</link><author>noreply@blogger.com (Jan Christian Selke)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-5601714198208780275.post-4906625954259731881</guid><pubDate>Tue, 11 Jan 2011 15:57:00 +0000</pubDate><atom:updated>2011-01-11T07:57:00.306-08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Entwicklung</category><category domain="http://www.blogger.com/atom/ns#">Sharepoint Server 2010</category><category domain="http://www.blogger.com/atom/ns#">VSTO</category><title>Den Standard Editierdialog des Sharepoint Servers nutzen</title><description>Wer den Sharepoint Editierdialog anzupassen möchte hat Glück, denn dazu gibt es im Internet reichlich Quellen.&lt;br /&gt;Schon etwas anders sieht es allerdings aus, möchte man den 0815-Standarddialog zur Bearbeitung von Listitems benutzen; allerdings den Popup Dialog - nicht den seitenfüllenden. Denn dazu gibt es schon nicht mehr so viel Informationen. Der Fall ist vermutlich so banal, dass er schon wieder exotisch ist...&lt;br /&gt;Dennoch wollte ich vor Kurzem genau das!&lt;br /&gt;&lt;br /&gt;Nach einigem Suchen fand ich dann doch schließlich etwas: &lt;a href=&quot;http://jomit.blogspot.com/2009/12/dialog-platform-in-sharepoint-2010-how.html&quot;&gt;Jomit&#39;sBlog&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Hier wird beschrieben, was die neue Dialog Plattform ist und wie sie genutzt werden kann am - kurzer Trommelwirbel - Beispiel des Standard Editierdialogs.&lt;br /&gt;Wenn man doch immer so einfach glücklich gemacht werden könnte ;-)</description><link>http://jcselke.blogspot.com/2011/01/den-standard-editierdialog-des.html</link><author>noreply@blogger.com (Jan Christian Selke)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-5601714198208780275.post-1574097326018531851</guid><pubDate>Tue, 11 Jan 2011 13:07:00 +0000</pubDate><atom:updated>2011-01-11T05:07:50.355-08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Entwicklung</category><category domain="http://www.blogger.com/atom/ns#">Sharepoint Server 2010</category><category domain="http://www.blogger.com/atom/ns#">VSTO</category><title>JQuery im Sharepoint Server 2010 für Dummies²</title><description>&lt;p&gt;Um JQuery in den Sharepoint Server 2010 einzubinden, gibt es verschiedene Möglichkeiten. Beschrieben wurden diese Möglichkeiten etwa von &lt;a href=&quot;http://weblogs.asp.net/jan/archive/2010/03/01/scriptsrc-referencing-javascript-files-with-sharepoint-2010-custom-actions.aspx&quot; target=&quot;_blank&quot;&gt;Jan Tielens&lt;/a&gt;, &lt;a href=&quot;http://blog.voyta.net/2010/09/12/referencing-javascript-files-using-customaction-in-sharepoint-2010-sandboxed-solutions/&quot; target=&quot;_blank&quot;&gt;Voyta&lt;/a&gt; aber auch Anderen.&lt;/p&gt;&lt;p&gt;Als Anfänger in diesem Thema habe ich mich also Schritt für Schritt an deren Anleitung langgehangelt. Aber letztlich wollte nach dem Deployment in den Sharepoint einfach keine &lt;em&gt;jquery-1.4.1.js&lt;/em&gt; Datei in dem Ordner JQuery innerhalb des Layouts Verzeichnis des Sharepoint Servers erscheinen.&lt;/p&gt;&lt;p&gt;Nach einigen Versuchen und etwas Internetrecherche stellte ich fest, dass nur eine Kleinigkeit fehlte damit die JQuery Datei, und damit auch jede andere Javascript Datei, in das &lt;em&gt;/_layouts&lt;/em&gt; Verzeichnis verteilt wird. Die Lösung ist ebenso so schlagend wie einfach:&lt;/p&gt;&lt;p&gt;Einen zugeordneten Sharepoint-Ordner “Layouts” im Visual Studio hinzufügen.&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;http://lh6.ggpht.com/_6MDRCGJmRdA/TSxB75rSSVI/AAAAAAAAAKg/6ksVjGyu-DE/s1600-h/AddFolder%5B12%5D.png&quot;&gt;&lt;img style=&quot;background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px&quot; title=&quot;AddFolder&quot; border=&quot;0&quot; alt=&quot;AddFolder&quot; src=&quot;http://lh6.ggpht.com/_6MDRCGJmRdA/TSxB8yfyHnI/AAAAAAAAAKk/VXV4RqKP-Sg/AddFolder_thumb%5B10%5D.png?imgmax=800&quot; width=&quot;823&quot; height=&quot;186&quot; /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;In diesen Ordner wird die JQuery Datei aus dem Modulordner verschoben und die elements.xml entsprechend angepasst.&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;http://lh4.ggpht.com/_6MDRCGJmRdA/TSxB9im5NbI/AAAAAAAAAKo/Dr4UvGflXKw/s1600-h/LayoutsFolder%5B10%5D.png&quot;&gt;&lt;img style=&quot;background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px&quot; title=&quot;LayoutsFolder&quot; border=&quot;0&quot; alt=&quot;LayoutsFolder&quot; src=&quot;http://lh3.ggpht.com/_6MDRCGJmRdA/TSxB9-pXXCI/AAAAAAAAAKs/FRbu7ImQLes/LayoutsFolder_thumb%5B6%5D.png?imgmax=800&quot; width=&quot;296&quot; height=&quot;100&quot; /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Die CustomAction bleibt unverändert und jetzt wird nach dem Deployment auch der Ordner /&lt;em&gt;JQuery &lt;/em&gt;unterhalb des Ordners &lt;em&gt;/Layouts&lt;/em&gt; angelegt und die Datei &lt;em&gt;jquery-1.4.1.js&lt;/em&gt; dort abgelegt. Warum nicht gleich so?! ;-)&lt;/p&gt;</description><link>http://jcselke.blogspot.com/2011/01/jquery-im-sharepoint-server-2010-fur.html</link><author>noreply@blogger.com (Jan Christian Selke)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh6.ggpht.com/_6MDRCGJmRdA/TSxB8yfyHnI/AAAAAAAAAKk/VXV4RqKP-Sg/s72-c/AddFolder_thumb%5B10%5D.png?imgmax=800" height="72" width="72"/><thr:total>2</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-5601714198208780275.post-3526687864389834324</guid><pubDate>Mon, 20 Dec 2010 09:23:00 +0000</pubDate><atom:updated>2010-12-20T01:23:43.201-08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Architektur</category><category domain="http://www.blogger.com/atom/ns#">CAB</category><category domain="http://www.blogger.com/atom/ns#">Entwicklung</category><category domain="http://www.blogger.com/atom/ns#">StructureMap</category><title>(m)Ein EA Versuch</title><description>&lt;p&gt;Im Zuge meiner ersten Gehversuche mit dem MVVM Light Framework von Laurant Bugnion, habe ich festgestellt, dass ich mit dem EventAggregator (EA) nicht ganz warm werde. Das hat sich zwar mittlerweile etwas relativiert (Hast Recht, &lt;a href=&quot;http://blog.codemurai.de/&quot;&gt;André&lt;/a&gt; ;-)), jetzt bin ich vor Kurzem auf eine neue Implementierung eines EA von &lt;a href=&quot;http://codepaste.net/f5zs2o&quot;&gt;Glenn Block&lt;/a&gt; gestoßen. Diese Implementierung basiert auf dem in &lt;a href=&quot;http://storyteller.github.com/&quot;&gt;StoryTeller&lt;/a&gt; genutzten EA von Jeremy D Miller.&lt;/p&gt;&lt;p&gt;Alles in allem fand ich diese Version schon sehr spannend: Der EA nutzt &lt;em&gt;WeakRefences&lt;/em&gt;, extrahiert selbst aus einem registrierten Objekt die notwendigen Events und entfernt sie auch so wieder…&lt;/p&gt;&lt;p&gt;Letztlich habe ich (in meinen Augen) ein bisschen &lt;em&gt;cherry picking&lt;/em&gt; betrieben. Aus den verschiedenen Varianten habe ich versucht, mir einen eigenen “maßgeschneiderten” EA zu erstellen.&lt;/p&gt;&lt;p&gt;Im folgenden das vorläufige Ergebnis:&lt;/p&gt;&lt;div style=&quot;padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px&quot; id=&quot;scid:f32c3428-b7e9-4f15-a8ea-c502c7ff2e88:658ca250-fc99-4963-b0d4-0f235a3fabbf&quot; class=&quot;wlWriterEditableSmartContent&quot;&gt;&lt;pre class=&quot;brush: c#;&quot;&gt;public class EventAggregator : IEventAggregator&lt;br /&gt;{&lt;br /&gt;   private readonly Dictionary&amp;lt;Type, List&amp;lt;WeakReference&amp;gt;&amp;gt; _eventSubscriberLists = new Dictionary&amp;lt;Type, List&amp;lt;WeakReference&amp;gt;&amp;gt;();&lt;br /&gt;   private readonly SynchronizationContext _context;&lt;br /&gt;   private object _lock = new object();&lt;br /&gt;&lt;br /&gt;   public EventAggregator(SynchronizationContext context)&lt;br /&gt;   {&lt;br /&gt;      _context = context;&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   public void Subscribe(object subscriber)&lt;br /&gt;   {&lt;br /&gt;      Lock(() =&amp;gt;&lt;br /&gt;      {&lt;br /&gt;         var subscriptionTypes = subscriber.DissectSubscriptionTypes();&lt;br /&gt;         subscriptionTypes.Select(SubscribersFor).Each(referenceList =&amp;gt;referenceList.Add(new WeakReference(subscriber)));&lt;br /&gt;      });&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   public void RemoveSubscription(object subscriber)&lt;br /&gt;   {&lt;br /&gt;      Lock(() =&amp;gt;&lt;br /&gt;      {&lt;br /&gt;         var subscriberTypes = subscriber.DissectSubscriptionTypes();&lt;br /&gt;         subscriberTypes.Select(SubscribersFor).Each(referenceList =&amp;gt; referenceList&lt;br /&gt;            .ForEach(weakReference =&amp;gt;&lt;br /&gt;            {&lt;br /&gt;               if (weakReference.Target == subscriber)&lt;br /&gt;               referenceList.Remove(weakReference);&lt;br /&gt;            }));&lt;br /&gt;      });&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   public void Publish&amp;lt;T&amp;gt;() where T : class, new()&lt;br /&gt;   {&lt;br /&gt;      Publish(new T());&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   public void Publish&amp;lt;T&amp;gt;(T eventToPublish) where T : class&lt;br /&gt;   {&lt;br /&gt;      var subscribersToRemove = new List&amp;lt;WeakReference&amp;gt;();&lt;br /&gt;      SubscribersFor(eventToPublish.ToClosedSubscriber&amp;lt;T&amp;gt;()).ForEach(weakSubscriber =&amp;gt;&lt;br /&gt;      {&lt;br /&gt;         if (!weakSubscriber.IsAlive)&lt;br /&gt;         {&lt;br /&gt;            subscribersToRemove.Add(weakSubscriber);&lt;br /&gt;         }&lt;br /&gt;         else&lt;br /&gt;         {&lt;br /&gt;            PublishingAction(() =&amp;gt; weakSubscriber.AsSubscriber&amp;lt;T&amp;gt;().Handle(eventToPublish));&lt;br /&gt;         }&lt;br /&gt;      });&lt;br /&gt;&lt;br /&gt;      if (subscribersToRemove.Any())&lt;br /&gt;      {&lt;br /&gt;         Lock(() =&amp;gt; subscribersToRemove.ForEach(removableReference =&amp;gt; &lt;br /&gt;SubscribersFor(referenceList.Target.ToClosedSubscriber&amp;lt;T&amp;gt;()).Remove(removableReference)));&lt;br /&gt;      }&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   private void PublishingAction(Action action)&lt;br /&gt;   {&lt;br /&gt;      _context.Post(s =&amp;gt; action(), null);&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   private List&amp;lt;WeakReference&amp;gt; SubscribersFor(Type subscriberType)&lt;br /&gt;   {&lt;br /&gt;      List&amp;lt;WeakReference&amp;gt; subscribers = null;&lt;br /&gt;      Lock(() =&amp;gt;&lt;br /&gt;      {&lt;br /&gt;         var found = _eventSubscriberLists.TryGetValue(subscriberType, out subscribers);&lt;br /&gt;         if (!found)&lt;br /&gt;         {&lt;br /&gt;            subscribers = new List&amp;lt;WeakReference&amp;gt;();&lt;br /&gt;            _eventSubscriberLists.Add(subscriberType, subscribers);&lt;br /&gt;         }&lt;br /&gt;      });&lt;br /&gt;&lt;br /&gt;      return subscribers;&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   private void Lock(Action action)&lt;br /&gt;   {&lt;br /&gt;      lock (_lock)&lt;br /&gt;      {&lt;br /&gt;         action();&lt;br /&gt;      }&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;p&gt;Mir gefiel der Registrierungsansatz mit einem TypeInterceptor besonders sehr gut. Da ich ohnehin meist mit einem IoC Container arbeite, ist eine solche Verwendung naheliegend.&lt;/p&gt;&lt;p&gt;Also findet die Registrierung der Objekte nicht durch das Anmelden von sich selbst statt, wie in den Beispielen von MVVM Light oder dem EA Beispiel von Glenn Block, sondern mittels eines &lt;em&gt;TypeInterceptors&lt;/em&gt;.&lt;/p&gt;&lt;div style=&quot;padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px&quot; id=&quot;scid:f32c3428-b7e9-4f15-a8ea-c502c7ff2e88:32b740b5-a308-4719-a05f-a962ae5f9fb0&quot; class=&quot;wlWriterEditableSmartContent&quot;&gt;&lt;pre class=&quot;brush: c#;&quot;&gt;public class SubscriptionInterceptor : StructureMap.Interceptors.TypeInterceptor&lt;br /&gt;{&lt;br /&gt;   public object Process(object target, IContext context)&lt;br /&gt;   {&lt;br /&gt;      context.GetInstance&amp;lt;IEventAggregator&amp;gt;().Subscribe((target));            &lt;br /&gt;      return target;&lt;br /&gt;   }        &lt;br /&gt;&lt;br /&gt;   public bool MatchesType(Type type)&lt;br /&gt;   {&lt;br /&gt;      return type.ImplementsInterfaceTemplate(typeof(ISubscribe&amp;lt;&amp;gt;));&lt;br /&gt;   }       &lt;br /&gt;}&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Mal sehen, wie es weiter geht…&lt;/p&gt;</description><link>http://jcselke.blogspot.com/2010/12/mein-ea-versuch.html</link><author>noreply@blogger.com (Jan Christian Selke)</author><thr:total>1</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-5601714198208780275.post-3404925015097829107</guid><pubDate>Fri, 17 Dec 2010 20:08:00 +0000</pubDate><atom:updated>2010-12-17T12:08:51.866-08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Entwicklung</category><category domain="http://www.blogger.com/atom/ns#">OpenXml</category><category domain="http://www.blogger.com/atom/ns#">VSTO</category><category domain="http://www.blogger.com/atom/ns#">Word 2007</category><title>Eine ContentControl Id ist eine Id ist nicht immer die gleiche Id</title><description>Heute wäre ich fast wieder auf eine kleine, alte Nicklichkeit von Word und dem OpenXml hereingefallen…&lt;br /&gt;Innerhalb von Word habe ich ein Inhaltssteuerelement angelegt und dessen interne Id ermittelt. Diese wird von der Word API als &lt;em&gt;String &lt;/em&gt;bereitgehalten. Die MSDN Auskunft dazu ist eindeutig:&lt;br /&gt;&lt;blockquote&gt;&lt;span style=&quot;font-family: Arial;&quot;&gt;&lt;strong&gt;Returns a String that represents the identification for a content control. Read-only.&lt;/strong&gt;&lt;/span&gt;&lt;/blockquote&gt;Diese Id wird nun intern von uns als Zahl weiterverarbeitet. – Soweit kein Problem. Aus&lt;br /&gt;&lt;div class=&quot;wlWriterEditableSmartContent&quot; id=&quot;scid:f32c3428-b7e9-4f15-a8ea-c502c7ff2e88:207d344f-25bd-4ea5-ad4a-7957a9922c62&quot; style=&quot;display: inline; float: none; margin: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;&quot;&gt;&lt;br /&gt;&lt;pre class=&quot;brush: c#;&quot;&gt;long id = long.Parse(contentControl.Id);&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;erhalte ich die Id &lt;strong&gt;2857609749&lt;/strong&gt;.&lt;br /&gt;&lt;br /&gt;Jetzt musste ich aber anhand dieser Id das Inhaltssteuerelement in der &lt;em&gt;document.xml&lt;/em&gt; ermitteln. Zu meiner ersten großen Überraschung war aber keines mit dieser Id zu finden?! Nach etwas Suchen stellte sich heraus, dass das Inhaltssteuerelement anscheinend unter der Id &lt;strong&gt;–1437357547&lt;/strong&gt; in dem Dokument abgelegt war.&lt;br /&gt;&lt;br /&gt;Innerhalb der Word API wird anscheinend die Darstellung als unsigned Wert, also ohne negative Vorzeichen bevorzugt, während innerhalb der Dokumentstruktur auch negative Vorzeichen verwendet werden.&lt;br /&gt;&lt;br /&gt;Es bleibe also nichts andere übrig, als zwischen den verschiedenen Darstellungen zu konvertieren.&lt;br /&gt;&lt;br /&gt;In meinem Fall lag der String-Wert ohnehin schon als &lt;strong&gt;long&lt;/strong&gt; vor. Daher konnte ich folgenden Aufruf nutzen, um den Word API Wert, in den zu der &lt;em&gt;document.xml &lt;/em&gt;zu konvertieren:&lt;br /&gt;&lt;br /&gt;&lt;div class=&quot;wlWriterEditableSmartContent&quot; id=&quot;scid:f32c3428-b7e9-4f15-a8ea-c502c7ff2e88:b53d5c68-b634-4ea1-aa16-6985528416af&quot; style=&quot;display: inline; float: none; margin: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;&quot;&gt;&lt;pre class=&quot;brush: c#;&quot;&gt;long ccid = Convert.ToInt64((int)id);&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Der umgekehrte Weg, von der Darstellung aus der &lt;em&gt;document.xml&lt;/em&gt; in den von Word bevorzugten Wert erfolgt dann folgendermaßen:&lt;br /&gt;&lt;br /&gt;&lt;div class=&quot;wlWriterEditableSmartContent&quot; id=&quot;scid:f32c3428-b7e9-4f15-a8ea-c502c7ff2e88:03f4c8e9-6c2b-48b8-a6ed-d64fe79d78ba&quot; style=&quot;display: inline; float: none; margin: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;&quot;&gt;&lt;pre class=&quot;brush: c#;&quot;&gt;long ccid = Convert.ToInt64((uint)id);&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Oder mit noch etwas mehr Konvertierungsaufwand lassen sich die Werte direkt aus dem String-Wert konvertieren:&lt;br /&gt;&lt;br /&gt;&lt;div class=&quot;wlWriterEditableSmartContent&quot; id=&quot;scid:f32c3428-b7e9-4f15-a8ea-c502c7ff2e88:dad79c36-769c-4397-a053-109e1483bd61&quot; style=&quot;display: inline; float: none; margin: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;&quot;&gt;&lt;pre class=&quot;brush: c#;&quot;&gt;long ccid = Convert.ToInt64((uint)long.Parse(contentControl.Id));&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;… Das bietet sicherlich auch noch Optimierungspotential…</description><link>http://jcselke.blogspot.com/2010/12/eine-contentcontrol-id-ist-eine-id-ist.html</link><author>noreply@blogger.com (Jan Christian Selke)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-5601714198208780275.post-3743466146417614185</guid><pubDate>Wed, 15 Dec 2010 15:02:00 +0000</pubDate><atom:updated>2010-12-15T07:02:44.892-08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Architektur</category><category domain="http://www.blogger.com/atom/ns#">Entwicklung</category><category domain="http://www.blogger.com/atom/ns#">MEF</category><title>Commands als MEF Plugins einbinden</title><description>Bei der Nachlese zu meinem letzten Refactoring kam mir eine Idee: Wie wäre es denn das Ganze noch etwas generischer zu gestalten, um den Quellcode gar nicht mehr anfassen zu müssen?! Ich habe dabei daran gedacht, &lt;a href=&quot;http://mef.codeplex.com/&quot;&gt;MEF&lt;/a&gt; einzusetzen und die Prozesslogik als Plugin einzubinden.&lt;br /&gt;Gut, in der momentanen Form ist es eine Milchmädchenrechnung, da die Flags, anhand derer entschieden wird, sich zur Zeit auch noch im Zielprojekt befinden. Aber dass soll erst einmal nicht beachtet werden – das ist vielleicht eine spätere Baustelle.&lt;br /&gt;Zuerst einmal muss das MEF von Codeplex herunter geladen werden und die Assembly &lt;em&gt;System.ComponentModel.Composition.Codeplex.dll&lt;/em&gt; in das Projekt eingebunden werden.&lt;br /&gt;Das Bereitstellen der Prozessor Klassen erfolgt über das Export Attribut. Als Export wird die Schnittstelle &lt;span style=&quot;color: blue; font-family: Consolas;&quot;&gt;IItemProcessor&lt;/span&gt; genutzt, da auf diese Weise nur eine Referenz auf die Schnittstelle beinhaltende Assembly benötigt wird.&lt;br /&gt;&lt;br /&gt;&lt;div class=&quot;wlWriterEditableSmartContent&quot; id=&quot;scid:f32c3428-b7e9-4f15-a8ea-c502c7ff2e88:6ba59f86-e7ae-4c3b-abbc-aad4c5e68495&quot; style=&quot;display: inline; float: none; margin: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;&quot;&gt;&lt;pre class=&quot;brush: c#;&quot;&gt;[Export(typeof(IItemProcessor))]&lt;br /&gt;public class SimpleItemProcessor : IItemProcessor&lt;br /&gt;{&lt;br /&gt;    public void Process(WorkItem item)&lt;br /&gt;    {&lt;br /&gt;        throw new NotImplementedException();&lt;br /&gt;    }&lt;br /&gt;}&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Der Import der Typen erfolgt über das &lt;em&gt;Import&lt;/em&gt; Attribut. Da hier in eine Liste importiert wird, genauer genommen das &lt;em&gt;ImportMany&lt;/em&gt; Attribut.&lt;br /&gt;&lt;br /&gt;&lt;div class=&quot;wlWriterEditableSmartContent&quot; id=&quot;scid:f32c3428-b7e9-4f15-a8ea-c502c7ff2e88:cc8faebd-90ad-4426-a934-a7ed8aec548a&quot; style=&quot;display: inline; float: none; margin: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;&quot;&gt;&lt;pre class=&quot;brush: c#;&quot;&gt;public class WorkItem&lt;br /&gt;{&lt;br /&gt;    public WorkItem()&lt;br /&gt;    {&lt;br /&gt;        this.Processors = new List&amp;lt;IItemProcessor&amp;gt;();&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    [ImportMany(typeof(IItemProcessor))]&lt;br /&gt;    public IList&amp;lt;IItemProcessor&amp;gt; Processors { get; set; }&lt;br /&gt;    ...&lt;br /&gt;    public void Process()&lt;br /&gt;    {&lt;br /&gt;        this.processorList.Where(x =&amp;gt; x.CanProcess(this)).Each(proc =&amp;gt; proc.Process(this));&lt;br /&gt;    }&lt;br /&gt;}&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Jetzt sind Quelle und Ziel vorbereitet, es fehlt nur noch die Konfiguration im Programmstart zum Auffinden der Plugins. Dazu werden die sogenannten &lt;em&gt;Catalogs&lt;/em&gt; genutzt. Exporte können sich selbst in einem solchen Katalog registrieren. Dafür stehen verschiedene Typen von Catalogs zur Verfügung. Da in diesem Fall eine Assembly gesucht wird, die im selben Verzeichnis liegt, wie die auszuführende Assembly, nutze ich den &lt;span style=&quot;color: blue; font-family: Consolas;&quot;&gt;DirectoryCatalog&lt;/span&gt;. &lt;br /&gt;&lt;br /&gt;&lt;div class=&quot;wlWriterEditableSmartContent&quot; id=&quot;scid:f32c3428-b7e9-4f15-a8ea-c502c7ff2e88:e324d012-c736-4476-bd59-f2a5c27541a6&quot; style=&quot;display: inline; float: none; margin: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;&quot;&gt;&lt;pre class=&quot;brush: c#;&quot;&gt;var catalog = new DirectoryCatalog(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location));&lt;br /&gt;    var container = new CompositionContainer(catalog);&lt;br /&gt;    var batch = new CompositionBatch();&lt;br /&gt;    batch.AddPart(this);&lt;br /&gt;    container.Compose(batch);&lt;/pre&gt;&lt;/div&gt;&lt;pre&gt;&lt;/pre&gt;&lt;br /&gt;Der Aufruf der &lt;em&gt;Compose &lt;/em&gt;Methode startet das Auffinden der Plugins in allen Assemblies des hinterlegten Verzeichnisses. Eine sehr einfache Möglichkeit solche Plugins zu nutzen…</description><link>http://jcselke.blogspot.com/2010/12/commands-als-mef-plugins-einbinden.html</link><author>noreply@blogger.com (Jan Christian Selke)</author><thr:total>1</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-5601714198208780275.post-7384317220225340187</guid><pubDate>Tue, 14 Dec 2010 22:56:00 +0000</pubDate><atom:updated>2010-12-14T14:56:14.261-08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Architektur</category><category domain="http://www.blogger.com/atom/ns#">Design Pattern</category><category domain="http://www.blogger.com/atom/ns#">Entwicklung</category><title>Refactoring: Switch durch Commands ersetzen</title><description>&lt;span style=&quot;font-family: Courier New;&quot;&gt;&lt;/span&gt;&lt;br /&gt;Vor Kurzem war es notwendig, bestehenden Quellcode zu erweitern. Eine der entscheidenden Änderungen bestand darin, Prozessablauflogik durch eine neue Variante zu erweitern. Dabei bestand die Möglichkeit eines meiner bevorzugten Refactorings durchzuführen: &lt;a href=&quot;http://www.industriallogic.com/xp/refactoring/conditionDispatcherWithCommand.html&quot;&gt;Das Ersetzen von Conditional Dispatch durch Commands&lt;/a&gt;.&lt;br /&gt;Bei meinen Arbeiten bin ich auf ein Konstrukt gestoßen, das ich als nicht besonders hübsch und elegant erachte; Viel entscheidender aber, es fördert weder die Wartbarkeit noch die Erweiterbarkeit. Es handelte sich um einen &lt;em&gt;switch&lt;/em&gt;-Block, der stark vereinfacht etwa dem Folgenden entsprach.&lt;br /&gt;&lt;div class=&quot;wlWriterEditableSmartContent&quot; id=&quot;scid:f32c3428-b7e9-4f15-a8ea-c502c7ff2e88:928b378e-ff22-488a-ac8e-0ccc2a4d04f8&quot; style=&quot;display: inline; float: none; margin: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;&quot;&gt;&lt;pre class=&quot;brush: c#;&quot;&gt;public class WorkItem&lt;br /&gt;{&lt;br /&gt;    private ItemSubType itemType;&lt;br /&gt;    public ItemSubType SubType { get; private set; }&lt;br /&gt;    …&lt;br /&gt;    public void Process()&lt;br /&gt;    {&lt;br /&gt;        switch(this.itemType)&lt;br /&gt;        {&lt;br /&gt;            case ItemSubType.Simple:&lt;br /&gt;                // do something simple&lt;br /&gt;            break;&lt;br /&gt;            case ItemSubType.Complex:&lt;br /&gt;                // do something complex&lt;br /&gt;            break;&lt;br /&gt;            default:&lt;br /&gt;                // just do something&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;}&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Nicht nur, dass die Klasse bei jeder Erweiterung aufs Neue angefasst werden muss und damit dem OCP widerspricht, die Methode &lt;span style=&quot;font-family: Consolas; font-size: small;&quot;&gt;&lt;em&gt;Process&lt;/em&gt;&lt;/span&gt; erfüllt damit auch noch mehrere Aufgaben. Also nutzte ich die Möglichkeit, um hier ein wenig zu entkoppeln. Zuerst war die Frage zu klären, spezialisierte &lt;span style=&quot;color: blue; font-family: Consolas;&quot;&gt;WorkItem&lt;/span&gt; Klassen anlegen oder einfach die Prozesslogik auslagern. Da sich die Änderungen ausschließlich auf den &lt;em&gt;switch&lt;/em&gt;-Block beschränkten, entschied ich mich für die Auslagerung.&lt;br /&gt;&lt;br /&gt;Für jeden SubTyp wurde eine Prozessor Klasse angelegt, die die Schnittstelle &lt;span style=&quot;color: blue; font-family: Consolas;&quot;&gt;IItemProcessor&lt;/span&gt; implementiert.&lt;br /&gt;&lt;br /&gt;&lt;div class=&quot;csharpcode&quot;&gt;&lt;div class=&quot;wlWriterEditableSmartContent&quot; id=&quot;scid:f32c3428-b7e9-4f15-a8ea-c502c7ff2e88:94ee7300-45ed-4e7f-ad3c-34537d333e91&quot; style=&quot;display: inline; float: none; margin: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;&quot;&gt;&lt;pre class=&quot;brush: c#;&quot;&gt;public interface IItemProcessor&lt;br /&gt;{&lt;br /&gt;    void Process(WorkItem item);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public class SimpleTypeProcessor : IItemProcessor&lt;br /&gt;{&lt;br /&gt;    public void Process(WorkItem item)&lt;br /&gt;    {}&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public class ComplexTypeProcessor : IItemProcessor&lt;br /&gt;{&lt;br /&gt;    public void Process(WorkItem item)&lt;br /&gt;    {}&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public class NulloProcessor : IItemProcessor&lt;br /&gt;{&lt;br /&gt;    public void Process(WorkItem item)&lt;br /&gt;    {}&lt;br /&gt;}&lt;/pre&gt;&lt;/div&gt;&lt;pre&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Der &lt;span style=&quot;color: blue; font-family: Consolas;&quot;&gt;NulloProcessor&lt;/span&gt; entspricht hierbei der Implementierung des Null-Object-Patterns. Der nächste Schritt wäre das Zuweisen des richtigen Processors zur richtigen Zeit. Dazu wird in der Regel eine Factory Klasse genutzt.&lt;br /&gt;&lt;br /&gt;&lt;div class=&quot;wlWriterEditableSmartContent&quot; id=&quot;scid:f32c3428-b7e9-4f15-a8ea-c502c7ff2e88:5236753e-e8f7-4648-9092-01c2c45df355&quot; style=&quot;display: inline; float: none; margin: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;&quot;&gt;&lt;pre class=&quot;brush: c#;&quot;&gt;public void Process()&lt;br /&gt;{&lt;br /&gt;    var processor = ProcessorFactory.GetProcessor(this.subType);&lt;br /&gt;    processor.Process(this);&lt;br /&gt;}&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;So hätte ich die Bedingungen zwar aus dem &lt;span style=&quot;color: blue; font-family: Consolas;&quot;&gt;WorkItem&lt;/span&gt; heraus genommen, aber nur in die Factory ausgelagert und dort den &lt;em&gt;switch&lt;/em&gt;-Block, der immer wieder erweitert werden müsste. &lt;br /&gt;&lt;br /&gt;Wie wäre es also, der &lt;span style=&quot;color: blue; font-family: Consolas;&quot;&gt;WorkItem&lt;/span&gt; Klasse die Prozessoren von außen herein zu geben und jeden Processor für sich selbst entscheiden lassen, ob er etwas zu tun hat?!&lt;br /&gt;&lt;br /&gt;&lt;div class=&quot;wlWriterEditableSmartContent&quot; id=&quot;scid:f32c3428-b7e9-4f15-a8ea-c502c7ff2e88:3be9a06d-d836-4551-b948-421e8a38919c&quot; style=&quot;display: inline; float: none; margin: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;&quot;&gt;&lt;pre class=&quot;brush: c#;&quot;&gt;public class WorkItem&lt;br /&gt;{&lt;br /&gt;    IList&amp;lt;IItemProcessor&amp;gt; processorList;&lt;br /&gt;    public WorkItem(IList&amp;lt;IItemProcessor processors, ...)&lt;br /&gt;    {&lt;br /&gt;        this.processorList = processors;&lt;br /&gt;        // something more&lt;br /&gt;    }&lt;br /&gt;    ...&lt;br /&gt;    public void Process()&lt;br /&gt;    {&lt;br /&gt;        this.processorList.Where(x =&amp;gt; x.CanProcess(this)).Each(proc =&amp;gt; proc.Process(this));&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public class SimpleTypeProcessor : IItemProcessor&lt;br /&gt;{&lt;br /&gt;    public bool CanProcess(WorkItem item)&lt;br /&gt;    {&lt;br /&gt;        return item.SubType == ItemSubType.Simple;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public void Process(WorkItem item)&lt;br /&gt;    {&lt;br /&gt;        // Do something simple&lt;br /&gt;    }&lt;br /&gt;}&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Die Abfrage auf &lt;span style=&quot;font-family: Consolas; font-size: small;&quot;&gt;&lt;em&gt;CanProcess&lt;/em&gt;&lt;/span&gt; empfand ich noch als zu viel Rauschen. Die einzelnen Prozessoren können doch bei Aufruf ihre Zuständigkeit selbst überprüfen.&lt;br /&gt;&lt;br /&gt;&lt;div class=&quot;wlWriterEditableSmartContent&quot; id=&quot;scid:f32c3428-b7e9-4f15-a8ea-c502c7ff2e88:5722e31c-2b14-41e3-8c98-26392ca1192e&quot; style=&quot;display: inline; float: none; margin: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;&quot;&gt;&lt;pre class=&quot;brush: c#;&quot;&gt;public class SimpleTypeProcessor : IItemProcessor&lt;br /&gt;{&lt;br /&gt;    public void Process(WorkItem item)&lt;br /&gt;    {&lt;br /&gt;        if(item.SubType != ItemSubType.Simple) return;&lt;br /&gt;        // Do something simple&lt;br /&gt;    }&lt;br /&gt;}&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Innerhalb der WorkItem Klasse wird dann einfach an alle Prozessoren “ge-broadcastet”…&lt;br /&gt;&lt;br /&gt;&lt;div class=&quot;wlWriterEditableSmartContent&quot; id=&quot;scid:f32c3428-b7e9-4f15-a8ea-c502c7ff2e88:699492ab-ec60-46aa-82c8-e28d27bfc671&quot; style=&quot;display: inline; float: none; margin: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;&quot;&gt;&lt;pre class=&quot;brush: c#;&quot;&gt;public void Process()&lt;br /&gt;{&lt;br /&gt;    processorList.Each(processor =&amp;gt; processor.Process(this));&lt;br /&gt;}&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Auf diese Weise habe ich meine Anpassungen letztlich durchgeführt und bin (noch?) recht zufrieden damit.</description><link>http://jcselke.blogspot.com/2010/12/refactoring-switch-durch-commands.html</link><author>noreply@blogger.com (Jan Christian Selke)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-5601714198208780275.post-1362775196210997268</guid><pubDate>Thu, 04 Nov 2010 20:00:00 +0000</pubDate><atom:updated>2010-11-04T13:05:53.016-07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Entwicklung</category><category domain="http://www.blogger.com/atom/ns#">StructureMap</category><title>Lazy loading von Abhängigkeiten mit StructureMap</title><description>&lt;h5&gt;Das Offensichtliche&lt;/h5&gt;  &lt;p&gt;Vor kurzem beschäftigte mich die Überlegung: Wie kann ich mit StructureMap meine Abhängigkeiten quasi &lt;em&gt;just-in-time&lt;/em&gt; holen? Es gibt ja durchaus Klassen, deren Abhängigkeiten nicht alle sofort und vor allem gemeinsam genutzt werden.&lt;/p&gt;  &lt;p&gt;Als ob das nicht genug wäre, habe ich kurz darauf einen Beitrag in der &lt;a href=&quot;http://groups.google.com/group/structuremap-users/msg/5604854fcd11189e/&quot; target=&quot;_blank&quot;&gt;Google-Group&lt;/a&gt; zu genau dieser Frage gelesen. Grund genug für mich, das nochmal genauer anzusehen und kompakt für mich zusammen zu fassen.&lt;/p&gt;  &lt;p&gt;Wenn man mit StructureMap Lazy Loading realisieren möchte, dann kann ab Version 2.6 anstelle des abhängigen Typs eine &lt;font face=&quot;Courier New&quot;&gt;Func&amp;lt;DependentType&amp;gt;&lt;/font&gt; als Parameter genutzt werden. Diese werden dann erst bei dem tatsächlichen Zugriff evaluiert. Beispielhaft könnte eine Klasse dann folgendermaßen aussehen.&lt;/p&gt;  &lt;pre class=&quot;brush: csharp; auto-links: true; collapse: false; first-line: 1; gutter: true; html-script: false; light: false; ruler: true; smart-tabs: true; tab-size: 4; toolbar: true;&quot;&gt;    public class MyType : IMyType&lt;br /&gt;    {&lt;br /&gt;        private readonly Func&amp;lt;IDependency1&amp;gt; _dependency1;&lt;br /&gt;        private readonly Func&amp;lt;IDependency2&amp;gt; _dependency2;&lt;br /&gt;&lt;br /&gt;        public MyType(Func&amp;lt;IDependency1&amp;gt; dependency1, Func&amp;lt;IDependency2&amp;gt; dependency2)&lt;br /&gt;        {&lt;br /&gt;            _dependency1 = dependency1;&lt;br /&gt;            _dependency2 = dependency2;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        public void DoSomething()&lt;br /&gt;        {&lt;br /&gt;            var dependency1 = _dependency1();&lt;br /&gt;            dependency1.DoSomething();&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        public void DoSomethingElse()&lt;br /&gt;        {&lt;br /&gt;            var dependency2 = _dependency2();&lt;br /&gt;            dependency2.DoSomethingElse();&lt;br /&gt;        }&lt;br /&gt;    }&lt;/pre&gt;&lt;br /&gt;Eigentlich eine recht einfache Methode, eine einfache Variante des Lazy Loadings zu implementieren. Aber was mir bisher etwas zu kurz kam; funktioniert das wirklich so einfach? Muss ich etwas bei der Registrierung der Typen beachten/anders machen?&lt;br /&gt;Kurz: Nein! Alles bleibt beim alt-bekannten :-).&lt;br /&gt;Für dieses recht einfache Beispiel reicht bereits eine minimale Registrierung.&lt;br /&gt;&lt;pre class=&quot;brush: csharp; auto-links: true; collapse: false; first-line: 1; gutter: true; html-script: false; light: false; ruler: true; smart-tabs: true; tab-size: 4; toolbar: true;&quot;&gt;    ObjectFactory.Initialize(x =&amp;gt; x.Scan(scan =&amp;gt;&lt;br /&gt;    {&lt;br /&gt;        scan.TheCallingAssembly();&lt;br /&gt;        scan.WithDefaultConventions();&lt;br /&gt;    }));&lt;br /&gt;&lt;br /&gt;    myType = ObjectFactory.GetInstance&amp;lt;IMyType&amp;gt;();&lt;/pre&gt;&lt;br /&gt;&lt;h5&gt;Die Magie&lt;/h5&gt;&lt;br /&gt;Für alle, die etwas mehr Hintergrundinformation haben möchten - Die Magie dahinter verbirgt sich in der Anwendung des Typs&amp;#160; &lt;font face=&quot;Courier New&quot;&gt;LazyInstance&amp;lt;T&amp;gt;&lt;/font&gt; :&lt;br /&gt;&lt;pre class=&quot;brush: csharp; auto-links: true; collapse: false; first-line: 1; gutter: true; html-script: false; light: false; ruler: true; smart-tabs: true; tab-size: 4; toolbar: true;&quot;&gt;    public class LazyInstance&amp;lt;T&amp;gt; : Instance&lt;br /&gt;    {&lt;br /&gt;        protected override string getDescription()&lt;br /&gt;        {&lt;br /&gt;            return &amp;quot;Lazy construction of &amp;quot; + typeof (T).FullName;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        protected override object build(Type pluginType, BuildSession session)&lt;br /&gt;        {&lt;br /&gt;            var container = session.GetInstance&amp;lt;IContainer&amp;gt;();&lt;br /&gt;            Func&amp;lt;T&amp;gt; func = () =&amp;gt; container.GetInstance&amp;lt;T&amp;gt;();&lt;br /&gt;&lt;br /&gt;            return func;&lt;br /&gt;        }&lt;br /&gt;    }&lt;/pre&gt;&lt;br /&gt;Die &lt;font face=&quot;Courier New&quot;&gt;Func&amp;lt;&amp;gt;&lt;/font&gt; Konstruktor Argumente werden von StructureMap als &lt;font face=&quot;Courier New&quot;&gt;LazyInstance&amp;lt;&amp;gt;&lt;/font&gt; registriert. Lediglich die Typen müssen registriert sein (sei es wie oben durch DefaultConventions oder durch manuelle Registrierung), den Rest macht StructureMap.&lt;br /&gt;Der Func&amp;lt;T&amp;gt; wird zugewiesen&lt;br /&gt;  &lt;br /&gt;&lt;font face=&quot;Courier New&quot;&gt;&amp;#160;&amp;#160;&amp;#160; () =&amp;gt; container.GetInstance&amp;lt;T&amp;gt;()&lt;br /&gt;    &lt;br /&gt;&lt;/font&gt;Schon werden Abhängigkeiten bei Bedarf nachgeladen.&lt;br /&gt;Registriert wird der Lazy-Typ übrigens im BuildUp des Containers…&lt;br /&gt;&lt;pre class=&quot;brush: csharp; auto-links: true; collapse: false; first-line: 1; gutter: true; html-script: false; light: false; ruler: true; smart-tabs: true; tab-size: 4; toolbar: true;&quot;&gt;    var funcInstance = new FactoryTemplate(typeof (LazyInstance&amp;lt;&amp;gt;));&lt;br /&gt;    _pluginGraph.FindFamily(typeof(Func&amp;lt;&amp;gt;)).AddInstance(funcInstance);&lt;br /&gt;    _pluginGraph.ProfileManager.SetDefault(typeof(Func&amp;lt;&amp;gt;), funcInstance);&lt;/pre&gt;&lt;br /&gt;Das FactoryTemplate hat wiederum eine Methode zum Schließen der offenen generischen Funcs… ;-)  </description><link>http://jcselke.blogspot.com/2010/11/lazy-loading-von-abhangigkeiten-mit.html</link><author>noreply@blogger.com (Jan Christian Selke)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-5601714198208780275.post-7754003226506229666</guid><pubDate>Sat, 25 Sep 2010 19:07:00 +0000</pubDate><atom:updated>2010-09-25T12:16:16.831-07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Entwicklung</category><category domain="http://www.blogger.com/atom/ns#">Fluent NHibernate</category><category domain="http://www.blogger.com/atom/ns#">NHibernate</category><title>Einstiegshürden mit Fluent NHibernate und dem  Oracle Instant Client</title><description>&lt;p&gt;NHibernate kenne ich nun schon eine Weile, auch Fluent NHibernate ist mir – zumindest theoretisch – kein Unbekannter mehr. Außer einem sehr flüchtigen Versuch damit einen kleinen Prototypen zu entwickeln, gab es damit noch wenig Berührungspunkte. Jetzt habe ich es doch versucht und habe prompt die Eine oder Andere Fallgrube mitgenommen. Das gab mir Grund genug, etwas darüber zu schreiben. &lt;/p&gt;  &lt;p&gt;Schon vor einiger Zeit habe ich einen sehr schönen Einstiegsartikel von &lt;a href=&quot;http://www.aspnetzone.de/blogs/juergengutsch/archive/2009/09/28/zweiter-start-mit-nhibernate.aspx&quot; target=&quot;_blank&quot;&gt;Jürgen Gutsch&lt;/a&gt; gelesen. Eine willkommen Hilfe dabei, mich intensiver mit dem Thema zu beschäftigen. Also holte ich auf der einen Seite das Visual Studio 2010 heraus, auf der anderen Jürgens Artikel und es konnte los gehen (an dieser Stelle noch ein kleines Dankeschön für die gelungene Einstiegshilfe :-)).&lt;/p&gt;  &lt;p&gt;Jetzt verwendete ich als Datenbank nicht den SQL Server und folglich nicht die SQL Server Client Verbindung, sondern Oracle Express und den Oracle Instant Client. Ich tat es erst einmal als Marginalie ab – ein Trugschluss, wie sich heraus stellte. Ich möchte damit nicht sagen, dass der Einstieg in dieser Kombination mit Fluent NHibernate schwierig ist. Es sind aber anfänglich schon die eine oder andere Hürde, die genommen werden möchten.&lt;/p&gt;  &lt;p&gt;Genug der Vorrede, es kann losgehen. Zunächst habe ich die aktuellste Version von &lt;a href=&quot;http://fluentnhibernate.org/&quot; target=&quot;_blank&quot;&gt;FluentNHibernate&lt;/a&gt; heruntergeladen und entpackt. Aus dem gesamten Verzeichnis habe ich die folgenden Assemblies in mein Testprojekt eingebunden:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;strong&gt;FluentNHibernate.dll &lt;/strong&gt;&lt;/li&gt;    &lt;li&gt;&lt;strong&gt;NHibernate.dll &lt;/strong&gt;&lt;/li&gt;    &lt;li&gt;&lt;strong&gt;NHibernate.ByteCode.Castle.dll&lt;/strong&gt; &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Schon ein erstes Kompilieren war spontan nicht von Erfolg gekrönt :-(. In der Zusammenfassung hagelte es folgende Fehler:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;font face=&quot;Courier New&quot;&gt;&lt;strong&gt;The referenced assembly &amp;quot;NHibernate.ByteCode.Castle&amp;quot; could not be resolved because it has a dependency on &amp;quot;System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a&amp;quot; which is not in the currently targeted framework &amp;quot;.NETFramework,Version=v4.0,Profile=Client&amp;quot;. &lt;/strong&gt;&lt;/font&gt;&lt;/li&gt;    &lt;li&gt;&lt;font face=&quot;Courier New&quot;&gt;&lt;strong&gt;The referenced assembly &amp;quot;NHibernate&amp;quot; could not be resolved because it has a dependency on &amp;quot;System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a&amp;quot; which is not in the currently targeted framework &amp;quot;.NETFramework,Version=v4.0,Profile=Client&amp;quot;. &lt;/strong&gt;&lt;/font&gt;&lt;/li&gt;    &lt;li&gt;&lt;font face=&quot;Courier New&quot;&gt;&lt;strong&gt;The referenced assembly &amp;quot;FluentNHibernate&amp;quot; could not be resolved because it has a dependency on &amp;quot;System.Data.OracleClient, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089&amp;quot; which is not in the currently targeted framework &amp;quot;.NETFramework,Version=v4.0,Profile=Client&amp;quot;.&lt;/strong&gt;&lt;/font&gt; &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Ok, die Meldung ist recht eindeutig –Mist, schon wieder vergessen... Also rein in die Projekteinstellungen und das Target framework entsprechen umsetzen. &lt;/p&gt;  &lt;p&gt;&lt;a href=&quot;http://lh5.ggpht.com/_6MDRCGJmRdA/TJ5IZWdF1TI/AAAAAAAAAKA/YDiupvb1ipA/s1600-h/TargetFramework4.png&quot;&gt;&lt;img title=&quot;TargetFramework&quot; style=&quot;display: inline&quot; height=&quot;363&quot; alt=&quot;TargetFramework&quot; src=&quot;http://lh3.ggpht.com/_6MDRCGJmRdA/TJ5IZ6rV1lI/AAAAAAAAAKE/oSzj-buNnH4/TargetFramework_thumb2.png?imgmax=800&quot; width=&quot;666&quot; /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Wunderbar – Jetzt baut es wenigstens schon einmal fehlerfrei. Es kann also weiter gehen. Jetzt muss der Datenbankzugriff konfiguriert werden. Ich habe den Zugriff erst einmal vollständig im Quellcode abgebildet. Es sah dann schließlich folgendermaßen aus:&lt;/p&gt; &lt;pre class=&quot;brush: vb; auto-links: true; collapse: false; first-line: 1; gutter: true; html-script: false; light: false; ruler: true; smart-tabs: true; tab-size: 4; toolbar: true;&quot;&gt;ISession session = Fluently.Configure()&lt;br /&gt;    .Database(OracleClientConfiguration.Oracle10.ConnectionString(cs =&amp;gt;&lt;br /&gt;        cs.Instance(&amp;quot;xe&amp;quot;)&lt;br /&gt;            .Server(&amp;quot;localhost&amp;quot;)&lt;br /&gt;            .Port(1521)&lt;br /&gt;            .Username(&amp;quot;myuser&amp;quot;)&lt;br /&gt;            .Password(&amp;quot;mypassword&amp;quot;))&lt;br /&gt;        .ProxyFactoryFactory(typeof(NHibernate.ByteCode.Castle.ProxyFactoryFactory))&lt;br /&gt;        .ShowSql())&lt;br /&gt;    .Mappings(m =&amp;gt; m.FluentMappings.AddFromAssemblyOf&amp;lt;IEntity&amp;gt;()).BuildSessionFactory().OpenSession();&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;Das Kompilieren funktionierte auch, also los - mit dem Test starten. Und schon fing ich mir die erste Laufzeit Ausnahme ein: &lt;font face=&quot;Courier New&quot;&gt;&lt;strong&gt;&lt;em&gt;OCIEnvCreate failed with return code -1 but error message text was not available.&lt;/em&gt;&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;a href=&quot;http://lh6.ggpht.com/_6MDRCGJmRdA/TJ5IalYxlXI/AAAAAAAAAKI/m-fbmWV85S0/s1600-h/FalscherProvider%5B4%5D.png&quot;&gt;&lt;img title=&quot;FalscherProvider&quot; style=&quot;display: inline&quot; height=&quot;406&quot; alt=&quot;FalscherProvider&quot; src=&quot;http://lh6.ggpht.com/_6MDRCGJmRdA/TJ5IbPCXb1I/AAAAAAAAAKM/nZEXIKy8BAg/FalscherProvider_thumb%5B2%5D.png?imgmax=800&quot; width=&quot;783&quot; /&gt;&lt;/a&gt;&amp;#160; &lt;/p&gt;&lt;br /&gt;&lt;p&gt;Nach kurzer Suche hatte ich die Lösung. Ich habe den falschen Provider gewählt. Wenn der Instant Client statt des Microsoft Clients verwendet wird, ist nicht die Klasse &lt;font face=&quot;Courier New&quot;&gt;&lt;strong&gt;OracleClientConfiguration&lt;/strong&gt;&lt;/font&gt; zu verwenden, sondern &lt;font face=&quot;Courier New&quot;&gt;&lt;strong&gt;OracleDataClientConfiguration&lt;/strong&gt;&lt;/font&gt;. Gut zu wissen. Kurze Anpassung.&lt;/p&gt;&lt;br /&gt;&lt;pre class=&quot;brush: vb; auto-links: true; collapse: false; first-line: 1; gutter: true; html-script: false; light: false; ruler: true; smart-tabs: true; tab-size: 4; toolbar: true;&quot;&gt;ISession session = Fluently.Configure()&lt;br /&gt;    .Database(&lt;br /&gt;        OracleDataClientConfiguration.Oracle10.ConnectionString(cs =&amp;gt;&lt;br /&gt;            cs.Instance(&amp;quot;xe&amp;quot;)&lt;br /&gt;                .Server(&amp;quot;localhost&amp;quot;)&lt;br /&gt;                .Port(1521)&lt;br /&gt;                .Username(&amp;quot;myuser&amp;quot;)&lt;br /&gt;                .Password(&amp;quot;mypassword&amp;quot;))&lt;br /&gt;            .ProxyFactoryFactory(typeof(NHibernate.ByteCode.Castle.ProxyFactoryFactory))&lt;br /&gt;        .ShowSql())&lt;br /&gt;    .Mappings(m =&amp;gt; m.FluentMappings.AddFromAssemblyOf&amp;lt;Form1&amp;gt;()).BuildSessionFactory().OpenSession();&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;Kompiliert und weiter im Test. –Rumms! Die nächste Laufzeit Ausnahme – schon wieder… Immerhin ist schon in der vierten inneren Ausnahme die Lösung zu finden ;-).&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;a href=&quot;http://lh4.ggpht.com/_6MDRCGJmRdA/TJ5IbQUs7wI/AAAAAAAAAKQ/ny_cigbI8eE/s1600-h/NoOracleDataAccess%5B4%5D.png&quot;&gt;&lt;img title=&quot;NoOracleDataAccess&quot; style=&quot;display: inline&quot; height=&quot;500&quot; alt=&quot;NoOracleDataAccess&quot; src=&quot;http://lh3.ggpht.com/_6MDRCGJmRdA/TJ5Ib089LmI/AAAAAAAAAKU/qtbLktl6zaE/NoOracleDataAccess_thumb%5B2%5D.png?imgmax=800&quot; width=&quot;700&quot; /&gt;&lt;/a&gt; &lt;/p&gt;&lt;br /&gt;&lt;p&gt;Richtig, ich hatte nur die XCopy Installation des Instant Clients durchgeführt. Keine Installation in den GAC mit den mitgelieferten Skripten. In das Ausführungsverzeichnis hatte ich die Oracle.DataAccess.dll auch noch nicht kopiert. Kein Wunder also. Schnell die Assembly in das &lt;em&gt;/bin&lt;/em&gt; Verzeichnis kopiert und sie da: Ich konnte endlich auf die Datenbank zugreifen! Nach all den kleinen Startschwierigkeiten funktionierte endlich mein Datenbankzugriff mit Fluent NHibernate.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Es fehlte nur eine Kleinigkeit; dass Auslagern der Zugriffsinformationen in einen ConnectionString. Gesagt, getan:&lt;/p&gt;&lt;br /&gt;&lt;pre class=&quot;brush: xml; auto-links: true; collapse: false; first-line: 1; gutter: true; html-script: false; light: false; ruler: true; smart-tabs: true; tab-size: 4; toolbar: true;&quot;&gt;&amp;lt;?xml version=&amp;quot;1.0&amp;quot;?&amp;gt;&lt;br /&gt;&amp;lt;configuration&amp;gt;&lt;br /&gt;  &amp;lt;connectionStrings&amp;gt;&lt;br /&gt;    &amp;lt;add name=&amp;quot;FNH.Properties.Settings.Lokal&amp;quot; connectionString=&amp;quot;User Id=myuser;Password=mypassword;Data Source=localhost:1521&amp;quot;&lt;br /&gt;        providerName=&amp;quot;Oracle.DataAccess.Client&amp;quot; /&amp;gt;&lt;br /&gt;  &amp;lt;/connectionStrings&amp;gt;&lt;br /&gt;  &amp;lt;startup&amp;gt;&lt;br /&gt;    &amp;lt;supportedRuntime version=&amp;quot;v4.0&amp;quot; sku=&amp;quot;.NETFramework,Version=v4.0&amp;quot;/&amp;gt;&lt;br /&gt;  &amp;lt;/startup&amp;gt;&lt;br /&gt;&amp;lt;/configuration&amp;gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;Dazu muss natürlich auch der Konfigurationsaufruf entsprechend angepasst werden:&lt;/p&gt;&lt;br /&gt;&lt;pre class=&quot;brush: csharp; auto-links: true; collapse: false; first-line: 1; gutter: true; html-script: false; light: false; ruler: true; smart-tabs: true; tab-size: 4; toolbar: true;&quot;&gt;ISession session = Fluently.Configure()&lt;br /&gt;    .Database(OracleDataClientConfiguration.Oracle10.ConnectionString(cs =&amp;gt;&lt;br /&gt;            cs.FromConnectionStringWithKey(&amp;quot;FNH.Properties.Settings.Lokal&amp;quot;))&lt;br /&gt;                .ProxyFactoryFactory(typeof(NHibernate.ByteCode.Castle.ProxyFactoryFactory))&lt;br /&gt;        .ShowSql())&lt;br /&gt;    .Mappings(m =&amp;gt; m.FluentMappings.AddFromAssemblyOf&amp;lt;Form1&amp;gt;()).BuildSessionFactory().OpenSession();&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;Was lange währt, … Schwierig war es letztlich wirklich nicht, aber ich habe anscheinend traumwandlerisch alles erwischt, was nicht funktionieren könnte. Das nächste Mal geht es mit Sicherheit deutlich schneller :-)&lt;/p&gt;  </description><link>http://jcselke.blogspot.com/2010/09/einstiegshurden-mit-fluent-nhibernate.html</link><author>noreply@blogger.com (Jan Christian Selke)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh3.ggpht.com/_6MDRCGJmRdA/TJ5IZ6rV1lI/AAAAAAAAAKE/oSzj-buNnH4/s72-c/TargetFramework_thumb2.png?imgmax=800" height="72" width="72"/><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-5601714198208780275.post-4550641339888370370</guid><pubDate>Fri, 24 Sep 2010 20:07:00 +0000</pubDate><atom:updated>2010-09-24T14:37:28.935-07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Entwicklung</category><category domain="http://www.blogger.com/atom/ns#">OpenXml SDK</category><category domain="http://www.blogger.com/atom/ns#">VSTO</category><category domain="http://www.blogger.com/atom/ns#">Word 2007</category><title>Tabellen in Word Dokumenten auf Vorlagenbasis erweitern - Reloaded</title><description>&lt;p&gt;Schon vor einiger Zeit habe ich über das &lt;a href=&quot;http://jcselke.blogspot.com/2010/01/tabellen-in-word2007-dokumenten-auf.html&quot; target=&quot;_blank&quot;&gt;vorlagenbasierte Erweitern von Tabellen geschrieben&lt;/a&gt;. Vor kurzem wurde in einem Kommentar um Hilfe gebeten, den Quellcode in VB.Net umzusetzen. Meine Neugier war nahezu sofort geweckt, wie es wohl tatsächlich in VB.Net aussehen könnte.&lt;/p&gt;  &lt;p&gt;So habe ich mich daran gemacht, den Quellcode zu portieren. Die erste Lösung war eine nahe 1:1 Umsetzung des Quellcodes. Einige Änderungen waren notwendig, wie etwa der Aufruf von TypParametern. Aus &lt;font face=&quot;Courier New&quot;&gt;MyType&amp;lt;MyTypeParamter&amp;gt;&lt;/font&gt; wurde unter VB.Net beispielsweise &lt;font face=&quot;Courier New&quot;&gt;MyType(Of MyTypeParameter)&lt;/font&gt;.&lt;/p&gt;  &lt;p&gt;Das Ergebnis sieht nun wie folgt aus.&lt;/p&gt;  &lt;pre class=&quot;brush: vbnet; auto-links: true; collapse: false; first-line: 1; gutter: true; html-script: false; light: false; ruler: true; smart-tabs: true; tab-size: 4; toolbar: true;&quot;&gt;Using package As WordprocessingDocument = WordprocessingDocument.Open(fileName, True)&lt;br /&gt;    Dim mainDocumentPart As MainDocumentPart = package.MainDocumentPart&lt;br /&gt;    Dim document As Document = mainDocumentPart.Document&lt;br /&gt;    Dim sdt As SdtBlock = document.Descendants(Of SdtBlock) _&lt;br /&gt;        .Where(Function(sdtBLock) sdtBLock.GetFirstChild(Of SdtProperties) _&lt;br /&gt;            .GetFirstChild(Of Tag).Val.Value = &amp;quot;Tabelle&amp;quot;) _&lt;br /&gt;        .First&lt;br /&gt;&lt;br /&gt;    For i As Integer = 0 To 5&lt;br /&gt;&lt;br /&gt;        Dim lastRow As DocumentFormat.OpenXml.Wordprocessing.TableRow = sdt.Descendants(Of Table).First.Descendants(Of TableRow).Last&lt;br /&gt;        lastRow.InsertAfterSelf( _&lt;br /&gt;            New DocumentFormat.OpenXml.Wordprocessing.TableRow( _&lt;br /&gt;                New DocumentFormat.OpenXml.Wordprocessing.TableCell(New DocumentFormat.OpenXml.Wordprocessing.Paragraph(New DocumentFormat.OpenXml.Wordprocessing.Run(New DocumentFormat.OpenXml.Wordprocessing.Text(String.Format(&amp;quot;Zeile {0}: Zelle 1&amp;quot;, (i + 2)))))), _&lt;br /&gt;                New DocumentFormat.OpenXml.Wordprocessing.TableCell(New DocumentFormat.OpenXml.Wordprocessing.Paragraph(New DocumentFormat.OpenXml.Wordprocessing.Run(New DocumentFormat.OpenXml.Wordprocessing.Text(String.Format(&amp;quot;Zeile {0}: Zelle 2&amp;quot;, (i + 2)))))), _&lt;br /&gt;                New DocumentFormat.OpenXml.Wordprocessing.TableCell(New DocumentFormat.OpenXml.Wordprocessing.Paragraph(New DocumentFormat.OpenXml.Wordprocessing.Run(New DocumentFormat.OpenXml.Wordprocessing.Text(String.Format(&amp;quot;Zeile {0}: Zelle 3&amp;quot;, (i + 2))))))))&lt;br /&gt;    Next&lt;br /&gt;End Using&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;Das gefiel mir syntaktisch eigentlich nicht besonders gut. Besonders die LINQ Erweiterungsmethoden mit den anonymen Methoden waren mir ein Dorn im Auge. Also habe ich noch etwas weiter gesucht und mich schließlich für eine Version mit der LINQ Abfrage Syntax entschieden. Dies lässt sich nun meines Erachtens deutlich einfacher lesen. Bedauerlicherweise war ich hierbei nur bedingt erfolgreich.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Wer hier mehr Erfahrung hat und mehr Kürze in die Abfragen bringen kann, soll sich hiermit dazu aufgerufen fühlen! ;-)&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Ich hoffe, das hilft fürs erste auch weiter. Ich freue mich immer über solche Anreize, wieder etwas Neues auszuprobieren. :-) &lt;/p&gt;  </description><link>http://jcselke.blogspot.com/2010/09/tabellen-in-word-dokumenten-auf.html</link><author>noreply@blogger.com (Jan Christian Selke)</author><thr:total>10</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-5601714198208780275.post-5403029237493763760</guid><pubDate>Sun, 19 Sep 2010 22:44:00 +0000</pubDate><atom:updated>2010-09-19T15:46:35.304-07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Architektur</category><category domain="http://www.blogger.com/atom/ns#">Entwicklung</category><category domain="http://www.blogger.com/atom/ns#">MVVM Light</category><category domain="http://www.blogger.com/atom/ns#">WPF</category><title>Erste Gehversuche mit MVVM Light</title><description>&lt;p&gt;Vor Kurzem habe ich mich dazu entschlossen, erste Schritte mit dem &lt;a href=&quot;http://www.galasoft.ch/mvvm/getstarted/&quot; target=&quot;_blank&quot;&gt;MVVM Light&lt;/a&gt; von &lt;a href=&quot;http://blog.galasoft.ch/&quot; target=&quot;_blank&quot;&gt;Laurent Bugnion&lt;/a&gt; in der WPF Entwicklung zu versuchen. Eines muss man diesem Framework lassen, es ist wirklich einfach und schnell damit produktiv zu werden.&lt;/p&gt;  &lt;p&gt;Kurzerhand habe ich die aktuelle Version 3 als ZIP Paket herunter geladen und entpackt. Der Anfang ist altbekannt: Neues WPF Projekt im Visual Studio angelegt, die WPF4 Assemblies in mein Prototypen Projekt eingebunden - los gings.&lt;/p&gt;  &lt;p&gt;Meine erste Versuche beschäftigten sich mit dem Commanding. Innerhalb meines Prototypen fügte ich vorerst mal nur einen TreeView ein. Bei Doppelklick auf einzelne Elemente sollte ein kleines Fenster für Detailinformationen geöffnet werden. Da der TreeView eine solche Funktionalität nun mal nicht out-of-the-box liefert, habe ich mir das Command Binding des MVVM Light zunutze gemacht. Was soll ich sagen – es war klasse.&lt;/p&gt;  &lt;p&gt;Als erstes habe ich den Commanding Namespace eingebunden.&lt;/p&gt;  &lt;pre class=&quot;brush: csharp; auto-links: true; collapse: false; first-line: 1; gutter: true; html-script: false; light: false; ruler: true; smart-tabs: true; tab-size: 4; toolbar: true;&quot;&gt;using GalaSoft.MvvmLight.Command;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Dann in meinem ViewModel eine Eigenschaft vom Typ &lt;font face=&quot;Courier New&quot;&gt;RelayCommand&lt;/font&gt; hinzugefügt, der im Konstruktor die Funktionalität zugewiesen wurde.&lt;/p&gt;&lt;br /&gt;&lt;pre class=&quot;brush: csharp; auto-links: true; collapse: false; first-line: 1; gutter: true; html-script: false; light: false; ruler: true; smart-tabs: true; tab-size: 4; toolbar: true;&quot;&gt;public DokumentViewModel(Dokument dokument)&lt;br /&gt;{&lt;br /&gt;    _dokument = dokument;&lt;br /&gt;    ShowDokument = new RelayCommand(() =&amp;gt; Messenger.Default.Send(new ShowDokument(Id)));&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public RelayCommand ShowDokument { get; private set; }&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;Innerhalb des Xaml Codes habe ich dann das Command mit Hilfe eines Triggers an den TreeView gebunden: fertig! …Und es lief auf Anhieb.&lt;/p&gt;&lt;br /&gt;&lt;pre class=&quot;brush: csharp; auto-links: true; collapse: false; first-line: 1; gutter: true; html-script: false; light: false; ruler: true; smart-tabs: true; tab-size: 4; toolbar: true;&quot;&gt;&amp;lt;TreeView ItemsSource=&amp;quot;{Binding Mappe}&amp;quot;&amp;gt;&lt;br /&gt;    &amp;lt;TreeView.Resources&amp;gt;&lt;br /&gt;    …&lt;br /&gt;        &amp;lt;DataTemplate DataType=&amp;quot;{x:Type ViewModel:DokumentViewModel}&amp;quot;&amp;gt;&lt;br /&gt;            &amp;lt;StackPanel Orientation=&amp;quot;Horizontal&amp;quot;&amp;gt;&lt;br /&gt;                &amp;lt;TextBlock Text=&amp;quot;{Binding Id}&amp;quot;&amp;gt;&lt;br /&gt;                    &amp;lt;i:Interaction.Triggers&amp;gt;&lt;br /&gt;                        &amp;lt;i:EventTrigger EventName=&amp;quot;MouseDoubleClick&amp;quot;&amp;gt;&lt;br /&gt;                            &amp;lt;cmd:EventToCommand Command=&amp;quot;{Binding ShowDokument&amp;quot;/&amp;gt;&lt;br /&gt;                        &amp;lt;/i:EventTrigger&amp;gt;&lt;br /&gt;                    &amp;lt;/i:Interaction.Triggers&amp;gt;&lt;br /&gt;                &amp;lt;/TextBlock&amp;gt;&lt;br /&gt;            &amp;lt;/StackPanel&amp;gt;&lt;br /&gt;        &amp;lt;/DataTemplate&amp;gt;&lt;br /&gt;    &amp;lt;/TreeView.Resources&amp;gt;&lt;br /&gt;&amp;lt;/TreeView&amp;gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;Wenn das nicht einfach ist. ;-) Zu diesem Zeitpunkt kannte meine Begeisterung keine Grenzen mehr. Wenn das so leicht weiter geht, dachte ich mir, ist das schon so gut wie fertig. :-)&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Wie schon in der Command Zuweisung oben zu erkennen ist, habe ich mir direkt dabei bereits den &lt;font face=&quot;Courier New&quot;&gt;Messenger&lt;/font&gt; angesehen und genutzt, der mit dem MVVM Light kommt. Dazu flugs den Namespace Messaging eingebunden.&lt;/p&gt;&lt;br /&gt;&lt;pre class=&quot;brush: csharp; auto-links: true; collapse: false; first-line: 1; gutter: true; html-script: false; light: false; ruler: true; smart-tabs: true; tab-size: 4; toolbar: true;&quot;&gt;using GalaSoft.MvvmLight.Messaging;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;Auch hier war mein erster Eindruck hervorragend. Die gesendete Nachricht, aus dem obigen Codebeispiel, wird von einem registrierten Listener verarbeitet. &lt;/p&gt;&lt;br /&gt;&lt;pre class=&quot;brush: csharp; auto-links: true; collapse: false; first-line: 1; gutter: true; html-script: false; light: false; ruler: true; smart-tabs: true; tab-size: 4; toolbar: true;&quot;&gt;public class DokumentListener&lt;br /&gt;{&lt;br /&gt;    public DokumentListener()&lt;br /&gt;    {&lt;br /&gt;        Messenger.Default.Register&amp;lt;ShowDokument&amp;gt;(typeof(ShowDokument), x =&amp;gt; Handle(x));&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public void Handle(ShowDokument message)&lt;br /&gt;    {&lt;br /&gt;        ...&lt;br /&gt;    }&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;Grundsätzlich gefällt mir dieser Messenger zum Einstieg auch noch immer, ein bisschen Bauschmerzen habe ich aber bekommen.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Was mir nicht gefällt, ist die Tatsache, dass die Listener Klasse den Messenger kennt. Dies ist eine Abhängigkeit, auf die ich gerne verzichten würde. Außerdem muss jede behandelbare Nachricht einzeln in der Klasse registriert werden, was bei zentralen Klassen mehr Aufwand bedeuten kann. Was mir ebenfalls nicht besonders gut gefällt, ist die Tatsache, dass Klassen, die Nachrichten behandeln können, nicht sofort durch ein Muster/Namensgebung erkennbar sind.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Da ohnehin mit DI Frameworks gearbeitet wird, halte ich eine eigene Interceptor Implementierung mit festen Konventionen in Kombination mit einem eigenen Messenger für die Registrierung von Listenern an einem Messenger für die bessere Variante.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Ich werde nach dem jüngsten Stand die Funktionalität zum Binden von Commands des MVVM nutzen. Den Messenger werde ich mir aber voraussichtlich maßschneidern und meinen Vorstellungen entsprechend anpassen. Vielleicht werde ich darüber ein anderes mal schreiben…&lt;/p&gt;  </description><link>http://jcselke.blogspot.com/2010/09/erste-gehversuche-mit-mvvm-light.html</link><author>noreply@blogger.com (Jan Christian Selke)</author><thr:total>2</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-5601714198208780275.post-424146679201711533</guid><pubDate>Fri, 06 Aug 2010 20:39:00 +0000</pubDate><atom:updated>2010-08-06T13:39:50.162-07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Entwicklung</category><category domain="http://www.blogger.com/atom/ns#">OpenXml</category><category domain="http://www.blogger.com/atom/ns#">VSTO</category><category domain="http://www.blogger.com/atom/ns#">Word 2007</category><title>Interessante Word-Autokorrektur</title><description>&lt;p&gt;Das Microsoft Word nicht zuletzt auch aufgrund der Unterstützung des transienten Schemas recht fehlertolerant ist, ist bekannt. Einen besonders interessanten Effekt, der bei fehlerhafter Dokumentstruktur auftreten kann, habe ich vor Kurzem zu Augen bekommen.&lt;/p&gt;  &lt;p&gt;Es begann damit, dass wir ein neues Dokument erzeugt haben. Dabei haben wir den Fehler begangen, dass der Inhalt eines ContentControls auf &lt;strong&gt;&lt;em&gt;body&lt;/em&gt;&lt;/strong&gt; Ebene vollständig geleert wurde.&lt;/p&gt;  &lt;p&gt;&lt;a href=&quot;http://lh4.ggpht.com/_6MDRCGJmRdA/TFxzDMRTAPI/AAAAAAAAAJg/ryFnqRLhev4/s1600-h/emptycc9.png&quot;&gt;&lt;img title=&quot;emptycc&quot; style=&quot;display: inline&quot; height=&quot;226&quot; alt=&quot;emptycc&quot; src=&quot;http://lh4.ggpht.com/_6MDRCGJmRdA/TFxzDlYFUgI/AAAAAAAAAJk/_7NE6jvuEbA/emptycc_thumb5.png?imgmax=800&quot; width=&quot;571&quot; /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Die Folge war nun, dass nach dem ersten Bearbeiten und Speichern des Dokuments, die Struktur innerhalb des Dokuments verschoben wurde. Der Unterschied kann bereits in der Entwicklungsansicht in Word ausgemacht werden.&lt;/p&gt;  &lt;p&gt;&lt;a href=&quot;http://lh6.ggpht.com/_6MDRCGJmRdA/TFxzEDeFh2I/AAAAAAAAAJo/UZRg3gTfcKc/s1600-h/test4.png&quot;&gt;&lt;img title=&quot;test&quot; style=&quot;display: inline&quot; height=&quot;295&quot; alt=&quot;test&quot; src=&quot;http://lh4.ggpht.com/_6MDRCGJmRdA/TFxzEW-CuHI/AAAAAAAAAJs/C0lF8PnyCpQ/test_thumb2.png?imgmax=800&quot; width=&quot;800&quot; /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Was genau passierte hier aber?&lt;/p&gt;  &lt;p&gt;Word korrigierte das Dokument selbstständig, indem der nächst folgende Paragraf in das leere ContentControl verschoben wurde. In diesem Fall handelt es sich dabei um den Paragrafen mit dem Text &lt;em&gt;Textparagraf nach dem leeren ContentControl. &lt;/em&gt;&lt;/p&gt;  &lt;p&gt;Nach dem Speichern weist das Dokument jetzt folgende Struktur auf.&lt;/p&gt;  &lt;p&gt;&lt;a href=&quot;http://lh3.ggpht.com/_6MDRCGJmRdA/TFxzE93Xt0I/AAAAAAAAAJw/R74CfjULgH0/s1600-h/emptycc24.png&quot;&gt;&lt;img title=&quot;emptycc2&quot; style=&quot;display: inline&quot; height=&quot;305&quot; alt=&quot;emptycc2&quot; src=&quot;http://lh5.ggpht.com/_6MDRCGJmRdA/TFxzFHA0bkI/AAAAAAAAAJ0/EUG_nOSvaw0/emptycc2_thumb2.png?imgmax=800&quot; width=&quot;628&quot; /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;h5&gt;Fazit&lt;/h5&gt;  &lt;p&gt;Word ist in der Tat sehr Fehlertolerant, allerdings werden mit dem Speichern automatische Korrekturen vorgenommen, die zum Teil nur schwer erkannt werden können. Diese Korrekturen können aber erhebliche Veränderungen in der Dokumentstruktur nach sich ziehen, die eine automatische Weiterverarbeitung der Dokumente unter Umständen stark beeinträchtigen können.&lt;/p&gt;  </description><link>http://jcselke.blogspot.com/2010/08/interessante-word-autokorrektur.html</link><author>noreply@blogger.com (Jan Christian Selke)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh4.ggpht.com/_6MDRCGJmRdA/TFxzDlYFUgI/AAAAAAAAAJk/_7NE6jvuEbA/s72-c/emptycc_thumb5.png?imgmax=800" height="72" width="72"/><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-5601714198208780275.post-2544317302333879960</guid><pubDate>Fri, 18 Jun 2010 08:25:00 +0000</pubDate><atom:updated>2010-06-18T01:25:32.334-07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Agile</category><category domain="http://www.blogger.com/atom/ns#">Continuous Integration</category><category domain="http://www.blogger.com/atom/ns#">Scrum</category><category domain="http://www.blogger.com/atom/ns#">TFS</category><title>Scrum Prozessvorlage für TFS</title><description>&lt;p&gt;Zwar nicht mehr brandaktuell, aber Microsoft bietet seit Anfang des Monats die Beta Version einer Scrum Prozessvorlage für den TFS zum kostenlosen Download an. Mehr dazu findet sich &lt;a href=&quot;http://blogs.msdn.com/b/vsnewsde/archive/2010/06/09/scrum-mit-team-foundation-server-echte-scrum-prozessvorlage-zum-kostenlosen-download.aspx&quot; target=&quot;_blank&quot;&gt;hier&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;Folgende Punkte werden mit der Vorlage abgedeckt:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Work Item Types      &lt;ul&gt;       &lt;li&gt;Product Backlog Item &lt;/li&gt;        &lt;li&gt;Bug &lt;/li&gt;        &lt;li&gt;Task &lt;/li&gt;        &lt;li&gt;Impediment &lt;/li&gt;        &lt;li&gt;Test Case &lt;/li&gt;        &lt;li&gt;Sprint &lt;/li&gt;     &lt;/ul&gt;   &lt;/li&gt;    &lt;li&gt;Reports      &lt;ul&gt;       &lt;li&gt;Release Burndown &lt;/li&gt;        &lt;li&gt;Velocity &lt;/li&gt;        &lt;li&gt;Sprint Burndown &lt;/li&gt;     &lt;/ul&gt;   &lt;/li&gt;    &lt;li&gt;SharePoint Project Portal &lt;/li&gt; &lt;/ul&gt;  </description><link>http://jcselke.blogspot.com/2010/06/scrum-prozessvorlage-fur-tfs.html</link><author>noreply@blogger.com (Jan Christian Selke)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-5601714198208780275.post-1675160488377476785</guid><pubDate>Thu, 17 Jun 2010 06:26:00 +0000</pubDate><atom:updated>2010-06-16T23:27:34.998-07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Entwicklung</category><category domain="http://www.blogger.com/atom/ns#">StructureMap</category><title>Konstruktorinjektion unterschiedlicher Instanzen eines Typs mit StructureMap</title><description>&lt;p&gt;In einem Projekt, in dem wir StructureMap als DI Container nutzen, standen wir vor einem kleinen Rätsel. Wir hatten einen Typ, der im Konstruktor als Parameter zwei unterschiedliche Objekte des gleichen Typs erwartete.&lt;/p&gt; &lt;pre class=&quot;brush: csharp; auto-links: true; collapse: false; first-line: 1; gutter: true; html-script: false; light: false; ruler: true; smart-tabs: true; tab-size: 4; toolbar: true;&quot;&gt;public interface IMojo&lt;br /&gt;{&lt;br /&gt;    …&lt;br /&gt;}&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;public class Mojo&lt;br /&gt;{&lt;br /&gt;    public Mojo(IFooBar fooBar1, IFooBar fooBar2)&lt;br /&gt;    {&lt;br /&gt;        …&lt;br /&gt;    }&lt;br /&gt;    ...&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;Zuerst haben wir hier die StructureMap Standardregistrierung genutzt.&lt;br /&gt;&lt;pre class=&quot;brush: csharp; auto-links: true; collapse: false; first-line: 1; gutter: true; html-script: false; light: false; ruler: true; smart-tabs: true; tab-size: 4; toolbar: true;&quot;&gt;For&amp;lt;IMojo&amp;gt;().Use&amp;lt;Mojo&amp;gt;();&lt;br /&gt;For&amp;lt;IFooBar&amp;gt;().Use&amp;lt;FooBar&amp;gt;();&lt;/pre&gt;&lt;br /&gt;Das hatte aber zur Folge, dass nicht zwei Instanzen des Typs als Parameter injiziert wurden (was ich eigentlich aufgrund des transienten LifeCycles erwartet hatte), sondern zweimal die selbe Instanz. Ein andere Lösung musste also her.&lt;br /&gt;Kurz gesagt: wir haben letztlich benannte Instanzen genutzt. Ich weiß, dass es unterschiedliche Ansichten über Sinn und Unsinn von benannten Instanzen gibt – in diesem Fall funktioniert es damit aber für uns. Falls jemand eine andere Idee hat, bin ich für Anregungen offen ;-).&lt;br /&gt;Die Registrierung sieht zum Schluss nun wie folgt aus:&lt;br /&gt;&lt;pre class=&quot;brush: csharp; auto-links: true; collapse: false; first-line: 1; gutter: true; html-script: false; light: false; ruler: true; smart-tabs: true; tab-size: 4; toolbar: true;&quot;&gt;For&amp;lt;IFooBar&amp;gt;().Use&amp;lt;FooBar&amp;gt;().Named(&amp;quot;foo1&amp;quot;);&lt;br /&gt;For&amp;lt;IFoorBar&amp;gt;().Use&amp;lt;FooBar&amp;gt;().Named(&amp;quot;foo2&amp;quot;);&lt;br /&gt;&lt;br /&gt;For&amp;lt;IMojo&amp;gt;().Use&amp;lt;Mojo&amp;gt;()&lt;br /&gt;    .Ctor&amp;lt;IFooBar&amp;gt;(&amp;quot;fooBar1&amp;quot;).Is(x =&amp;gt; x.TheInstanceNamed(&amp;quot;foo1&amp;quot;))&lt;br /&gt;    .Ctor&amp;lt;IFooBar&amp;gt;(&amp;quot;fooBar2&amp;quot;).Is(x =&amp;gt; x.TheInstanceNamed(&amp;quot;foo2&amp;quot;));&lt;/pre&gt;  </description><link>http://jcselke.blogspot.com/2010/06/konstruktorinjektion-unterschiedlicher.html</link><author>noreply@blogger.com (Jan Christian Selke)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-5601714198208780275.post-3588562799838274441</guid><pubDate>Wed, 16 Jun 2010 19:11:00 +0000</pubDate><atom:updated>2010-06-16T12:11:58.591-07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Artikel</category><category domain="http://www.blogger.com/atom/ns#">Continuous Integration</category><title>Buildautomation mit Hudson in der dotnetpro</title><description>&lt;p&gt;Mit etwas stolz habe ich gesehen, dass der Artikel &lt;strong&gt;Bitte ein Build! Software automatisiert mit Hudson bauen&lt;/strong&gt;, den ich gemeinsam mit meinem Kollegen &lt;a href=&quot;http://blog.codemurai.de/&quot; target=&quot;_blank&quot;&gt;André Krämer&lt;/a&gt; geschrieben habe, in der &lt;strong&gt;aktuellen Ausgabe 07/2010 &lt;/strong&gt;der &lt;a href=&quot;http://www.dotnetpro.de/CurrentIssue.aspx&quot; target=&quot;_blank&quot;&gt;dotnetpro&lt;/a&gt; erschienen ist.&lt;/p&gt;  &lt;p&gt;&lt;a href=&quot;http://lh3.ggpht.com/_6MDRCGJmRdA/TBkh-noLOZI/AAAAAAAAAJY/W48qsQHtnVM/s1600-h/dnp_072010%5B3%5D.jpg&quot;&gt;&lt;img title=&quot;dnp_072010&quot; style=&quot;display: inline&quot; height=&quot;184&quot; alt=&quot;dnp_072010&quot; src=&quot;http://lh5.ggpht.com/_6MDRCGJmRdA/TBkh_c-KIzI/AAAAAAAAAJc/2I6xi1Do5fk/dnp_072010_thumb%5B1%5D.jpg?imgmax=800&quot; width=&quot;130&quot; /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Wir stellen einen im .Net Umfeld eher unbekannten Vertreter der Buildserver vor: &lt;a href=&quot;http://hudson-ci.org/&quot; target=&quot;_blank&quot;&gt;Hudson&lt;/a&gt;. Weit verbreitet in der Java Welt stellt er als OSS auch eine mächtige und kostengünstige Alternative zu Buildservern wie dem TFS oder CruiseControl.Net dar.&lt;/p&gt;  &lt;p&gt;Also, lesen… ;-)&lt;/p&gt;  </description><link>http://jcselke.blogspot.com/2010/06/buildautomation-mit-hudson-in-der.html</link><author>noreply@blogger.com (Jan Christian Selke)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh5.ggpht.com/_6MDRCGJmRdA/TBkh_c-KIzI/AAAAAAAAAJc/2I6xi1Do5fk/s72-c/dnp_072010_thumb%5B1%5D.jpg?imgmax=800" height="72" width="72"/><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-5601714198208780275.post-3623662361341570769</guid><pubDate>Tue, 04 May 2010 21:40:00 +0000</pubDate><atom:updated>2010-05-04T14:42:28.110-07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Architektur</category><category domain="http://www.blogger.com/atom/ns#">Entwicklung</category><category domain="http://www.blogger.com/atom/ns#">StructureMap</category><category domain="http://www.blogger.com/atom/ns#">VSTO</category><category domain="http://www.blogger.com/atom/ns#">Word 2007</category><title>DI/IoC und StartUp in VSTO Projekten</title><description>&lt;p&gt;Vor einiger Zeit schrieb ich über einen Ansatz in &lt;a href=&quot;http://jcselke.blogspot.com/2009/12/mvp-fur-vsto-projekte-auch-hier-gilt.html/&quot; target=&quot;_blank&quot;&gt;VSTO Projekten das MVP Pattern&lt;/a&gt; einzusetzen und damit auch – zumindest mehr oder weniger indirekt – über Testbarkeit und DI. Zugegeben, damals fand ich den Ansatz schon recht gut. Recht gut finde ich den &lt;em&gt;Ansatz&lt;/em&gt; noch immer, aber so richtig zufrieden war ich damit eigentlich nicht.&lt;/p&gt;  &lt;p&gt;Als Konsequenz habe ich immer wieder darüber nachgedacht, wie der Ansatz weiter verfeinert werden könnte. Mittlerweile bin ich bei einer Variante angekommen, die ich noch wieder ein Stück weit besser finde.&lt;/p&gt;  &lt;p&gt;Was mich an der ersten Variante besonders störte, war die Initialisierung des AddIns und das Anhängen des ersten Presenters an den Ribbon. Den &lt;em&gt;passive view &lt;/em&gt;Ansatz halte ich mittlerweile auch nicht mehr für notwendig. Die Logik muss nicht maximal von der Oberfläche isoliert werden. Es kann also genauso gut ein anderes &lt;em&gt;presentation pattern, &lt;/em&gt;etwa der &lt;em&gt;supervising controller&lt;/em&gt;,&lt;em&gt;&amp;#160;&lt;/em&gt;angewandt werden. Hierbei handelt es sich aber eher um eine Frage des persönlichen Geschmacks.&lt;/p&gt;  &lt;p&gt;Das eigentliche Thema ist also der Einstieg ins bzw. die Initialisierung des AddIns. Viele AddIns weisen sich durch komplexere Initialisierungslogik aus. Damit diese aber nicht etwa die Word Instanz vor weiterer Ausführung blockiert, sollte die Initialisierung asynchron im Hintergrund ablaufen. Zuerst dachte ich an den guten alten Backgroundworker: Nach einiger dieser erschien mir aber schnell als etwas zu umständlich, schwerfällig und unflexibel.&lt;/p&gt;  &lt;p&gt;Die Lösung, für die ich mich letztlich entschieden habe, ist eine Variante des &lt;a href=&quot;http://jcselke.blogspot.com/2010/01/das-commandexecutor-pattern.html/&quot; target=&quot;_blank&quot;&gt;Command Executors&lt;/a&gt;. Der erste Aufruf erfolgt innerhalb der StartUp-Methode des AddIns. &lt;/p&gt;  &lt;pre class=&quot;brush: csharp; auto-links: true; collapse: false; first-line: 1; gutter: true; html-script: false; light: false; ruler: true; smart-tabs: true; tab-size: 4; toolbar: true;&quot;&gt;private void ThisAddIn_Startup(object sender, System.EventArgs e)&lt;br /&gt;{&lt;br /&gt;    new BackgroundExecutor(new SynchronizationContext()).Execute(() =&amp;gt;&lt;br /&gt;    {&lt;br /&gt;        new Bootstrapper().BootstrapAddInDIContainer&amp;lt;IRibbonPresenter&amp;lt;IRibbonView&amp;gt;&amp;gt;();&lt;br /&gt;        return () =&amp;gt; this.Initialized = true;&lt;br /&gt;    });&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;Die Rückmeldung an das AddIn erfolgt als &lt;em&gt;continuation. &lt;/em&gt;Das Initialisierungsflag des AddIns wird gesetzt und damit erst die Funktionalität des AddIns zur Verfügung gestellt. So bleibt Word trotz möglicher aufwändiger Initialisierungslogik reaktionsfähig.&lt;br /&gt;&lt;br /&gt;Bleibt die Frage, wie wird der Presenter zugewiesen? Dies steckt bereits im Bootstrapper des DI Containers. In meinem Beispiel verwende ich mal wieder StructureMap.&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;brush: csharp; auto-links: true; collapse: false; first-line: 1; gutter: true; html-script: false; light: false; ruler: true; smart-tabs: true; tab-size: 4; toolbar: true;&quot;&gt;public STARTTYPE BootstrapAddInDIContainer&amp;lt;STARTUPTYPE&amp;gt;() where STARTUPTYPE : class&lt;br /&gt;{&lt;br /&gt;    var container = BuildUpContainer();&lt;br /&gt;    return container.GetInstance&amp;lt;STARTUPTYPE&amp;gt;();&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;Nachdem der Container konfiguriert und aufgebaut ist, wird der Presenter ein Mal aus dem Container abgerufen. Aufgrund der Anweisung mit &lt;em&gt;OnCreationForAll(Action&amp;lt;PLUGINTYPE&amp;gt;) &lt;/em&gt;wird ein TypeInterceptor registriert, der die hinterlegte Aktion gegen jede neu erstellte Instanz durchführt.&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;brush: csharp; auto-links: true; collapse: false; first-line: 1; gutter: true; html-script: false; light: false; ruler: true; smart-tabs: true; tab-size: 4; toolbar: true;&quot;&gt;public class AddInRegistry : Registry&lt;br /&gt;{&lt;br /&gt;    public AddInRegistry()&lt;br /&gt;    {&lt;br /&gt;        For&amp;lt;IRibbonPresenter&amp;lt;IRibbonView&amp;gt;&amp;gt;().Use&amp;lt;RibbonPresenter&amp;gt;();&lt;br /&gt;        For&amp;lt;IRibbonPresenter&amp;lt;IRibbonView&amp;gt;&amp;gt;().OnCreationForAll(x =&amp;gt;&lt;br /&gt;            x.View = (IRibbonView) Globals.Ribbons.FirstOrDefault(y =&amp;gt;&lt;br /&gt;                y is MvpDiSampleRibbon));&lt;br /&gt;    }&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Der AddIn Ribbon wird aus der Liste der Ribbons ausgelesen und als View für den Presenter übergeben. Und da diese Instanz nur einmal beim StartUp abgerufen wird und dabei an den Ribbon gebunden wird, muss man sich keine Sorgen über Mehrfachinstanziierungen machen.&lt;br /&gt;&lt;br /&gt;Mal abwarten, an welchem Teil ich als nächstes weiter drehen werde…  </description><link>http://jcselke.blogspot.com/2010/05/diioc-in-vsto-projekten.html</link><author>noreply@blogger.com (Jan Christian Selke)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-5601714198208780275.post-6545483632037323963</guid><pubDate>Mon, 03 May 2010 21:18:00 +0000</pubDate><atom:updated>2010-05-03T14:27:26.273-07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Architektur</category><category domain="http://www.blogger.com/atom/ns#">Design Pattern</category><category domain="http://www.blogger.com/atom/ns#">Entwicklung</category><title>Ist der Entwicklerspaß mit C# 2.0 vorbei?</title><description>&lt;p&gt;C# 4.0 und &lt;em&gt;dynamics&lt;/em&gt; sind cool.&lt;/p&gt; &lt;p&gt;C# 3.5 mit &lt;em&gt;extension methods&lt;/em&gt;, &lt;em&gt;lamda&lt;/em&gt;-Ausdrücken und &lt;em&gt;LINQ &lt;/em&gt;war fast noch spannender… was aber ist mit 2.0?&lt;/p&gt; &lt;p&gt;Leider hat man nicht immer die Chance in Projekten mit der neuesten Technologie zu arbeiten. Es gibt schließlich auch noch Pflege-Projekte, die auf einer älteren Version aufsetzen, aber auch betreut sein wollen. Ist dann der Spaß vorbei?!&lt;/p&gt; &lt;p&gt;Nein. Die Syntax wirkt vielleicht nicht mehr ganz so elegant; lambda-Ausdrücke und extension methods gibt es schließlich noch nicht. Dafür gibt es aber noch immer die anonymen Methoden. Diese werden, völlig zu unrecht, zu wenig beachtet.&lt;/p&gt; &lt;p&gt;Sicherlich, Entwicklung darf nicht allein auf den Spaß reduziert werden - aber es macht doch auch einen großen Anteil aus. Wer keinen Spaß hat, ist nicht kreativ. Wer allgemein keinen Spaß daran hat, sollte sich lieber überlegen, ob er wirklich das Richtige tut…&lt;/p&gt; &lt;p&gt;Zurück zum Thema. Anonyme Methoden bieten beachtliche Möglichkeiten. Mit dem 3.5er Framework wurde das Rad der Sprache nicht neu erfunden. Deutlich wird dies bereits an einem einfachen Quelltextauszug.&lt;/p&gt; &lt;pre class=&quot;brush: csharp; auto-links: true; collapse: false; first-line: 1; gutter: true; html-script: false; light: false; ruler: true; smart-tabs: true; tab-size: 4; toolbar: true;&quot;&gt;var liste = new List&amp;lt;string&amp;gt;{&amp;quot;Test&amp;quot;, &amp;quot;Test2&amp;quot;};&lt;br /&gt;liste.Any(x =&amp;gt; x.Contains(&amp;quot;Test&amp;quot;));&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;Schaut man sich nun das Kompilat in einem Reflektor an, stellt man fest: Es gibt nichts bedeutend neues.&lt;/p&gt;&lt;br /&gt;&lt;pre class=&quot;brush: csharp; auto-links: true; collapse: false; first-line: 1; gutter: true; html-script: false; light: false; ruler: true; smart-tabs: true; tab-size: 4; toolbar: true;&quot;&gt;List&amp;lt;string&amp;gt; &amp;lt;&amp;gt;g__initLocal0 = new List&amp;lt;string&amp;gt;();&lt;br /&gt;&amp;lt;&amp;gt;g__initLocal0.Add(&amp;quot;Test&amp;quot;);&lt;br /&gt;&amp;lt;&amp;gt;g__initLocal0.Add(&amp;quot;Test2&amp;quot;);&lt;br /&gt;&amp;lt;&amp;gt;g__initLocal0.Any&amp;lt;string&amp;gt;(delegate (string x) {&lt;br /&gt;    return x.Contains(&amp;quot;Test&amp;quot;);&lt;br /&gt;});&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;Der Typ-Initialisierer wird in Einzelaufrufe ausgewertet und der lambda-Ausdruck in eine anonyme Methode übersetzt. Also sind lambdas im Endeffekt auch nichts anderes als hübsch verpackte anonyme Methoden und damit, mit Ausnahme der Anwendung in &lt;em&gt;extension methods&lt;/em&gt;, auch in 2.0 umsetzbar.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Auf diesem Wissen aufbauend, habe ich vor kurzem eine FileService Klasse geschrieben. Dieser Service macht nichts anderes, als ein byte-Array in eine Datei zu schreiben. Der Kontrakt dieses Service ist relativ schmal gehalten. Auffällig sind nur die Methoden &lt;em&gt;Write(…), &lt;/em&gt;die zum Einen einen Action delegate als Paramter erwarten, zum Anderen als Rückgabewert einen Typ von sich selbst übergeben. Alles bereits in Vorbereitung auf das &lt;em&gt;method chaining &lt;/em&gt;im Stile einer fluent API.&lt;/p&gt;&lt;br /&gt;&lt;pre class=&quot;brush: csharp; auto-links: true; collapse: false; first-line: 1; gutter: true; html-script: false; light: false; ruler: true; smart-tabs: true; tab-size: 4; toolbar: true;&quot;&gt;public interface IFileService &lt;br /&gt;{ &lt;br /&gt;    void Write(Action&amp;lt;FileExpression&amp;gt; expression); &lt;br /&gt;    IFileService Write(byte[] bytes); &lt;br /&gt;    void ToFile(string path); &lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;Auch die Implementierung ist noch recht übersichtlich. Alles weder Hexenwerk noch Raketentechnik…&lt;/p&gt;&lt;br /&gt;&lt;pre class=&quot;brush: csharp; auto-links: true; collapse: false; first-line: 1; gutter: true; html-script: false; light: false; ruler: true; smart-tabs: true; tab-size: 4; toolbar: true;&quot;&gt;public class FileService : IFileService &lt;br /&gt;{ &lt;br /&gt;    private byte[] fileBytes; &lt;br /&gt;&lt;br /&gt;    public FileService() &lt;br /&gt;    { &lt;br /&gt;    } &lt;br /&gt;&lt;br /&gt;    public void Write(Action&amp;lt;FileExpression&amp;gt; expression) &lt;br /&gt;    { &lt;br /&gt;        expression(new FileExpression(this)); &lt;br /&gt;    } &lt;br /&gt;&lt;br /&gt;    public IFileService FileContent(byte[] bytes) &lt;br /&gt;    { &lt;br /&gt;        this.fileBytes = bytes; &lt;br /&gt;        return this; &lt;br /&gt;    } &lt;br /&gt;&lt;br /&gt;    public void ToFile(string path) &lt;br /&gt;    { &lt;br /&gt;        FileStream fs = new FileStream(path, FileMode.Create, FileAccess.ReadWrite); &lt;br /&gt;        using (BinaryWriter bw = new BinaryWriter(fs)) &lt;br /&gt;        { &lt;br /&gt;            bw.Write(this.fileBytes); &lt;br /&gt;        } &lt;br /&gt;    }&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;Über den fertigen Service habe ich dann einen Expression Builder gebaut. Als Einstiegspunkt dient die Methode &lt;em&gt;Write(Action&amp;lt;FileNameExpression&amp;gt; expression)&lt;/em&gt;. Der Expression Builder sieht wie folgt aus:&lt;/p&gt;&lt;br /&gt;&lt;pre class=&quot;brush: csharp; auto-links: true; collapse: false; first-line: 1; gutter: true; html-script: false; light: false; ruler: true; smart-tabs: true; tab-size: 4; toolbar: true;&quot;&gt;public class FileExpression &lt;br /&gt;{ &lt;br /&gt;    private readonly IFileService Service; &lt;br /&gt;&lt;br /&gt;    public FileExpression(IFileService service) &lt;br /&gt;    { &lt;br /&gt;        Service = service; &lt;br /&gt;    } &lt;br /&gt;&lt;br /&gt;    public FileExpression File(byte[] bytes) &lt;br /&gt;    { &lt;br /&gt;        this.Service.FileContent(bytes); &lt;br /&gt;        return this; &lt;br /&gt;    } &lt;br /&gt;&lt;br /&gt;    public FileSaveAction Named(string filename) &lt;br /&gt;    { &lt;br /&gt;        return new FileSaveAction(this.Service, filename); &lt;br /&gt;    } &lt;br /&gt;} &lt;/pre&gt;&lt;br /&gt;&lt;p&gt;Der Expression Builder nimmt die spätere Datei als byte[] in der Methode &lt;em&gt;File(byte[])&lt;/em&gt; und den Dateinamen in der Methode &lt;em&gt;Named(string)&lt;/em&gt; entgegen. Die Expression wird schließlich mit einer entsprechenden &lt;em&gt;FileSaveAction&lt;/em&gt; beendet. Diese nimmt den vorher festgelegten Namen sowie das byte[] entgegen und schreibt es via &lt;em&gt;ToDisc()&lt;/em&gt; mittels unterlegtem Service auf die Festplatte.&lt;/p&gt;&lt;br /&gt;&lt;pre class=&quot;brush: csharp; auto-links: true; collapse: false; first-line: 1; gutter: true; html-script: false; light: false; ruler: true; smart-tabs: true; tab-size: 4; toolbar: true;&quot;&gt;public class FileSaveAction &lt;br /&gt;{ &lt;br /&gt;    private readonly IFileService service; &lt;br /&gt;&lt;br /&gt;    private readonly string filename; &lt;br /&gt;&lt;br /&gt;    public FileSaveAction(IFileService service, string filename) &lt;br /&gt;    { &lt;br /&gt;        this.service = service; &lt;br /&gt;        this.filename = filename; &lt;br /&gt;    } &lt;br /&gt;&lt;br /&gt;    public void ToDisc() &lt;br /&gt;    { &lt;br /&gt;        this.service.ToFile(filename); &lt;br /&gt;    } &lt;br /&gt;} &lt;/pre&gt;&lt;br /&gt;&lt;p&gt;Der Aufruf zum Speichern der Datei wird dann im Code folgendermaßen zusammengesetzt. &lt;/p&gt;&lt;br /&gt;&lt;pre class=&quot;brush: csharp; auto-links: true; collapse: false; first-line: 1; gutter: true; html-script: false; light: false; ruler: true; smart-tabs: true; tab-size: 4; toolbar: true;&quot;&gt;IFileService fileService = new FileService();&lt;br /&gt;fileService.Write(delegate(FileExpression x) &lt;br /&gt;    { &lt;br /&gt;        x.File(queryResult.Content).Named(queryResult.SuggestedFileName)).ToDisc(); &lt;br /&gt;    }); &lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;An der einen oder anderen Stelle kann nochmal ein Refactoring angesetzt werden, aber hey! Jetzt soll noch einmal jemand sagen, dass C# unter .Net 2.0 nicht auch schon spannend wäre! :-)&lt;/p&gt;  </description><link>http://jcselke.blogspot.com/2010/05/ist-der-entwicklerspa-mit-c-20-vorbei.html</link><author>noreply@blogger.com (Jan Christian Selke)</author><thr:total>2</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-5601714198208780275.post-7864052288903926756</guid><pubDate>Sun, 02 May 2010 12:38:00 +0000</pubDate><atom:updated>2010-05-02T05:38:00.646-07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Entwicklung</category><category domain="http://www.blogger.com/atom/ns#">StructureMap</category><title>Geplante Neuerungen in StructureMap 3.0</title><description>&lt;p&gt;Voraussichtlich noch diesen Monat wird es die Version 3.0 von StructureMap geben.&lt;/p&gt;  &lt;p&gt;&lt;a href=&quot;http://codebetter.com/blogs/jeremy.miller/&quot; target=&quot;_blank&quot;&gt;Jeremy D. Millers&lt;/a&gt; &lt;a href=&quot;http://groups.google.com/group/structuremap-users/browse_thread/thread/c94ca43569ca25bc&quot; target=&quot;_blank&quot;&gt;eigenem Bekunden&lt;/a&gt; zu folgen, sind die beiden Highlights der neuen Version&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;das Löschen &lt;em&gt;aller obsoleten &lt;/em&gt;Methoden,&lt;/li&gt;    &lt;li&gt;verbesserter Support für &lt;em&gt;nested containers.&lt;/em&gt;&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Dem möchte ich noch das verbesserte &lt;em&gt;object tracking &lt;/em&gt;hinzufügen. Ebenfalls interessant klingen &lt;em&gt;On StartUp Actions, &lt;/em&gt;auch wenn&lt;em&gt;&amp;#160;&lt;/em&gt;mir noch nicht ganz klar ist, was genau darunter zu verstehen ist…&lt;/p&gt;  &lt;p&gt;Wer sich dafür interessiert, kann die vollständigen Release Plans bei &lt;a href=&quot;http://wiki.github.com/structuremap/structuremap/30-release-plans&quot; target=&quot;_blank&quot;&gt;github&lt;/a&gt; einsehen.&lt;/p&gt;  </description><link>http://jcselke.blogspot.com/2010/05/geplante-neuerungen-in-structuremap-30.html</link><author>noreply@blogger.com (Jan Christian Selke)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-5601714198208780275.post-2002947900156065853</guid><pubDate>Fri, 30 Apr 2010 19:55:00 +0000</pubDate><atom:updated>2010-04-30T12:55:16.609-07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Artikel</category><category domain="http://www.blogger.com/atom/ns#">Entwicklung</category><category domain="http://www.blogger.com/atom/ns#">OpenXml SDK</category><category domain="http://www.blogger.com/atom/ns#">VSTO</category><category domain="http://www.blogger.com/atom/ns#">Word 2007</category><title>Artikel in der Visual Studio One</title><description>&lt;p&gt;Heute ist es soweit! Mein Artikel zum Thema Open Xml mit dem Titel “Word-Dokumente am laufenden Band” wurde in der aktuellen Ausgabe 03/2010 der &lt;a href=&quot;http://www.visualstudio1.de/&quot; target=&quot;_blank&quot;&gt;Visual Studio One&lt;/a&gt; Ausgabe abgedruckt.&lt;/p&gt;  &lt;p&gt;Ein kurzer Teaser meines Artikels kann &lt;a href=&quot;http://www.codegemini.net/download/teaser_selke.pdf/&quot; target=&quot;_blank&quot;&gt;hier&lt;/a&gt; eingesehen werden.&lt;/p&gt;  &lt;p&gt;Alle, denen der Artikel gefallen hat, dürfen sich gerne an der &lt;a href=&quot;http://polldaddy.com/poll/3098044/&quot; target=&quot;_blank&quot;&gt;laufenden Umfrage&lt;/a&gt; der Visual Studio One beteiligen und dafür abstimmen. ;-)&lt;/p&gt;  </description><link>http://jcselke.blogspot.com/2010/04/artikel-in-der-visual-studio-one.html</link><author>noreply@blogger.com (Jan Christian Selke)</author><thr:total>0</thr:total></item></channel></rss>