tag:blogger.com,1999:blog-80341715429010026252024-03-12T18:38:11.370-07:00Nette SoftwareSoftwareentwicklung in .NETAnonymoushttp://www.blogger.com/profile/12930288690417317478noreply@blogger.comBlogger6125tag:blogger.com,1999:blog-8034171542901002625.post-71563204960059635492012-10-22T02:18:00.001-07:002012-10-22T02:18:19.617-07:00MonoTouch/Mono for Android: Windows-1252 kodierte Texte lesen und schreiben<p>Eines der am nervigsten Themen mit denen man sich beim schreiben von Software rumschlagen muss ist aus meiner Sicht das Thema <strong>Encoding</strong>. Ich weiß nicht mehr wann ich das erste mal so richtig mit den Problemen konfrontiert wurde, aber es ist gefühlt eine halbe Ewigkeit. Dank Unicode und Co. werden die Probleme bei neuer Software zwar weniger, aber es kommt immer wieder die Situation in denen man Daten einlesen muss welche nicht entsprechend kodiert sind.</p> <p>Als .NET Entwickler hat man durch die Klasse <a href="http://msdn.microsoft.com/en-us/library/system.text.encoding(v=vs.110).aspx" target="_blank">System.Text.Encoding</a> allerdings eine ganz gute Waffe in der Hand um mit den verschiedenen Kodierungen umzugehen. Die Sache wird aber dann wieder “interessanter” wenn verschiedene Plattformen wie z.B. MonoTouch oder Mono for Android im Spiel sind.</p> <p>In meinem Fall muss ich Daten verarbeiten die mit einem Delphi Programm erzeugt werden. Da der Quellcode der Software vorhanden ist konnte ich sehen, dass die Daten mit der Standard Windows Codepage geschrieben werden (und da die Software nur im deutschsprachigen Raum verwendet wird kann man <strong>Windows-1252 Westeuropäisch</strong> als gegeben nehmen). Für den neuen .NET Code bin ich also ganz naiv davon ausgegangen das ich mit <a href="http://msdn.microsoft.com/en-us/library/system.text.encoding.default.aspx" target="_blank">System.Text.Encoding.Default</a> zum Ziel komme. Das war anfangs auch der Fall. Da die Delphi Software auch immer das Default Encoding verwendet kam es nie zu Problemen.</p> <p><strong><font size="3">Das Problem</font></strong></p> <p>Jetzt soll der .NET Code aber auch auf Plattformen wie iOS und Android laufen. Ist ja danke MonoTouch und Mono for Android kein Problem. Nur leider unterscheidet sich das <strong>Default-Encoding</strong> dieser Plattformen von dem von Windows. Auf beiden wird <strong>UTF-8</strong> verwendet:</p> <p><strong>MonoTouch</strong></p> <p><a href="http://lh5.ggpht.com/-k13PY2VkI2w/UIUPHQSWVvI/AAAAAAAAAmw/9Ru4xixc-O8/s1600-h/Screen-Shot-2012-10-22-at-10.05.4911.png"><img style="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" title="MonoTouch" border="0" alt="UTF-8 Encoding von MonoTouch" src="http://lh6.ggpht.com/-2bsiq1MztkI/UIUPITqnH3I/AAAAAAAAAm0/n4uNCgA1O1s/Screen-Shot-2012-10-22-at-10.05.49_t.png?imgmax=800" width="494" height="100"></a></p> <p><strong>Mono for Android</strong></p> <p><a href="http://lh5.ggpht.com/-pfXxwTg2GCc/UIUPJUVi2TI/AAAAAAAAAnA/sL8kGLutQPE/s1600-h/mono4android7.png"><img style="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" title="mono4android" border="0" alt="mono4android" src="http://lh4.ggpht.com/-iuRvoxIsKcE/UIUPKr7MfVI/AAAAAAAAAnI/xkNvu7jqwSU/mono4android_thumb5.png?imgmax=800" width="438" height="85"></a></p> <p>Werden die Daten nun mit dem Default-Encoding verarbeitet, dann klappt das bei einigen Zeichen noch ganz gut, aber spätestens wenn Steuerzeichen ins Spiel kommen geht das ganze schief.</p> <p><font size="3"><strong>Die Lösung</strong></font></p> <p>Die Lösung für dieses Problem ist eigentlich ganz einfach: Man besorgt sich das richtige Encoding. In meinem Fall <strong>Windows-1252 Westeuropäisch</strong>. Das geht unter .NET/Mono ganz einfach mit folgendem Einzeiler:</p> <p><font face="Courier New">var encoding = Encoding.GetEncoding(1252);</font></p> <p>Wenn man dieses Encoding jetzt an alle Lese und Schreib Methoden übergibt, dann klappt es auch wieder mit den Steuerzeichen.</p> <div id="codeSnippetWrapper"> <div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum1"> 1:</span> var encoding = Encoding.GetEncoding(1252);</pre><!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum2"> 2:</span> </pre><!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum3"> 3:</span> File.ReadAllText(<span style="color: #006080">@"C:\Temp\text.txt"</span>, encoding);</pre><!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum4"> 4:</span> </pre><!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum5"> 5:</span> File.WriteAllText(<span style="color: #006080">@"C:\Temp\text.txt"</span>, <span style="color: #006080">"content"</span>,encoding);</pre><!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum6"> 6:</span> </pre><!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum7"> 7:</span> var sr = <span style="color: #0000ff">new</span> StreamReader(<span style="color: #006080">@"C:\Temp\text.txt"</span>, encoding);</pre><!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum8"> 8:</span> </pre><!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum9"> 9:</span> var sw = <span style="color: #0000ff">new</span> StreamWriter(<span style="color: #0000ff">new</span> MemoryStream(), encoding);</pre><!--CRLF--></div></div><br /><p><font size="3"><strong>Ein weiteres Problem</strong></font></p><br /><p>Das Ganze hat dann unter Mono for Android auch gleich funktioniert (zumindest sah es so aus) und ich war mir sicher das es unter MonoTouch auch so sein wird. Hier wurde ich aber gleich eines besseren belehrt:</p><br /><p><a href="http://lh6.ggpht.com/-Han4KESl3nE/UIUPMFe00KI/AAAAAAAAAnM/Wu0GGPVHrtE/s1600-h/Exception%252520MT%25255B8%25255D.png"><img style="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" title="Exception MT" border="0" alt="Exception MT" src="http://lh3.ggpht.com/-FEoY-JfV0Mc/UIUPNXFsCAI/AAAAAAAAAnY/RjZwMUOo6Gs/Exception%252520MT_thumb%25255B4%25255D.png?imgmax=800" width="644" height="225"></a></p><br /><br /><p>Die Codepage wurde nicht gefunden <img style="border-bottom-style: none; border-left-style: none; border-top-style: none; border-right-style: none" class="wlEmoticon wlEmoticon-sadsmile" alt="Trauriges Smiley" src="http://lh4.ggpht.com/-xMeID7DmZAM/UIUPOrjgY5I/AAAAAAAAAng/goDzfeAY-g0/wlEmoticon-sadsmile%25255B2%25255D.png?imgmax=800"></p><br /><p>Nach ein bisschen suchen in den Projekteinstellungen und bei Google bin ich auf folgende Settings-Page gestoßen:</p><br /><p><a href="http://lh3.ggpht.com/-0_J1A59TAvI/UIUPQFIF2dI/AAAAAAAAAno/AJsgzQSpykM/s1600-h/monotouch_settings%25255B11%25255D.png"><img style="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" title="monotouch_settings" border="0" alt="monotouch_settings" src="http://lh4.ggpht.com/-4ZcfUMQDZ28/UIUPRnoYVeI/AAAAAAAAAnw/a2mAUtrhfPc/monotouch_settings_thumb%25255B5%25255D.png?imgmax=800" width="644" height="437"></a></p><br /><br /><br /><p>Hier kann man angeben welche Encodings mit in den Build integriert werden sollen. Diese werden nur bei explizit integriert um die Anwendung kleiner zu halten. Eine Liste mit den Encodings gibt es bei Xamarin: <a href="http://docs.xamarin.com/ios/advanced_topics/internationalization">http://docs.xamarin.com/ios/advanced_topics/internationalization</a></p><br /><p><font size="3"><strong>Mono for Android schlägt zurück</strong></font></p><br /><p>Wie oben schon geschrieben sah es bei Mono for Android leider nur so aus, als ob es ohne Probleme funktioniert. Ich habe das ganze leider nur im Debug Build getestet. Und hier schlägt eine Eigenart von Mono for Android zu. Bei Debug Builds wird die Shared Runtime von Mono for Android verwendet. In dieser sind alle Encodings integriert. Bei Release Builds hingegen wird die Mono Runtime mit der App in das Package gelinkt. Und hier gilt nun das selbe wie bei MonoTouch: Die verfügbaren Encodings müssen explizit hinzugefügt werden.</p><br /><p><strong>Visual Studio</strong></p><br /><p><a href="http://lh6.ggpht.com/-YCk20Gsj00c/UIUPSTkzHsI/AAAAAAAAAn0/3lm7pgiF0Yk/s1600-h/M4A%252520Win%25255B3%25255D.png"><img style="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" title="M4A Win" border="0" alt="M4A Win" src="http://lh3.ggpht.com/-6Txy6vL4scI/UIUPTV-gSoI/AAAAAAAAAoA/CCO300lePf0/M4A%252520Win_thumb%25255B1%25255D.png?imgmax=800" width="644" height="302"></a></p><br /><p><strong>MonoDevelop</strong></p><br /><p><a href="http://lh4.ggpht.com/-whE_qCHfeLs/UIUPUelVWPI/AAAAAAAAAoI/ikuAiiuwM70/s1600-h/M4A%252520Mac%25255B3%25255D.png"><img style="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" title="M4A Mac" border="0" alt="M4A Mac" src="http://lh3.ggpht.com/-1ntk6oMz0CE/UIUPWONRonI/AAAAAAAAAoQ/5VIXPIy1at4/M4A%252520Mac_thumb%25255B1%25255D.png?imgmax=800" width="644" height="443"></a></p><br /><p><font size="4">Fazit</font></p><br /><p>Nach der ganzen Aktion weiß ich wieder warum ich <a href="http://www.getdigital.de/products/scheiss_encoding" target="_blank">dieses T-Shirt</a> besitze.<br>Grundsätzlich muss ich sagen, dass der Umgang mit verschiedenen Zeichenkodierungen für mich noch nie so komfortabel wie mit .NET war. Das ganze aber mal wieder “interessant” geworden ist, als MonoTouch bzw. Mono for Android mit gespielt haben. Das soll keine Kritik an Xamarin sein, da ihr vorgehen hier vollkommen legitim ist um die Größe der Anwendung zu reduzieren. </p><br /><p>Ansonsten empfehle ich noch jedem Entwickler diesen Blogeintrag von Joel Spolsky zu lesen:</p><br /><h4><a href="http://www.joelonsoftware.com/articles/Unicode.html" target="_blank"><font style="font-weight: normal">The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets (No Excuses!)</font></a></h4> Anonymoushttp://www.blogger.com/profile/12930288690417317478noreply@blogger.com0tag:blogger.com,1999:blog-8034171542901002625.post-42443957417255956152012-03-03T05:17:00.001-08:002012-03-03T12:19:20.813-08:00Monotouch - Eigene Views im Interface Builder verwendenAuch wenn man, so wie ich, kein großer Freund von Apples Interface Builder ist, so hat es gelegentlich doch einen gewissen Charme User Interfaces für iOS Geräte "mal kurz zusammen zu klicken". <br />
Wenn man nur die Standard Elemente, wie Button, WebView usw. verwendet, dann ist das alles auch ganz schnell gemacht. <br />
<br />
Interessanter wird das ganze, wenn man eine eigene View verwenden möchte.<br />
<h4>
Erstellen einer Custom View</h4>
Wichtig bei einer <b>Custom View</b> sind die zwei folgende Eigenschaften: <br />
<ul>
<li>Das Register Attribut auf der Klasse </li>
<li>Ein Constructor mit folgender Signatur: <span style="font-family: 'Courier New';">.ctor(IntrPtr handle) : base(handle)</span></li>
</ul>
<div id="codeSnippetWrapper">
<div id="codeSnippet" style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;">
<pre style="background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"><span id="lnum1" style="color: #606060;"> 1:</span> [Register(<span style="color: #006080;">"MyView"</span>)]</pre>
<pre style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"><span id="lnum2" style="color: #606060;"> 2:</span> <span style="color: blue;">public</span> <span style="color: blue;">class</span> MyView : UIView</pre>
<pre style="background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"><span id="lnum3" style="color: #606060;"> 3:</span> {</pre>
<pre style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"><span id="lnum4" style="color: #606060;"> 4:</span> <span style="color: blue;">public</span> MyView(IntPtr handle)</pre>
<pre style="background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"><span id="lnum5" style="color: #606060;"> 5:</span> :<span style="color: blue;">base</span>(handle)</pre>
<pre style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"><span id="lnum6" style="color: #606060;"> 6:</span> {</pre>
<pre style="background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"><span id="lnum7" style="color: #606060;"> 7:</span> <span style="color: blue;">this</span>.Initialize();</pre>
<pre style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"><span id="lnum8" style="color: #606060;"> 8:</span> }</pre>
<pre style="background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"><span id="lnum9" style="color: #606060;"> 9:</span> </pre>
<pre style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"><span id="lnum10" style="color: #606060;"> 10:</span> <span style="color: blue;">private</span> <span style="color: blue;">void</span> Initialize()</pre>
<pre style="background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"><span id="lnum11" style="color: #606060;"> 11:</span> {</pre>
<pre style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"><span id="lnum12" style="color: #606060;"> 12:</span> <span style="color: green;">// Initialization Code</span></pre>
<pre style="background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"><span id="lnum13" style="color: #606060;"> 13:</span> }</pre>
<pre style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"><span id="lnum14" style="color: #606060;"> 14:</span> }</pre>
</div>
</div>
<br />
<h4>
Verwendung im Interface Builder</h4>
Wenn die eigene View erfolgreich compiliert ist es Zeit den <strong>Interface Builder</strong> zu starten.<br />
<br />
Hier zieht man dann ein View Element aus der <strong>Object Library</strong> auf seine View und positioniert dieses an der richtigen Stelle.<br />
<img alt="SelectView" border="0" height="233" src="http://lh4.ggpht.com/-9qXiac9dS74/T1IYjBLtVmI/AAAAAAAAAHc/tf_ZiTKui9Q/SelectView%25255B7%25255D.png?imgmax=800" style="background-image: none; border-bottom-width: 0px; border-left-width: 0px; border-right-width: 0px; border-top-width: 0px; display: block; float: none; margin-left: auto; margin-right: auto; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="SelectView" width="244" /> <br />
<br />
Damit die eigene View verwendet wird muss man nur noch den Namen der Klasse im<strong> Identity Inspector</strong> setzen.<br /><img alt="IdentityInspector" border="0" height="162" src="http://lh5.ggpht.com/-GlbjXv8kok4/T1IYj7I7SCI/AAAAAAAAAHk/aYO2Qwj08lE/IdentityInspector%25255B3%25255D.png?imgmax=800" style="background-image: none; border-bottom-width: 0px; border-left-width: 0px; border-right-width: 0px; border-top-width: 0px; display: block; float: none; margin-left: auto; margin-right: auto; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="IdentityInspector" width="244" /> <br />
<br />
Abschließend legt man noch ein Outlet für die View an und kann die eigene View wie alle anderen Views im Code verwenden.<br />
<br />
<a href="http://lh4.ggpht.com/-NFfnjdvIX14/T1IYlJEJo-I/AAAAAAAAAHs/csAYBniD3pI/s1600-h/Outlet%25255B3%25255D.png"><img alt="Outlet" border="0" height="264" src="http://lh3.ggpht.com/-BC2nVA78FY8/T1IYlwtVOYI/AAAAAAAAAHw/Z60JdQwZ05g/Outlet_thumb%25255B1%25255D.png?imgmax=800" style="background-image: none; border-bottom-width: 0px; border-left-width: 0px; border-right-width: 0px; border-top-width: 0px; display: inline; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="Outlet" width="661" /></a><br />
<br />
<br />Anonymoushttp://www.blogger.com/profile/12930288690417317478noreply@blogger.com0Ulm, Deutschland48.39091404578955 9.99618530273437548.306584045789549 9.8382568027343744 48.475244045789552 10.154113802734376tag:blogger.com,1999:blog-8034171542901002625.post-13297934359160254842012-01-20T10:38:00.000-08:002012-01-20T23:58:52.659-08:00Visual Studio durch eine RAM Disk beschleunigen<p><br>Heute hat mich mein Visual Studio mal wieder durch eine quälende Langsamkeit genervt. Oft gibt sich das nach ein paar Minuten und man kann normal damit arbeiten. Also habe ich mich dann mal auf Ursachen begeben. Die ersten verdächtigen sind dabei immer die Add-Ins und Extension die so installiert sein. Und nachdem mich <a href="http://visualstudiogallery.msdn.microsoft.com/bc7a433b-b594-48d4-bba2-a2f24774d02f" target="_blank">Visual Studio Achievments</a> als “Extensions Junkie Deluxe” bezeichnet hat, sollte da eigentlich auch Potential da sein und 1-2 Extensions können wahrscheinlich fliegen. Das hat leider auch nicht den gewünschten Erfolg gebracht und ich musste weiter suchen. Nach ein paar Minuten fiel mein Verdacht auf <a href="http://www.ncrunch.net/" target="_blank">NCrunch</a> und <a href="http://www.jetbrains.com/resharper/" target="_blank">Resharper</a>. Beides auf jeden Fall Tools auf die ich nicht verzichten möchte.<br>NCrunch selbst hat mich dann auf eine gute Idee gebracht: Der Einsatz einer RAM Disk.<br><br></p> <p><a href="http://lh5.ggpht.com/-pPnK8arcrXs/TxmyiPtPw6I/AAAAAAAAAFQ/d6fmov62_mA/s1600-h/image%25255B3%25255D.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto; padding-top: 0px" title="image" border="0" alt="image" src="http://lh6.ggpht.com/-GRmUABC7uNw/Txmyi47J3MI/AAAAAAAAAFU/9_CdIDrYtgM/image_thumb%25255B1%25255D.png?imgmax=800" width="646" height="106"></a><br></p> <h3>Ram Disk konfigurieren</h3> <p>Nach ein bisschen suchen im Internet bin ich auf <a href="http://memory.dataram.com/products-and-services/software/ramdisk" target="_blank">DataRam RAMDisk</a>. Die ist für Ram Disks bis zu 4GB kostenlos und läuft auch unter 64-Bit Systemen. Des weiteren lässt sich die Ram Disk so konfigurieren dass der Inhalt beim herunterfahren gesichert und bei nächsten Start wieder geladen wird.<br>Die Ram Disk lässt sich nach der Installation über das mitgelieferte <strong>Configuration Utility</strong> einstellen. Neben der Größe kann hier eingestellt werden ob die Disk sich direkt als FAT16 oder FAT32 Partition melden soll.<br><br></p> <p><a href="http://lh4.ggpht.com/-8VjB55FjBOA/TxmyjZYZOBI/AAAAAAAAAFc/nLMcQa1AV-M/s1600-h/image%25255B7%25255D.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto; padding-top: 0px" title="image" border="0" alt="image" src="http://lh4.ggpht.com/-WqpGMfuE3MQ/TxmykRZ5TxI/AAAAAAAAAFo/azeSH_RSrQA/image_thumb%25255B3%25255D.png?imgmax=800" width="531" height="434"></a><br><br>Da ich NTFS auf der Disk verwenden möchte habe ich mich für <strong>Unformated</strong> entschieden und die Disk direkt unter Windows partitioniert und mit NTFS formatiert. Damit ich das nicht nach jedem Neustart durchführen muss lass ich die Disk beim herunterfahren sichern:<br><br><a href="http://lh5.ggpht.com/-9yvK4M_22Fo/Txmyk4OcKTI/AAAAAAAAAFs/Gc7utYJ0c5g/s1600-h/image%25255B12%25255D.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto; padding-top: 0px" title="image" border="0" alt="image" src="http://lh6.ggpht.com/-6de-QxI7WYA/TxmylhdirHI/AAAAAAAAAF0/uXwZdYFi11Q/image_thumb%25255B6%25255D.png?imgmax=800" width="534" height="438"></a><br></p> <h3>NCrunch konfigurieren</h3> <p>Damit NCrunch jetzt auch auf der Ram Disk arbeitet muss es noch konfiguriert werden. Dafür setzt man unter <strong>NCrunch –> Configuration</strong> den <strong>WorkspacePath</strong> auf ein Verzeichnis auf der Ram Disk.</p> <p><a href="http://lh4.ggpht.com/-sU0pi2kHcfw/TxpwMJoprkI/AAAAAAAAAGg/p3TZshzxG7Q/s1600-h/image%25255B4%25255D.png"><img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh4.ggpht.com/-kIeJhN0j834/TxpwM29eI5I/AAAAAAAAAGk/VBhYp0hG4eU/image_thumb%25255B1%25255D.png?imgmax=800" width="475" height="389"></a></p> <h3>Resharper konfigurieren</h3> <p>Beim Resharper gestaltet sich die Sache leider etwas schwieriger. Hier hat man nur die Möglichkeiten das dieser seine Meta-Daten entweder direkt bei der Solution abspeichert oder aber dem TEMP Verzeichnis.</p> <p><a href="http://lh3.ggpht.com/-8qlIn6tKX2w/TxpwNgn-KQI/AAAAAAAAAGs/K2IrVb-4h00/s1600-h/image%25255B9%25255D.png"><img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh6.ggpht.com/-fc4DL1RKFd8/TxpwOnmpmBI/AAAAAAAAAG4/8vsG0L523RM/image_thumb%25255B4%25255D.png?imgmax=800" width="546" height="284"></a></p> <p>Da ich meinen Source Code aber nicht in der Ram Disk halten möchte bleibt mir nur die Möglichkeit mein TEMP Verzeichnis zu verlegen.</p> <h3>TEMP Verzeichnis verlegen</h3> <p>Jetzt muss nur noch das TEMP Verzeichnis auf die Ram Disk verlegt werden. Das wird im Bereich <strong>Umgebungsvariablen…</strong> in den <strong>Erweiterten Systemeinstellungen</strong> gemacht<br><br><a href="http://lh6.ggpht.com/-ktviOwGvPZQ/TxmymUIz0FI/AAAAAAAAAGA/88FYG7hyJp4/s1600-h/image%25255B23%25255D.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto; padding-top: 0px" title="image" border="0" alt="image" src="http://lh5.ggpht.com/-Bdc9_zVw9N4/TxmynjLRS0I/AAAAAAAAAGI/bhUQh6EqqEM/image_thumb%25255B11%25255D.png?imgmax=800" width="552" height="595"></a><br><br>Dort legt man die beiden Variable <strong>TEMP</strong> und <strong>TMP</strong> auf einen Pfad auf der Ram Disk. Hier sollte man aufpassen das man nicht direkt das Wurzelverzeichnis nimmt, da wohl einige Programme damit nicht klar kommen<br><br></p> <h2><a href="http://lh3.ggpht.com/-IYePmVH-zG0/TxmyoY7YFWI/AAAAAAAAAGM/pVR6xoZZ0BU/s1600-h/image%25255B29%25255D.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto; padding-top: 0px" title="image" border="0" alt="image" src="http://lh4.ggpht.com/-trkCpKk9x74/Txmyo3H79XI/AAAAAAAAAGU/ccTrtHF1l0A/image_thumb%25255B15%25255D.png?imgmax=800" width="319" height="193"></a></h2> <h3> </h3><br> <h2></h2> <h1>Fazit</h1>Nach ein paar Stunden muss ich sagen, dass ich echt glücklich mit der Lösung bin. Visual Studio lahmt zwar immer noch hin und wieder, aber alles im allem rennt das ganze sehr gut. Anfangs war ich zwar etwas skeptisch, da dass TEMP Verzeichnis ursprünglich auf einer SSD lag und ich mir nicht all zu viel von dem verschieben erhofft hab, aber ich wurde eines besseren belehrt. Anonymoushttp://www.blogger.com/profile/12930288690417317478noreply@blogger.com0tag:blogger.com,1999:blog-8034171542901002625.post-67436073079021133992011-09-22T02:44:00.000-07:002011-09-22T02:49:45.980-07:00Darstellung von WPF AnwendungenWPF Anwendungen haftet immer noch der Ruf an, dass diese "irgendwie komisch" aussehen. Dies liegt vor allem an der Art und Weise wie WPF Text darstellt (vgl. <a href="http://megos.wordpress.com/2008/09/27/die-geschichte-vom-unscharfen-text/">Die Geschichte vom unscharfen Text</a> oder <a href="http://social.msdn.microsoft.com/forums/en-US/wpf/thread/30a818cb-521f-412c-bc11-310d35832594/">Fonts in WPF seem blurry</a>) Wenn man ein Windows ab Vista verwendet bessert sich das ganze ein bisschen, aber auch hier sehen die Schriften alle nicht wirklich scharf aus (vgl. <a href="http://megos.wordpress.com/2009/09/26/alles-wird-unscharf/">Alles wird unscharf</a>).<br />
<br />
Das ein WPF Anwendung nicht zwangsläufig "unscharf" und "komisch" aussehen muss, sieht man an Visual Studio 2010. Das hatte zwar zu Beta Zeiten auch das Problem, aber nach genug Kritik aus Entwicklerkreisen hat Microsoft es dann doch geschaft eine "scharfe" Version von Visual Studio 2010 auf den Markt zu bekommen.<br />
<br />
Dafür hat Microsoft ein paar Anpassungen im WPF Text Stack (vgl. <a href="http://blogs.msdn.com/b/text/archive/2009/08/24/wpf-4-0-text-stack-improvements.aspx">WPF 4.0 Text Stack Improvements</a>) vorgenommen. Leider sind diese Anpassungen nicht per Default für WPF Anwendungen verfügbar. Auch wenn man einen neue Anwendung entwickelt sind diese nicht von Haus aus eingestellt.<br />
<br />
Nach ein bisschen herumspielen haben sich für mich die folgenden Einstellungen als gut herraus gestellt:<br />
<br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="color: blue;"><</span><span class="Apple-style-span" style="color: #cc0000;">Window </span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="color: red;">TextOptions.TextFormattingMode</span><span class="Apple-style-span" style="color: blue;">="Display"</span> </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="color: red;">SnapsToDevicePixels</span><span class="Apple-style-span" style="color: blue;">="True"</span> </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="color: red;">UseLayoutRounding</span><span class="Apple-style-span" style="color: blue;">="True" /></span></span><br />
<span class="Apple-style-span" style="color: blue; font-family: 'Courier New', Courier, monospace;"><br />
</span><br />
Die folgenden Bilder zeigen den Unterschied. Auf der linken Seite werden die Controls mit den Standardeinstellungen angezeigt. Auf der rechten Seite mit den obigen Einstellungen:<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgejKj9ysqyBxWNplJTMnR8Q9qlhbtE3QVRZ0bcQpBKaiP4CsWKGFCSXfLRFsj157biZUfKqJ9DefYiizksO8IecaCG_oGf4aDARJkwAGMniixQKWYpo3e-cFnDBLEnWTbz0O5t6Yo3M1w/s1600/XP+Classic.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgejKj9ysqyBxWNplJTMnR8Q9qlhbtE3QVRZ0bcQpBKaiP4CsWKGFCSXfLRFsj157biZUfKqJ9DefYiizksO8IecaCG_oGf4aDARJkwAGMniixQKWYpo3e-cFnDBLEnWTbz0O5t6Yo3M1w/s1600/XP+Classic.png" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Windows XP mit Classic Theme</td></tr>
</tbody></table><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiOC28HPVs9ruF-EpTzCUTgKJ0RynOYoISNYo3yYEBMklkvjfPPMu0ffZgIn7yN-sfKMBDfQlOFZwUKZW3DJMTUv90ZbEFfz0kG3uIkgliaE9jYNZN4nKx66kgZ0H-L_LCw7SDrHYwnwIU/s1600/XP+Luna.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiOC28HPVs9ruF-EpTzCUTgKJ0RynOYoISNYo3yYEBMklkvjfPPMu0ffZgIn7yN-sfKMBDfQlOFZwUKZW3DJMTUv90ZbEFfz0kG3uIkgliaE9jYNZN4nKx66kgZ0H-L_LCw7SDrHYwnwIU/s1600/XP+Luna.png" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Windows XP mit Luna Theme</td></tr>
</tbody></table><br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg60RL0Azndi5nFStQhDmA4O6svGrbVMYxeT85NFYqqyr6EnV6X7ayouW9FEyIg2MtB4_8ZzfziuC-nX9yHTQh8kWfovJNJKmoM5qELpLHEEeRPmKDoh8UcY7xGbiKy30wYgdlAzlDH2VI/s1600/Windows+7+Aero.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg60RL0Azndi5nFStQhDmA4O6svGrbVMYxeT85NFYqqyr6EnV6X7ayouW9FEyIg2MtB4_8ZzfziuC-nX9yHTQh8kWfovJNJKmoM5qELpLHEEeRPmKDoh8UcY7xGbiKy30wYgdlAzlDH2VI/s1600/Windows+7+Aero.png" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Windows 7 mit Aero Theme</td></tr>
</tbody></table>Das Demo Programm selbst kann <a href="http://dl.dropbox.com/u/10297619/WpfDisplay.zip">hier</a> herunter geladen werden.Anonymoushttp://www.blogger.com/profile/12930288690417317478noreply@blogger.com0tag:blogger.com,1999:blog-8034171542901002625.post-6005272612051849822011-08-09T01:25:00.000-07:002011-08-09T01:25:11.767-07:00Erste Schritte beim Entwickeln eines Outlook 2010 Add-ins<span class="Apple-style-span" style="font-family: inherit;">Aktuell schreibe ich gerade mein erstes Add-in für Outlook 2010.</span><br />
<span class="Apple-style-span" style="font-family: inherit;">Der Einstieg ist dank der guten Projektvorlagen von Visual Studio 2010 auch nicht weiter schwer. Einfach ein neues "Outlook 2010 Add-in" anlegen und man kann eigentlich loslegen.</span><br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEguPPx5n2bm7Kb2P6Qnen8XEEEGDM8vACLQ6-Pk0pQIarfppNbEkq9hTYjsgypMpDheOYhyNAOUzIwM59yRDx4MZ0lcaLTxlQcGBYh2sVhtxBMhsX7kt2w9S4PFsJekxz8VsmQwhJ0m_EU/s1600/New+Project_2011-08-09_08-53-48.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="196" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEguPPx5n2bm7Kb2P6Qnen8XEEEGDM8vACLQ6-Pk0pQIarfppNbEkq9hTYjsgypMpDheOYhyNAOUzIwM59yRDx4MZ0lcaLTxlQcGBYh2sVhtxBMhsX7kt2w9S4PFsJekxz8VsmQwhJ0m_EU/s400/New+Project_2011-08-09_08-53-48.jpg" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Visual Studio 2010 - New Project</td></tr>
</tbody></table>Nach dem Anlegen erhält man ein Projekt bei dem eigentlich alles schon konfiguriert ist. Einfach "Start Debugging" wählen und Outlook wird gestartet und das Add-in geladen.<br />
<br />
Seinen eigenen Code kann man in die, von Visual Studio angelegte, Klasse ThisAddIn einfügen.<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjVmCENllDDjvQML3ASTvibmWP_YhWwK__zzX91YvkpaeEpR9kiMRLHPKFeKOnczx4hY65ittEbCY74rS-K8wfBfJjgyO3kPLXeUwR7VJ_JU_Ao_Okaeu9i2JsCWYT2KkwTqGOYZM0OQx0/s1600/OutlookAddIn1+-+Microsoft+Visual+Studio_2011-08-09_09-26-34.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="425" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjVmCENllDDjvQML3ASTvibmWP_YhWwK__zzX91YvkpaeEpR9kiMRLHPKFeKOnczx4hY65ittEbCY74rS-K8wfBfJjgyO3kPLXeUwR7VJ_JU_Ao_Okaeu9i2JsCWYT2KkwTqGOYZM0OQx0/s640/OutlookAddIn1+-+Microsoft+Visual+Studio_2011-08-09_09-26-34.jpg" width="640" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Nach dem Anlegen des Projekts</td></tr>
</tbody></table>Hier hat man jetzt z.B. die Möglichkeit auf verschiedene Events von Outlook zu reagieren. Neben denen, im Screenshot gezeigten, StartUp und Shutdown von ThisAddIn gibt es über this.Application noch einige weitere. Genauere Informationen darüber sind in der <a href="http://msdn.microsoft.com/en-us/library/microsoft.office.interop.outlook.applicationevents_11_event_events.aspx">MSDN (ApplicationEvents_11_Event Events)</a> zu finden.<br />
<br />
<br />
<br />
Anonymoushttp://www.blogger.com/profile/12930288690417317478noreply@blogger.com0tag:blogger.com,1999:blog-8034171542901002625.post-37695238540575621942011-05-25T13:45:00.000-07:002011-08-08T23:02:55.382-07:00NUnit Cheatsheet<span class="Apple-style-span" style="font-family: Verdana, sans-serif;">Frei nach "Ey Mann, wo ist mein Auto?" kann man sagen, dass NUnit ein sehr großes und mächtiges Unittest Framework ist. Und seine Größe wird nur durch seine Mächtigkeit übertroffen.</span><br />
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;"><br />
</span><br />
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;">NUnit ist aber auch sehr gut darin seine Größe und Mächtigkeit zu verbergen. Wenn ich mir die Unittests in meiner Firma gelegentlich so anschaue, dann könnte man meinen NUnit hätte nur die </span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">Assert.AreEqual(...) </span><span class="Apple-style-span" style="font-family: Verdana, sans-serif;">Methode. Eigentlich alle Tests werden über diese Methode realisiert. </span><br />
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;">Man könnte jetzt doch sagen "Hey, ist doch super. Mann muss sich nur diese eine Methode merken und kann Unittests schreiben".</span><br />
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;">Aus Erfahrung habe ich damit aber zwei Probleme:</span><br />
<br />
<ol><li><span class="Apple-style-span" style="font-family: Verdana, sans-serif;">Man schreibt keine Unittests, da man die Bedingung nicht oder nur umständlich mit einer Prüfung auf Gleichheit "erschlagen" kann.</span></li>
<li><span class="Apple-style-span" style="font-family: Verdana, sans-serif;">Unittests werden groß und kryptisch wenn man versucht alles mit </span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">Assert.AreEuqal(...)</span><span class="Apple-style-span" style="font-family: Verdana, sans-serif;"> zu machen.</span></li>
</ol><div><span class="Apple-style-span" style="font-family: Verdana, sans-serif;">Hier passt ein Zitat von Paul Watzlawick ziemlich gut: </span></div><div><span class="Apple-style-span" style="font-family: Verdana, sans-serif;"><br />
</span></div><div><span class="Apple-style-span" style="font-family: Verdana, sans-serif;"><i>"Wer als Werkzeug nur einen Hammer hat, sieht in jedem Problem einen Nagel.</i>"</span></div><div><span class="Apple-style-span" style="font-family: Verdana, sans-serif;"><br />
</span></div><div><span class="Apple-style-span" style="font-family: Verdana, sans-serif;">Und damit man nicht immer mit dem AreEqual-Hammer arbeitet habe ich hier jetzt mal einen kleinen Spickzettel für NUnit zusammen geschrieben.</span></div><div><span class="Apple-style-span" style="font-family: Verdana, sans-serif;"><br />
</span></div><div><span class="Apple-style-span" style="font-family: Verdana, sans-serif;">Prinzipiell hat NUnit zwei API Modelle. Da ist zum einen das bekannte "Classic Model" mit den Assert.Are... Methoden. Zum anderen das "Constraint Model" das mit sogenannten Constraints (deutsch Bedingungen) arbeitet.</span></div><div><span class="Apple-style-span" style="font-family: Verdana, sans-serif;">Ich werde hier nur das "Constraint Model" zeigen, da dies meiner Meinung nach besser lesbar und mächtiger ist.</span><br />
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;"><br />
</span><br />
<span class="Apple-style-span" style="font-family: Verdana, sans-serif; font-size: large;"><b>Cheatsheet</b></span><br />
<br />
<pre class="brush:csharp"> // Vergleich von 2 Objekten
Assert.That("lorem ipsum", Is.EqualTo("lorem ipsum"));
// Vergleich von 2 Zahlen mit absoluter Toleranz
Assert.That(3.14, Is.EqualTo(Math.PI).Within(0.01));
// Vergleich von 2 Zahlen mit relativer Toleranz
Assert.That(3.14, Is.EqualTo(Math.PI).Within(1).Percent);
// Vergleich auf identische Referenz
object o = new object();
object o2 = o;
Assert.That(o, Is.SameAs(o2));
// Vergleich auf Null
object x = null;
Assert.That(x, Is.Null);
// Vergleich auf nicht Null
Assert.That(o, Is.Not.Null);
// Zahl größer als
Assert.That(23, Is.GreaterThan(10));
// Zahl kleiner als
Assert.That(23, Is.LessThan(100));
// Innerhalb eines Bereichs
Assert.That(42, Is.InRange(1, 100));
// ******************************************************
// Strings
// ******************************************************
// Auf konkreten Type Prüfen
Assert.That("lorem", Is.TypeOf<string>());
// Auf substring prüfen
Assert.That("lorem", Contains.Substring("ore"));
// Nicht case sensitiv auf Substring prüfen
Assert.That("lorem", Is.StringContaining("ORE").IgnoreCase);
// Text mit einem regulären Ausdrück überprüfen
Assert.That("lorem ipsum", Is.StringMatching("^lorem\\s"));
// ******************************************************
// Collections
// ******************************************************
string[] values = new string[] { "lorem", "ipsum", "dolor", "sit" };
// Enhält
Assert.That(values, Has.Member("dolor"));
Assert.That(values, Has.Some.EqualTo("dolor"));
// Enhält nicht
Assert.That(values, Has.No.Member("amet"));</pre><br />
</div>Anonymoushttp://www.blogger.com/profile/12930288690417317478noreply@blogger.com0