<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Think First Development</title>
	<atom:link href="http://mentzel.name/feed/" rel="self" type="application/rss+xml" />
	<link>http://mentzel.name</link>
	<description>Erst denken, dann programmieren</description>
	<lastBuildDate>Wed, 28 Jul 2010 20:22:04 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
		<item>
		<title>QuickTipp: ASP.NET MVC2 &amp; Views im Kopfstand</title>
		<link>http://mentzel.name/2010/07/28/quicktipp-asp-net-mvc2-views-im-kopfstand/</link>
		<comments>http://mentzel.name/2010/07/28/quicktipp-asp-net-mvc2-views-im-kopfstand/#comments</comments>
		<pubDate>Wed, 28 Jul 2010 20:20:42 +0000</pubDate>
		<dc:creator>Thomas Mentzel</dc:creator>
				<category><![CDATA[ASP.NET MVC]]></category>
		<category><![CDATA[C#]]></category>

		<guid isPermaLink="false">http://mentzel.name/2010/07/28/quicktipp-asp-net-mvc2-views-im-kopfstand/</guid>
		<description><![CDATA[Das Ermitteln einer View folgt dem Mechanismus “Von Spezialisierten zum Generalisierten”. Das folgende Bild zeigt die Reihenfolge in Kombination mit Areas. Diese Reihenfolge gilt für den Lookup von sowohl Views als auch Partial Views. Das gilt für jedes (!) Lookup, auch innerhalb von Views (z.B. bei Html.RenderPartial()). Diesen Umstand kann man sich zu nutze machen [...]]]></description>
			<content:encoded><![CDATA[<p>Das Ermitteln einer View folgt dem Mechanismus “Von Spezialisierten zum Generalisierten”. Das folgende Bild zeigt die Reihenfolge in Kombination mit <a href="http://mentzel.name/2010/05/31/asp-net-mvc2-areas/" target="_blank">Areas</a>.</p>
<p><img src="http://mentzel.name/wp-content/uploads/2010/05/Mvc2_Page_Lookup.png" /></p>
</p>
<p>Diese Reihenfolge gilt für den Lookup von sowohl Views als auch Partial Views. Das gilt für jedes (!) Lookup, auch innerhalb von Views (z.B. bei Html.RenderPartial()). Diesen Umstand kann man sich zu nutze machen um Polymorphie abzubilden. Gegeben ist folgendes Modell.</p>
<p><a href="http://mentzel.name/wp-content/uploads/2010/07/image4.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://mentzel.name/wp-content/uploads/2010/07/image_thumb4.png" width="244" height="202" /></a> </p>
<p>Damit bietet es sich an, eine Shared View für “Contact” zu erstellen. Aber was passiert mit den Eigenschaften, die nur in den spezialisierten Klassen “Person” und “Company” existieren. Die ContactView ist für die “Contact” Basisklasse typisiert.</p>
<p>An dieser Stelle hilft die Lookup-Reihenfolge. Benutzt man in der Shared View ein RenderPartial(), kann man spezialisierten Views in den Controllern definieren.</p>
<p><a href="http://mentzel.name/wp-content/uploads/2010/07/image5.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://mentzel.name/wp-content/uploads/2010/07/image_thumb5.png" width="548" height="286" /></a> </p>
<p>Das Ergebnis ist, dass im CompanyController zusätzlich die CompanyView “SpecialView” gerendert wird und im PersonController die PersonView “SpezialView”. Es wird also automatisch zuerst in den Views für den Controller nachgeschaut. Einziges Problem mit RenderPartial() ist eine Exception, wenn in einem dritten Controller die “SpezialView” nicht implementiert ist, die ContactView aber gerendert wird.</p>
<p><a href="http://mentzel.name/wp-content/uploads/2010/07/image6.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://mentzel.name/wp-content/uploads/2010/07/image_thumb6.png" width="244" height="146" /></a>&#160; <a href="http://mentzel.name/wp-content/uploads/2010/07/image7.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://mentzel.name/wp-content/uploads/2010/07/image_thumb7.png" width="244" height="150" /></a> </p>
<p>Zu bemerken ist abschließend noch, dass die SpezialViews auf die spezialisierten Klassen typisiert ist, also Person bzw. Company. Das MVC2 Framework übernimmt (vereinfacht dargestellt) die Umwandlung von Contact in Person bzw. Company.</p>
]]></content:encoded>
			<wfw:commentRss>http://mentzel.name/2010/07/28/quicktipp-asp-net-mvc2-views-im-kopfstand/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>QuickTipp: ASP.NET MVC2 &amp; Html.FileFor()</title>
		<link>http://mentzel.name/2010/07/28/quicktipp-asp-net-mvc2-html-filefor/</link>
		<comments>http://mentzel.name/2010/07/28/quicktipp-asp-net-mvc2-html-filefor/#comments</comments>
		<pubDate>Wed, 28 Jul 2010 16:55:38 +0000</pubDate>
		<dc:creator>Thomas Mentzel</dc:creator>
				<category><![CDATA[Allgemeines]]></category>

		<guid isPermaLink="false">http://mentzel.name/?p=271</guid>
		<description><![CDATA[Das Html-Helper Object des MVC2 Frameworks unterstützt kein Generieren von File-Input Steuerelementen. Hier ist ein Workaround für dieses Problem: Man überschreibt das Type-Attribut mit &#8220;file&#8221;. &#60;%: Html.TextBoxFor(model => model.File, new { size = "30", type = "file" }) %&#62; Der vollständige Code sieht folgendermaßen aus. // Modell mit der Eigenschaft "File" für die hochgeladene Datei [...]]]></description>
			<content:encoded><![CDATA[<p>Das Html-Helper Object des MVC2 Frameworks unterstützt kein Generieren von File-Input Steuerelementen. Hier ist ein Workaround für dieses Problem: Man überschreibt das Type-Attribut mit &#8220;file&#8221;.</p>
<pre>&lt;%: Html.TextBoxFor(model => model.File, new { size = "30", type = "file" }) %&gt;</pre>
<p><span id="more-271"></span><br />
Der vollständige Code sieht folgendermaßen aus.</p>
<pre>
    // Modell mit der Eigenschaft "File" für die hochgeladene Datei
    public class UploadPartModel
    {
        [Required()]
        public HttpPostedFileWrapper File { get; set; }

        [Required()]
        public string Name { get; set; }

        [Required()]
        public string Description { get; set; }
    }
</pre>
<p>Das Formular wird mittels &#8220;Html.___For()&#8221; Methodne zusammengebaut. Nicht vergessen im Formular das &#8220;enctype&#8221;-Attribut mit dem Wert &#8220;multipart/form-data&#8221; zu setzen, sonst gibt es nicht serverseitig viel zu sehen.</p>
<pre>
    &lt;% Html.EnableClientValidation(); // used for client side validation with jQuery
       using (Html.BeginForm(null, null, FormMethod.Post, <font color="Red">new { enctype = "multipart/form-data" }</font >))
       {
           Html.ValidationSummary(true); %&gt;
    &lt;fieldset&gt;
        &lt;legend&gt;Fields&lt;/legend&gt;
        &lt;div class="editor-label"&gt;
            &lt;%: Html.LabelFor(model =&gt; model.Name) %&gt;
        &lt;/div&gt;
        &lt;div class="editor-field"&gt;
            &lt;%: Html.TextBoxFor(model =&gt; model.Name, new { size = "30" })%&gt;
            &lt;%: Html.ValidationMessageFor(model =&gt; model.Name) %&gt;
        &lt;/div&gt;
        &lt;div class="editor-label"&gt;
            &lt;%: Html.LabelFor(model =&gt; model.Description)%&gt;
        &lt;/div&gt;
        &lt;div class="editor-field"&gt;
            &lt;%: Html.TextBoxFor(model =&gt; model.Description, new { size = "30" })%&gt;
            &lt;%: Html.ValidationMessageFor(model =&gt; model.Description)%&gt;
        &lt;/div&gt;
         &lt;div class="editor-label"&gt;
            &lt;%: Html.LabelFor(model =&gt; model.File) %&gt;
        &lt;/div&gt;
        &lt;div class="editor-field"&gt;
            <font color="Red">&lt;%: Html.TextBoxFor(model =&gt; model.File, new { size = "30", type = "file" }) %&gt;</font >
            &lt;%: Html.ValidationMessageFor(model =&gt; model.File) %&gt;
        &lt;/div&gt;
        &lt;p&gt;
            &lt;input type="submit" value="Upload" /&gt;
        &lt;/p&gt;
    &lt;/fieldset&gt;
    &lt;% } %&gt;
</pre>
]]></content:encoded>
			<wfw:commentRss>http://mentzel.name/2010/07/28/quicktipp-asp-net-mvc2-html-filefor/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>ASP.NET MVC2 &amp; Validation I (Serverseitige Validierung)</title>
		<link>http://mentzel.name/2010/07/25/asp-net-mvc2-validation-i-serverseitige-validierung/</link>
		<comments>http://mentzel.name/2010/07/25/asp-net-mvc2-validation-i-serverseitige-validierung/#comments</comments>
		<pubDate>Sun, 25 Jul 2010 17:48:00 +0000</pubDate>
		<dc:creator>Thomas Mentzel</dc:creator>
				<category><![CDATA[Allgemeines]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[DotNetGerman Bloggers]]></category>
		<category><![CDATA[ASP.NET; MVC2]]></category>

		<guid isPermaLink="false">http://mentzel.name/2010/07/25/asp-net-mvc2-validation-i-serverseitige-validierung/</guid>
		<description><![CDATA[Serverseitige Validierung Das ASP.NET MVC2 Framework biete eine einfache Möglichkeit zur Validierung eines Modells: Data Annotations. Mit Attributen wird die Validierung für das Modell definiert. Im MVC2 Framework sind vier Validatoren enthalten: Required, StringLength, Range und RegularExpression. Eine Klasse “Contact” könnte also folgendermaßen annotiert werden. public class Contact {&#160; &#160;&#160;&#160; [Required(ErrorMessage = &#34;Es muss ein [...]]]></description>
			<content:encoded><![CDATA[<p><strong>Serverseitige Validierung</strong></p>
<p>Das ASP.NET MVC2 Framework biete eine einfache Möglichkeit zur Validierung eines Modells: Data Annotations. Mit Attributen wird die Validierung für das Modell definiert. Im MVC2 Framework sind vier Validatoren enthalten: Required, StringLength, Range und RegularExpression. <span id="more-261"></span>Eine Klasse “Contact” könnte also folgendermaßen annotiert werden.</p>
<blockquote style="width: 793px; height: 286px"><p>public class Contact      <br />{&#160; <br />&#160;&#160;&#160; [Required(ErrorMessage = &quot;Es muss ein Vorname angegeben werden.&quot;)]       <br />&#160;&#160;&#160; [StringLength(200)]       <br />&#160;&#160;&#160; public string Vorname { get; set; } </p>
<p>&#160;&#160;&#160; [Required(ErrorMessage = &quot;Es muss ein Nachname angegeben werden.&quot;)]      <br />&#160;&#160;&#160; public string Nachname { get; set; } </p>
<p>&#160;&#160;&#160; [Range(0, 69, ErrorMessage = &quot;Mit mehr als 69 Kindern halten sie den Weltrekord. Unwahrscheinlich!&quot;)]      <br />&#160;&#160;&#160; public int Kinder { get; set; } </p>
<p>&#160;&#160;&#160; [RegularExpression(@&quot;[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}&quot;)]      <br />&#160;&#160;&#160; public string Email { get; set; }       <br />} </p>
</blockquote>
<p>Damit kann anschließend das Modell entsprechend der Attributierung validieren und die Fehlermeldungen an den Anwender ausgeben lassen. Zusätzlich kann man noch eigene Meldungen an die View mittels “ModelState.AddModelError(&lt;Eigenschaft&gt;, &lt;Nachricht&gt;)” durchreichen.</p>
<blockquote style="width: 649px; height: 204px"><p>[HttpPost()]      <br />public ActionResult Logon(LogonModel model, string returnUrl)       <br />{       <br />&#160;&#160;&#160; // Validierung des Modells abfragen: “ModelState.IsValid”&#160; <br />&#160;&#160;&#160; if (!ModelState.IsValid) return View(model);</p>
<p>&#160;&#160;&#160; // Alternativ Meldungen für das gesamte Modell ausgeben      <br />&#160;&#160;&#160; ModelState.AddModelError(&quot;&quot;, &quot;Deine eingegebenen Daten sind falsch.&quot;);       <br />&#160;&#160;&#160; return View(model);       <br />}</p>
</blockquote>
<p><strong>Benutzerdefinierte serverseitige Validierung</strong></p>
<p>Diese vier Validatoren decken die häufigsten Fällt ab, leider aber nicht alle. Manchmal kommt man um eine eigene Validierung nicht herum. Dazu sieht das MCV2 Framework die Basisklasse “ValidationAttribute” vor. Erbt eine Klasse von dem ValidationAttribute kann die Methoden “IsValid” überschrieben werden. In dieser Methode wird die Validierungslogik implementiert. Hier ist ein kleines Beispiel für eine Validierung, welches die Komplexität eines Kennworts prüft (mindestens ein Buchstabe groß geschrieben).</p>
<blockquote><p>&#160;&#160;&#160; public class ComplexPasswordAttribute : ValidationAttribute<br />&#160;&#160;&#160; {<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; private readonly bool _capitalLetterRequired = true;</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160; public ComplexPasswordAttribute(bool capitalLetterRequired)<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; {<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; _capitalLetterRequired = capitalLetterRequired;<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; }</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160; public override bool IsValid(object value)<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; {<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; if (value == null) return false;<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; var valueString = value.ToString();</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; if (_capitalLetterRequired)<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; if (valueString.ToLower() == valueString)<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; return false;</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; return true;<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; }<br />&#160;&#160;&#160; }</p></blockquote>
<p>Der Validator kann nun wie die anderen Attribute verwendet werden. Das MVC2 Framework ruft automatisch die “IsValid()” Methode auf und gibt bei einem negativen Ergebnis die Fehlermeldung “ErrorMessage” an die View weiter.</p>
<blockquote style="width: 741px; height: 212px"><p>
  public class LoginData<br />
    <br />{&#160; <br />&#160;&#160;&#160; [Required()]<br />
    <br />&#160;&#160;&#160; public string LoginName { get; set; }<br />
    <br />&#160;&#160;&#160; [ComplexPassword(true, ErrorMessage=”Kennwort ist zu einfach”)]<br />
    <br />&#160;&#160;&#160; public string Password { get; set; }<br />
    <br />}
</p></blockquote>
]]></content:encoded>
			<wfw:commentRss>http://mentzel.name/2010/07/25/asp-net-mvc2-validation-i-serverseitige-validierung/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>SQL Server 2008 und “Concatenate”</title>
		<link>http://mentzel.name/2010/07/23/sql-server-2008-und-concatenate/</link>
		<comments>http://mentzel.name/2010/07/23/sql-server-2008-und-concatenate/#comments</comments>
		<pubDate>Fri, 23 Jul 2010 20:26:36 +0000</pubDate>
		<dc:creator>Thomas Mentzel</dc:creator>
				<category><![CDATA[C#]]></category>
		<category><![CDATA[DotNetGerman Bloggers]]></category>
		<category><![CDATA[Aggregate]]></category>
		<category><![CDATA[Concat]]></category>
		<category><![CDATA[SQL Server 2008]]></category>

		<guid isPermaLink="false">http://mentzel.name/2010/07/23/sql-server-2008-und-concatenate/</guid>
		<description><![CDATA[Vor nicht allzu langer Zeit … habe ich im SQL Server 2008 ein Aggregat-Funktion vermisst, die es bereits in MYSQL gibt: GROUP_CONCAT. Damit ist es bei einer Gruppierung möglich, Werte zu verketten. Es begab ich folgendes vereinfachtes Problem: Es war Tabelle mit Salaten, die Personen zum Grillen mitbringen. Das Ziel sollte ein Liste gruppiert nach [...]]]></description>
			<content:encoded><![CDATA[<p>Vor nicht allzu langer Zeit … habe ich im SQL Server 2008 ein Aggregat-Funktion vermisst, die es bereits in MYSQL gibt: <a href="http://dev.mysql.com/doc/refman/5.1/en/group-by-functions.html#function_group-concat" target="_blank">GROUP_CONCAT</a>. Damit ist es bei einer Gruppierung möglich, Werte zu verketten.</p>
<p>Es begab ich folgendes vereinfachtes Problem: Es war Tabelle mit Salaten, die Personen zum Grillen mitbringen. Das Ziel sollte ein Liste gruppiert nach dem Salat sein. Zusätzlich zur Zählung (COUNT) sollten noch alle Personen aufgelistet werden, die den entsprechenden Salat mitbringen (CONCAT).</p>
<p><a href="http://mentzel.name/wp-content/uploads/2010/07/image.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://mentzel.name/wp-content/uploads/2010/07/image_thumb.png" width="158" height="137" /></a><a href="http://mentzel.name/wp-content/uploads/2010/07/image1.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://mentzel.name/wp-content/uploads/2010/07/image_thumb1.png" width="300" height="138" /></a></p>
<p>Google hatte für dieses Problem verschiedene Lösungen. Die einen waren zu kompliziertes SQL (un-Wartbarkeit!) und funktionierten nur für endlich Anzahl von Zeilen bzw. nicht wiederverwendbare benutzerdefinierte Funktion. Die eleganteste aber aufwändigste Lösung im Bezug auf das Deployment schien das Entwickeln einer eigenen Aggregat-Funktion “Concat”. An Ende war die eigene Aggregatfunktion das einfachste und das Deployment überschaubar (Adminsicher <img src='http://mentzel.name/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> ).</p>
<p><strong>Vorgehen</strong></p>
<ol>
<li>Erstellen der Assembly </li>
<li>SQL Server anpassen </li>
<li>Aggregatfunktion verwenden </li>
</ol>
<p><strong>.NET Assembly erstellen</strong></p>
<p>Visual Studio 2010 unterstützt bei der Erstellung von SQL Server Assemblys über den “Neues Projekt” Wizard.</p>
<p><a href="http://mentzel.name/wp-content/uploads/2010/07/image2.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://mentzel.name/wp-content/uploads/2010/07/image_thumb2.png" width="244" height="175" /></a> </p>
<p>Anschließen kann über “Hinzufügen” eine neues Aggregat angelegt werden.</p>
<p><a href="http://mentzel.name/wp-content/uploads/2010/07/image3.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://mentzel.name/wp-content/uploads/2010/07/image_thumb3.png" width="244" height="86" /></a> </p>
<p>Das Klasse der Aggregatfunktion in der .NET Assembly ist selbsterklärend. Die Methoden werden mittels Reflection aufgerufen, daher ist keine separate Schnittstelle zu implementieren. Die Schnittstelle “IBinarySerialize” dient dazu, das in dem Klassenattribut deklarierte “Format.UserDefined” (<a href="http://msdn.microsoft.com/de-de/library/microsoft.sqlserver.server.ibinaryserialize.aspx" target="_blank">MSDN</a>) zu implementieren.</p>
<blockquote><p>using System;<br />using Microsoft.SqlServer.Server;<br />using System.Data.SqlTypes;<br />using System.IO;<br />using System.Text;</p>
<p>namespace SwkAggregates<br />{<br />&#160;&#160;&#160; [Serializable]<br />&#160;&#160;&#160; [SqlUserDefinedAggregate(<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; Format.UserDefined, //use clr serialization to serialize the intermediate result<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; IsInvariantToNulls = true, //optimizer property<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; IsInvariantToDuplicates = false, //optimizer property<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; IsInvariantToOrder = false, //optimizer property<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; MaxByteSize = 8000) //maximum size in bytes of persisted value<br />&#160;&#160;&#160; ]<br />&#160;&#160;&#160; public class Concat : IBinarySerialize<br />&#160;&#160;&#160; {<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; /// &lt;summary&gt;<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; /// The variable that holds the intermediate result of the concatenation<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; /// &lt;/summary&gt;<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; private StringBuilder _intermediateResult;</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160; /// &lt;summary&gt;<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; /// Initialize the internal data structures<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; /// &lt;/summary&gt;<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; public void Init()<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; {<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; this._intermediateResult = new StringBuilder();<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; }</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160; /// &lt;summary&gt;<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; /// Accumulate the next value, not if the value is null<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; /// &lt;/summary&gt;<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; /// &lt;param name=&quot;value&quot;&gt;&lt;/param&gt;<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; public void Accumulate(SqlString value)<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; {<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; if (value.IsNull)<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; {<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; return;<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; }</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; this._intermediateResult.Append(value.Value).Append(&quot;, &quot;);<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; }</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160; /// &lt;summary&gt;<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; /// Merge the partially computed aggregate with this aggregate.<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; /// &lt;/summary&gt;<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; /// &lt;param name=&quot;other&quot;&gt;&lt;/param&gt;<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; public void Merge(Concat other)<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; {<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; this._intermediateResult.Append(other._intermediateResult);<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; }</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160; /// &lt;summary&gt;<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; /// Called at the end of aggregation, to return the results of the aggregation.<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; /// &lt;/summary&gt;<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; /// &lt;returns&gt;&lt;/returns&gt;<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; public SqlString Terminate()<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; {<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; string output = string.Empty;<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; //delete the trailing comma, if any<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; if (this._intermediateResult != null<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; &amp;&amp; this._intermediateResult.Length &gt; 1)<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; {<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; output = this._intermediateResult.ToString(0, this._intermediateResult.Length &#8211; 2);<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; }</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; return new SqlString(output);<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; }</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160; public void Read(BinaryReader r)<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; {<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; _intermediateResult = new StringBuilder(r.ReadString());<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; }</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160; public void Write(BinaryWriter w)<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; {<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; w.Write(this._intermediateResult.ToString());<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; }<br />&#160;&#160;&#160; }<br />}</p></blockquote>
<p><font color="#800000">Hinweis: Die Assembly muss keinen Strong Name besitzen. Es lassen sich auch eine nicht-signierte Assemblys in den SQL Server hochladen. Ob das Bestandteil der neuen Sicherheitspolitik von Microsoft ist wage ich zu bezweifeln.</font></p>
<p>Also bleibt nur noch das Kompilieren der DLL und anschließend das Integrieren in den SQL Server.</p>
<p><strong>SQL Server Integration</strong></p>
<p>Die SQL Server Integration besteht aus zwei Schritten.</p>
<ol>
<li>Hochladen der Assembly in den SQL Server </li>
<li>Erstellen einer Aggregatfunktion mit einem “API-Call” auf die Klasse in der DLL </li>
</ol>
<p>Das Script enthält auch die optionalen Schritte, wenn das Ausführen von Assemblys in der Datenbank noch nicht aktiviert wurde. Das Script ist durch die Kommentierung (hoffentlich) selbsterklärend.</p>
<blockquote><p>&#8211; Add assembly to database<br />CREATE ASSEMBLY SwkUtilities FROM &#8216;d:\SwkAggregates.dll&#8217;<br />WITH PERMISSION_SET=SAFE;<br />GO</p>
<p>&#8211; Create aggregate function which calls the concrete &quot;Concat&quot; class<br />CREATE AGGREGATE Concat(@input nvarchar(4000))<br />RETURNS nvarchar(4000)<br />EXTERNAL NAME [SwkUtilities].[SwkAggregates.Concat];<br />GO</p>
<p>&#8211; Enable cls code execution. It is disabled by default<br />sp_configure &#8216;clr enabled&#8217;, 1;</p>
<p>GO</p>
<p>&#8211; Deploy the &quot;clr enabled&quot; setting in sql server<br />reconfigure<br />GO</p></blockquote>
<p>Zu bemerken ist, dass die Assembly im SQL Server einen symbolischen Namen &#8220;SwkUtilities&#8221; erhält. Der API-Call erfolgt über diesen symbolischen Namen. Außerdem wird die DLL wird in den SQL Server hochgeladen und ist damit Bestandteil der Datenbank. Das hat natürlich Auswirkungen auf Backup und Restore Szenarien. Bei einem Backup werden die Assemblies mitgesichert d.h. es entfällt ein FileSystem Backup. Im Gegenzug werden mit einem Restore der Datenbank auch die Assemblies wiederhergestellt.</p>
<p><strong>SQL Verwendung</strong></p>
<p>Ab jetzt heißt es viel Spaß mit der neuen Aggregat Funktion und der geplanten Grillfete <img src='http://mentzel.name/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> .</p>
<blockquote><p>SELECT Salat, Count(*), <strong>dbo.Concat(Person)</strong><br />FORM Grillfest<br />GROUP BY Salat</p></blockquote>
]]></content:encoded>
			<wfw:commentRss>http://mentzel.name/2010/07/23/sql-server-2008-und-concatenate/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>dotnet Cologne 2010 Tagebuch</title>
		<link>http://mentzel.name/2010/06/01/dotnet-cologne-2010-tagebuch/</link>
		<comments>http://mentzel.name/2010/06/01/dotnet-cologne-2010-tagebuch/#comments</comments>
		<pubDate>Tue, 01 Jun 2010 19:25:20 +0000</pubDate>
		<dc:creator>Thomas Mentzel</dc:creator>
				<category><![CDATA[Allgemeines]]></category>
		<category><![CDATA[DotNetGerman Bloggers]]></category>
		<category><![CDATA[dotnet Cologne]]></category>

		<guid isPermaLink="false">http://mentzel.name/2010/06/01/dotnet-cologne-2010-tagebuch/</guid>
		<description><![CDATA[6:15 Der Wecker hat klingelt. Die Nacht war viel zu kurz. Einen Kaffee trinken und pünktlich aus dem Haus, damit ich rechtzeitig da bin. Wollte mit dem Auto fahren und nicht in den Berufsverkehr kommen. 8:15 Mist! Viel zu spät losgefahren und in den Berufsverkehr geraten. Gehofft, dass alles noch klappt und es noch Frühstück [...]]]></description>
			<content:encoded><![CDATA[<p>6:15 Der Wecker hat klingelt. Die Nacht war viel zu kurz. Einen Kaffee trinken und pünktlich aus dem Haus, damit ich rechtzeitig da bin. Wollte mit dem Auto fahren und nicht in den Berufsverkehr kommen.</p>
<p>8:15 Mist! Viel zu spät losgefahren und in den Berufsverkehr geraten. Gehofft, dass alles noch klappt und es noch Frühstück gibt. Die Uhr rennt, der Verkehr steht.</p>
<p>9:25 Endlich da. Alle Parkplätze am Hotel waren leider besetzt. Also in Köln einen Parkplatz gesucht und zum Glück einen in der Nähe gefunden! Zeit für ein kleines Frühstück gehabt und die ersten bekannten Gesichter (wieder)gesehen wie <a href="http://blog.jan-welker.de/" target="_blank">Jan Welker</a> und <a href="http://webenliven-space.de/dotnetblog/" target="_blank">Gregor Biswanger</a>. Besonders interessant waren die Gesichter hinter den Blogs die ich nur von Fotos kannte wie <a href="http://dotnet-forum.de/blogs/thorstenhans/" target="_blank">Thorsten Hans</a>, <a href="http://www.philipproplesch.de/" target="_blank">Philip Proplesch</a> und <a href="http://gordon-breuer.de/" target="_blank">Gordon Breuer</a>.</p>
<p>9:45 Begrüßung und Keynote durch die Organisatoren <a href="http://weblogs.asp.net/rweigelt/" target="_blank">Roland Weigelt</a>, <a href="http://der-albert.com/" target="_blank">Albert Weinert</a> und <a href="http://www.st-lange.net/" target="_blank">Stefan Lange</a>. Leider war der Raum viel zu voll um noch einen Platz zu ergattern. Also weiter gefrühstückt und gequatscht, dieses mal unter anderem mit <a href="http://www.software-architects.com/Blogs/tabid/72/BlogID/5/Default.aspx" target="_blank">Rainer Stropek</a> über TimeCockpit und Windows Azure.</p>
<p>10:25 Der erste Vortrag beginnt: “Give Your Application a Triple Boost with Windows 7, Microsoft .NET 4.0, and Intel Multi-core” vom Rami Radi. Es ging nicht wie von mir erwartet um Windows 7 Applikationen und Multi-core Entwicklung sondern um Prozessorarchitektur und Auswirkungen auf den Entwickler. War man offen für dieses Thema, war der Vortrag sehr interessant und informativ. Besonders die <a href="http://www.intel.com/technology/tick-tock/" target="_blank">Tick-Tock</a> Vorgehensweise von Intel ist auch auf andere Projekte anwendbar und hat einen Hauch von “Red, Green, Refactor”.</p>
<p>11:40 Nicht nur draußen sondern auch im zweiten Vortrag war der Himmel blau…Azure-Blau. Rainer Stropek hat einen schönen Vortrag über die Migration einer lokalen Webapplikation in die Cloud gehalten. Dabei durften die Herausforderungen wie Datenbank und Dateisystem nicht fehlen. Pünktlich nach einer Stunde war die Applikation in der Cloud und lief.</p>
<p>12:55 Den dritten Vortrag habe ich sozusagen geschwänzt. Ich hätte sehr gerne den Vortrag von <a href="http://www.sturmnet.org/blog/" target="_blank">Oliver Sturm</a> (Funktionale Programmierung in C#) oder von <a href="http://dotnet-forum.de/blogs/thorstenhans/" target="_blank">Thorsten Hans</a> (MSBuild) gehört.Ich habe mich allerdings in den Sprecherraum zurückgezogen und bin noch einmal meine Präsentation durchgegangen. </p>
<p>13:55 Das Essen sah sehr lecker aus. Leider war mir der Andrang zu groß, also habe ich mich in die Sonne gelegt und abgewartet. Als ich mir dann die Mühe gemacht habe, Essen zu gehen war nur noch Nachtisch da. Als ich schließlich vom ganzen süßen Zeug satt war wurde neues Essen aufgelegt. Leider zu spät aber es war reichlich Essen da.</p>
<p>15:00 Es war endlich so weit, mein ASP.NET MVC2 Vortrag. Leider habe ich nur einen Teil von dem gezeigt, was ich zeigen wollte. 60 Minuten gingen viel zu schnell vorbei und habe mich viel zu lange an den Grundlagen aufgehalten. Es war viel zu wenig von den neuen tollen Features in ASP.NET MVC2.</p>
<p>16:15 Danach ging es dann zur “Konkurrenz”: ASP.NET 4.0 WebForms von Jan Welker. Es gab einen schönen Überblick über die neuen Features von ASP.NET 4.0. Die Beispiele waren sehr interessant und aufschlussreich. Sogar für mich als nicht WebForms Entwickler, da ASP.NET MVC2 auf WebForms aufsetzt.</p>
<p>17:30 Zu guter letzt ging es in den Vortrag <strike>“Warum sie JavaScript hassen sollten”</strike> “Warum sie nach diesem Vortrag JavaScript nicht mehr hassen können” von <a href="http://www.codemurai.de/" target="_blank">Andrè Krämer</a>. Ich bin bekennender JavaScript verweigerer. Aber jQuery im Gegensatz dazu ist wieder schön und sogar ich kann dem inzwischen etwas abgewinnen. Keine Browser-Abfragen, kleine Helfer mit großer Auswirkungen und besonders das <em>nachträgliche</em> dynamisieren der (MVC)WebApplikation. Vielleicht hat Andrè aus mir einen jQuery Freund gemacht…wir werden sehen.</p>
<p>18:40 An der Verlosung habe ich als fauler Sprecher nicht teilgenommen. Für mich gab es nix zu gewinnen und so hatte ich Zeit für ein paar ruhige Gespräche abseits des Rahmenprogramms mit anderen Faulpelzen. Ich hatte auch ohne Feedbackbogen noch eine Tasse ergattert und das reicht als Preis <img src='http://mentzel.name/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> . Einen großen Dank an die nette Tassen-Dame.</p>
<p>19:00 Endlich die Grillfete. Lange hinausgeschoben, lange angekündigt und endlich war es so weit. Ein riesen Dank an Jan Welker und die aktiven Mitglieder des <a href="http://dotnet-forum.de/" target="_blank">dotnet Forums</a>. Das Essen war lecker, das Wetter super und die Teilnehmer allesamt nett.</p>
<p>21:30 Der Tag war lang, die Nacht war kurz. Noch einen Strauß Blumen für meine Frau gekauft, die mich seit Wochen nur noch vor dem Notebook sitzen sah und nicht viel von mit hatte. Glotze an, Augen zu.</p>
<p><strong>Ich freue mich schon jetzt auf die dotnet Cologne 2011 und vielleicht wieder als Sprecher. Noch einmal einen riesigen Dank an die Organisatoren und Helfer der dotnet Cologne 2010.</strong></p>
]]></content:encoded>
			<wfw:commentRss>http://mentzel.name/2010/06/01/dotnet-cologne-2010-tagebuch/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>ASP.NET MVC2 &amp; Areas</title>
		<link>http://mentzel.name/2010/05/31/asp-net-mvc2-areas/</link>
		<comments>http://mentzel.name/2010/05/31/asp-net-mvc2-areas/#comments</comments>
		<pubDate>Mon, 31 May 2010 12:06:27 +0000</pubDate>
		<dc:creator>Thomas Mentzel</dc:creator>
				<category><![CDATA[C#]]></category>
		<category><![CDATA[DotNetGerman Bloggers]]></category>
		<category><![CDATA[ASP.NET; MVC2]]></category>

		<guid isPermaLink="false">http://mentzel.name/2010/05/31/asp-net-mvc2-areas/</guid>
		<description><![CDATA[Area Support In der zweite Version des MVC Frameworks für ASP.NET wurden sog. “Areas” eingeführt. Mit Areas können Controller thematisch gruppiert und als Unterprojekt verwaltet werden. Jede Area bekommt eine eigene Ordnerstruktur mit “Controllers”, “Models” und “Views” und enthält damit zu den Controllern die entsprechenden Views und Models. Eine Area kann als separates Modul betrachtet [...]]]></description>
			<content:encoded><![CDATA[<p><strong><a href="http://mentzel.name/wp-content/uploads/2010/05/Mvc2_AreaSupport.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; margin-left: 0px; border-left-width: 0px; margin-right: 0px" title="Mvc2_Area-Support" border="0" alt="Mvc2_Area-Support" align="right" src="http://mentzel.name/wp-content/uploads/2010/05/Mvc2_AreaSupport_thumb.png" width="143" height="244" /></a>Area Support</strong></p>
<p>In der zweite Version des MVC Frameworks für ASP.NET wurden sog. “Areas” eingeführt. Mit Areas können Controller thematisch gruppiert und als Unterprojekt verwaltet werden. Jede Area bekommt eine eigene Ordnerstruktur mit “Controllers”, “Models” und “Views” und enthält damit zu den Controllern die entsprechenden Views und Models. Eine Area kann als separates Modul betrachtet und entwickelt werden. Große und komplexe Projekte können in kleine überschaubare Module gegliedert werden. </p>
<p>Vorteile ergeben sich besonders, wenn Module tatsächlich unabhängig voneinander implementiert werden. So können wiederkehrende oder zentrale Komponenten wie “Blog”, “Wiki” oder “Benutzeradministration” zentral implementiert und weiterentwickelt werden. Projekte, welche diese Komponenten verwenden, können auf diese Module verweisen oder bei kundenspezifischen Anpassungen einen bestimmten Entwicklungsstand verwenden und anpassen.</p>
<p><strong>Areas anlegen und verwenden</strong></p>
<p>Areas werden im Visual Studio über das Kontextmenü “Hinzufügen” –&gt; “Bereich/Area” hinzugefügt. Nach der Eingabe des Namens werden die Verzeichnisse und die Infrastruktur für das erweiterte Routing (“[Area-Name]AreaRegistration.cs”) angelegt. Die Area-Registration erbt von einer Klasse “AreaRegistration” um die Routen separiert pro Modul definieren zu können. Dadurch wird eine absolute Unabhängigkeit der Module realisiert.</p>
<p>Für Links innerhalb der Applikation kann weiterhin die “Html.ActionLink()” Methode verwendet werden. Es muss nur ein weiteres Routing-Schlüsselwort “Area” in den RouteValues für die Ziel-Area definiert werden. Zu beachten ist allerdings die polymorphe Signatur der Methode.</p>
<blockquote><p><strike>&lt;li&gt;&lt;%: Html.ActionLink(&quot;Admin&quot;, &quot;Index&quot;, &quot;Default&quot;, new {Area = &quot;Admin&quot;}) %&gt;&lt;/li&gt;</strike>       <br />&lt;li&gt;&lt;%: Html.ActionLink(&quot;Admin&quot;, &quot;Index&quot;, &quot;Default&quot;, new {Area = &quot;Admin&quot;}, new {}) %&gt;&lt;/li&gt;</p>
</blockquote>
<p>Die 2. Zeile scheint gleich zu sein, da der Parameter leer ist. Der leere Parameter bewirkt aber den Aufruf einer anderen Methode wegen einer anderen Methodensignatur. Im ersten Fall wird der Parameter mit der Area Definition als “HtmlAttributes” interpretiert. In zweiten Fall wird der leere Parameter als “HtmlAttributes” interpretiert und die Area Definition wird zu &quot;RouteValues”.</p>
<p>Die Methode “ActionLink()” arbeitet relativ zu der aktuellen Area. Befindet man sich in der Root Area ist alles kein Problem. Befindet man sich allerdings innerhalb einer Area wird als Default die aktuelle Area verwendet. Wichtig wird das bei zentralen Menüs oder in der Masterpage. Die Masterpage eines Standard MVC2 Projektes enthält Links auf die Startseite (DefaultController –&gt; Index) ohne Angabe einer Area. Innerhalb einer Area wird daraus der Link auf die Startseite der Area (Area/DefaultController –&gt; Index). Der Link unabhängig von der Area auf die Startseite muss also mit leerer Area erfolgen:</p>
<blockquote><p><strike>&lt;li&gt;&lt;%: Html.ActionLink(&quot;Admin&quot;, &quot;Index&quot;, &quot;Default) %&gt;&lt;/li&gt;</strike>       <br />&lt;li&gt;&lt;%: Html.ActionLink(&quot;Admin&quot;, &quot;Index&quot;, &quot;Default&quot;, new {Area = &quot;&quot;}, new {}) %&gt;&lt;/li&gt;</p>
</blockquote>
<p><strong>Zwei Controller, ein Name</strong></p>
<p>Gibt es in einem Projekt zwei Controller mit dem gleichen Namen funktioniert die automatisch generierte Default-Route nicht mehr. Das MVC Framework ist nicht in der Lage ohne Angabe des Namespaces den richtigen Controller zu finden, das MVC nur den Kurznamen kennt. Der Default-Route muss in einem solchen Fall der Namespaces des Default-Controlles als Parameter mitgegeben werden.</p>
<blockquote><p>routes.MapRoute(      <br />&#160;&#160;&#160; &quot;Default&quot;, // Routenname       <br />&#160;&#160;&#160; &quot;{controller}/{action}/{id}&quot;, // URL mit Parametern       <br />&#160;&#160;&#160; new { controller = &quot;Home&quot;, action = &quot;Index&quot;, id = UrlParameter.Optional }, // Parameterstandardwerte       <br />&#160;&#160;&#160; new [] {&quot;SmartHome.Mvc&quot;} // Namespace       <br />); </p>
</blockquote>
<p><strong>Shared Views</strong></p>
<p>Bei der Verwendung der Shared Views ist zu berücksichtigen, dass bei automatisch ermittelten Controls erst in der betreffenden Area und anschließend in der Root Area nachgeschlagen wird. Interessant werden diese Aspekte bei z.B. EditorTemplates oder DisplayTemplates. So können Views zentral bereitgestellt und für Areas separat überschrieben werden.</p>
<p><a href="http://mentzel.name/wp-content/uploads/2010/05/Mvc2_Page_Lookup.png"><img style="border-right-width: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto" title="Mvc2_Page_Lookup" border="0" alt="Mvc2_Page_Lookup" src="http://mentzel.name/wp-content/uploads/2010/05/Mvc2_Page_Lookup_thumb.png" width="313" height="89" /></a> </p>
<p><strong>Fazit</strong></p>
<p>Areas sind eine sehr gute Erweiterung des Frameworks. Sind die Stolpersteine bekannt können Areas intuitiv verwendet werden. Besonders im Hinblick auf die modulare Entwicklung von Komponenten bieten sich hier viele Möglichkeiten. Durch das Verwenden eines Team Foundation Servers und Workspacedefinitionen ist ein Zusammenstecken einer Applikation sehr einfach, da wirklich auf die Module innerhalb eines andern Ordners im TFS verwiesen werden kann.</p>
]]></content:encoded>
			<wfw:commentRss>http://mentzel.name/2010/05/31/asp-net-mvc2-areas/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Coding Kata FizzBuzz</title>
		<link>http://mentzel.name/2010/05/10/coding-kata-fizzbuzz/</link>
		<comments>http://mentzel.name/2010/05/10/coding-kata-fizzbuzz/#comments</comments>
		<pubDate>Mon, 10 May 2010 18:36:49 +0000</pubDate>
		<dc:creator>Thomas Mentzel</dc:creator>
				<category><![CDATA[Architektur]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[DotNetGerman Bloggers]]></category>
		<category><![CDATA[Coding Kata]]></category>
		<category><![CDATA[FizzBuzz]]></category>

		<guid isPermaLink="false">http://thomas.mentzel.name/?p=112</guid>
		<description><![CDATA[Disclaimer: Diejenigen, die sich gerne unvorbelastet an die FizzBizz Coding Kata heranwagen möchten, sollten hier besser nicht weiterlesen. Der Artikel wird verschiedene Lösung zeigen Einleitung Unser firmeninternes Coding Dojo hatte eine relativ einfache Kata: FizzBuzz. Zwar ist die Aufgabe einfach und überschaubar, aber dafür sind die Erweiterungen vielfältig. Bei dieser Kata konnte man das Prinzip [...]]]></description>
			<content:encoded><![CDATA[<p><em>Disclaimer: Diejenigen, die sich gerne unvorbelastet an die FizzBizz Coding Kata heranwagen möchten, sollten hier besser nicht weiterlesen. Der Artikel wird verschiedene Lösung zeigen <img src='http://mentzel.name/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </em></p>
<p>
<div style="width:425px; text-align: center;" id="__ss_3951183"><object id="__sse3951183" width="425" height="355"><param name="movie" value="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=katafizzbizz-100503135732-phpapp02&#038;stripped_title=coding-kata-fizz-buzz" /><param name="allowFullScreen" value="true"/><param name="allowScriptAccess" value="always"/><embed name="__sse3951183" src="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=katafizzbizz-100503135732-phpapp02&#038;stripped_title=coding-kata-fizz-buzz" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="355"></embed></object></div>
</p>
<h3>Einleitung</h3>
<p>Unser firmeninternes Coding Dojo hatte eine relativ einfache Kata: FizzBuzz. Zwar ist die Aufgabe einfach und überschaubar, aber dafür sind die Erweiterungen vielfältig. Bei dieser Kata konnte man das Prinzip von Unit Test und Test Driven Development verdeutlichen. Erweitert man die Implementierung, kann die Implementierung der alten Anforderungen direkt getestet werden. Man merkt also, ob man über die neue Anforderung die alten Anforderungen vergessen hat. Als Organisator habe ich mir in Vorfeld Gedanken über die mögliche Implementierung gemacht, da ich einer der beiden Programmierer war. Bei der Kata musst ich dafür Sorgen, dass die Schnittstellen/Vorgaben so definiert sind dass der Test keine weiteren Vorgaben für die Implementierung macht als die Schnittstelle. Folgendes Klassengerüst war also vorgegeben:</p>
<pre><code>
public class FizzBuzzer
{
    public IEnumerable&lt;string&gt; FizzBuzz(int maxZahl)
    {
        throw new NotImplementedException();
    }
}
</code></pre>
<p>Das Pair-Programming-System ist auch in ein verändertes Ping-Pong geändert worden: Ich habe einen Test geschrieben, mein Co-Programmierer hat den Test implementiert und ich habe den nächsten Test geschrieben.</p>
<h3>Dojo Lösung</h3>
<p>Die Lösung im Dojo war die einfachste aller Möglichkeiten&#8230;eine Implementierung der Methode und das wars. Selbst als die Erweiterungen kamen wurde der FizzBuzzer höchstens um zwei Konstruktor-Parameter erweitert. Und damit die Tests laufen gabe es einen Default-Konstruktor mit dem Standard &#8220;3&#8243; und &#8220;5&#8243;.</p>
<pre><code>
public class FizzBuzzer
{
    #region Felder
    private int _n;
    private int _m;
    #endregion

    #region Konsturktor: (), (n, m)
    public FizzBuzzer() : this(3,5)
    {
    }

    public FizzBuzzer(int n, int m)
    {
        _n = n;
        _m = m;
    }
    #endregion

    public IEnumerable&lt;string&gt; FizzBuzz(int maxNumber)
    {
        //Plausibilitäts prüfung
        if (maxNumber &lt; 1)throw new ArgumentException("Nur Zahlen größer 0 sind erlaubt");
        if (maxNumber &gt; 100000) throw new ArgumentException("Nur Zahlen kleiner oder gleich 100000 sind erlaubt");

        //Liste anlegen
        List&lt;string&gt; words = new List&lt;string&gt;();

        //Alle Zahlen durchlaufen und prüfen
        for (int curNumber = 1; curNumber &lt;= maxNumber; curNumber++)
        {
            //Zahl durch n und m teilbar?
            if ((curNumber % _n) == 0 &#038;&#038; (curNumber % _m) == 0)
                words.Add("FizzBuzz");
            else if ((curNumber % _m) == 0)
                words.Add("Buzz");
            else if ((curNumber % _n) == 0)
                words.Add("Fizz");
            else
                words.Add(curNumber.ToString());
        }

        //Ergebniss zurückliefern
        return words;
    }
}
</code></pre>
<p>Das ist natürlich nur eine von vielen Varianten einen FizzBuzz zu implementieren. Der Ansatz bei dieser Implementierung ist eine Klasse mit einer Funktion, die alle Varianten enthält. Versucht man eine Erweiterung mit beliebig vielen Fizz-Buzz-Zahlen und Wörtern, würde man die Zahl/Wort Kombination wahrscheinlich in einem Dicitonary<int, string> ablegen und den zusammengesetzten String (FizzBuzz) für jeden Key des Dictionarys erweitern. Diese Lösung funktioniert nur, weil der Alorithmus zum Ermitteln des FizzBuzz gleich ist und nur durch eine Zahl parametrisiert ist. Ändert sich der Algorithmus oder ist der Algorithmus zum Zeitpunkt der Implementierung unbekannt, ist diese Lösung ungünstig oder funktioniert gar nicht mehr.</p>
<h3>Delegaten als Parametrierung</h3>
<p>Die Lösung, über die Werte zu Parametrieren reicht also nicht aus, da auch der Algorithmus und die Anzahl der Funkionen (Delegaten)variabel sein kann. Damit muss es eine Lösung geben, mit der ich Funktionen übergeben kann. Und von diesen Möglichkeiten gibt es in C# viele.</p>
<h4>Schnittstellen</h4>
<p> Der Klassiker ist eine Schnittstelle IFizzBuzz oder eine abstrakte Basisklasse mit unterschiedlichen Implementierungen für die verschiedenen Algorithmen. Mehr oder weniger parametrisierte Implementierungen dieser Schnittstelle werden an eine &#8220;Add&#8221; Methode des FizzBuzzers übergeben.</p>
<pre><code>
public class InterfaceFizzBuzzer
{
    private List&lt;IFizzBuzz&gt; buzzList = null;

    public InterfaceFizzBuzzer()
    {
        buzzList = new List&lt;IFizzBuzz&gt;();
    }

    public void Add(IFizzBuzz aBuzz)
    {
        buzzList.Add(aBuzz);
    }

    public IEnumerable&lt;string&gt; FizzBuzz(int maxNumber)
    {
        IList&lt;string&gt; result = new List&lt;string&gt;();

        for (int i = 1; i &lt;= maxNumber; i++)
        {
            // Result ermitteln
            var numberResult = string.Empty;
            foreach (var item in buzzList)
                currentRes += item.GetForNumber(i);

            // Ergebnis hinzufügen
            if (string.IsNullOrEmpty(numberResult))
                result.Add(i.ToString());
            else
                result.Add(numberResult);
        }

        return result;
    }
</code></pre>
<p>Die Schnittstelle mit einer entsprechenden Implementierung sieht dann wie folgt aus:</p>
<pre><code>
public interface IFizzBuzz
{
    string GetForNumber(int number);
}
class SimpleFizzBuzzImpl : IFizzBuzz
{
    private int _baseNumber;
    private string _word;

    public SimpleFizzBuzzImpl(int baseNumber, string word)
    {
        _baseNumber = baseNumber;
        _word = word;
    }

    public string GetForNumber(int number)
    {
        if (number % _baseNumber == 0) return _word;
        return string.Empty;
    }
}
</code></pre>
<h4>Lamba Expressions</h4>
<p>Lamba Expressions finde ich für kleinen Aufgaben genial. Man kann Logik an eine Funktion übergeben, ohne dafür entsprechende Schnittstellen, Delegaten oder abstrakte Basisklassen zu definieren. Der besondere Charme liegt dabei in der Übergabe in Logik, die nur einmal benutzt wird, wie bei &#8220;where&#8221; in LINQ. Die Lamba-Version des FizzBuzzer hat auch eine &#8220;Add&#8221; Methode, nimmt aber einen Parameter vom Typ Func&lt;int, string&gt; statt des Interfaces an.</p>
<pre><code>
public class LambdaFizzBuzzer
{
    private List&lt;Func&lt;int, string&gt;&gt; buzzList = null;

    public LambdaFizzBuzzer()
    {
        buzzList = new List&lt;Func&lt;int, string&gt;&gt;();
    }

    public void Add(Func&lt;int, string&gt; aBuzz)
    {
        buzzList.Add(aBuzz);
    }

    public IEnumerable&lt;string&gt; FizzBuzz(int maxNumber)
    {
        for (int i = 1; i &lt;= maxNumber; i++)
        {
            var currentRes = string.Empty;
            foreach (var item in buzzList)
                currentRes += item.Invoke(i);
            yield return string.IsNullOrEmpty(currentRes) ? i.ToString() : currentRes;
        }
    }
}
</code></pre>
<p>Die Verwendung des FizzBuzzer ist dann entsprechend mit Lambda-Expressions.</p>
<pre><code>
LambdaFizzBuzzer fb = new LambdaFizzBuzzer();
fb.Add(i => (i % 3 == 0) ? "Fizz" : string.Empty);
fb.Add(i => (i % 5 == 0) ? "Buzz" : string.Empty);
</code></pre>
<h3>Fazit</h3>
<p>Es gibt unterschiedliche Varianten, Code als Parameter an eine Methode zu übergeben. Interfaces und Lambda Expressions habe ich hier gezeigt. Delegaten und abstrakte Basisklasse sind hier zwar nicht vorgestellt, unterscheiden sich aber konzeptionell nicht großartig von Interfaces und Lambda Expressions. Der architekturelle Unterschied oder Frage ist, ob man den Code wiederverwenden möchte und die Algorithmen Teil der Architektur sind oder ob es &#8220;flüchtiger Code&#8221; wie Lambda Expressions sind.</p>
]]></content:encoded>
			<wfw:commentRss>http://mentzel.name/2010/05/10/coding-kata-fizzbuzz/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>NullReferenceException?</title>
		<link>http://mentzel.name/2010/05/09/nullreferenceexception/</link>
		<comments>http://mentzel.name/2010/05/09/nullreferenceexception/#comments</comments>
		<pubDate>Sun, 09 May 2010 20:31:51 +0000</pubDate>
		<dc:creator>Thomas Mentzel</dc:creator>
				<category><![CDATA[C#]]></category>
		<category><![CDATA[DotNetGerman Bloggers]]></category>
		<category><![CDATA[Extension Method]]></category>

		<guid isPermaLink="false">http://mentzel.name/?p=179</guid>
		<description><![CDATA[In einem Kommentar einer meiner Blogeinträge kam die Frage auf, ob man nicht eine Extension Method für das &#8216;??&#8217;-Konstrukt machen kann. Da habe ich mir die Frage gestellt, ob das überhaupt geht. Denn letztlich würde ja eine Methode auf einem Null-Objekt aufgerufen. Hier ein bißchen Code um den Sachverhalt zu verdeutlichen. public class Program { [...]]]></description>
			<content:encoded><![CDATA[<p>In einem Kommentar einer meiner Blogeinträge kam die Frage auf, ob man nicht eine Extension Method für das &#8216;??&#8217;-Konstrukt machen kann. Da habe ich mir die Frage gestellt, ob das überhaupt geht. Denn letztlich würde ja eine Methode auf einem Null-Objekt aufgerufen.  Hier ein bißchen Code um den Sachverhalt zu verdeutlichen.</p>
<p>
<pre><code>
    public class Program
    {
        static void Main(string[] args)
        {
            // NULL-String deklarieren
            string str = null;
            // Funktioniert NICHT, da es eine Klassenmethode ist
            var bar = str.Contains("elo");

            // Funktioniert, da es eine Extension Method ist
            var foo = str.IfIsNull("Hello");
            // Funktioniert auch! isFoo == "foo"
            var isFoo = ((string)null).IfIsNull("foo");
        }
    }

    internal static class StingExtension
    {
        public static string IfIsNull(this string hello, string alternateText)
        {
            if (hello == null) return alternate;
            return hello;
        }
    }
</code></pre>
</p>
<p>Aber warum funktioniert das? Weder erscheint eine Compiler Fehlermeldung, noch der ReSharper jammert und zur Laufzeit wird auch keine Exception geworfen. Der Grund liegt in der Übersetzung von Extension Methods durch den Compiler. Eine Extension Method erscheint zwar als Klassenmethode, wird aber durch den statischen Aufruf der Methode ersetzt. Und eine statischer Methodenaufruf ist für Null-Objekte möglich und die Prüfung innerhalb der Methode verhindert die Exception. Damit wirft der Aufruf einer Extension Method auf &#8220;Null&#8221;-Objekte keine NullReferenceException. Klingt komisch, ist aber so.</p>
]]></content:encoded>
			<wfw:commentRss>http://mentzel.name/2010/05/09/nullreferenceexception/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Was hast Du vor über zehn Jahren programmiert? Update 1</title>
		<link>http://mentzel.name/2010/04/10/was-hast-du-vor-uber-zehn-jahren-programmiert-update-1/</link>
		<comments>http://mentzel.name/2010/04/10/was-hast-du-vor-uber-zehn-jahren-programmiert-update-1/#comments</comments>
		<pubDate>Sat, 10 Apr 2010 12:56:45 +0000</pubDate>
		<dc:creator>Thomas Mentzel</dc:creator>
				<category><![CDATA[Allgemeines]]></category>
		<category><![CDATA[Programmieren]]></category>

		<guid isPermaLink="false">http://thomas.mentzel.name/?p=91</guid>
		<description><![CDATA[Nach langer Zeit habe ich mit endlich die Zeit genommen und meine CD-Kiste aufgeräumt. Gefühlte 1000 CDs mit Linux Distrubutionen aus der Ausbildung, PC-Backups aus der Jahrtausendwende, Fotos und natürlich Daten Backups. Darunter waren auch 3 CDs mit Software aus vergangenen Tagen. Und so kann ich endlich auch Quellcode und Software (!) von vor über [...]]]></description>
			<content:encoded><![CDATA[<p>Nach langer Zeit habe ich mit endlich die Zeit genommen und meine CD-Kiste aufgeräumt. Gefühlte 1000 CDs mit Linux Distrubutionen aus der Ausbildung, PC-Backups aus der Jahrtausendwende, Fotos und natürlich Daten Backups. Darunter waren auch 3 CDs mit Software aus vergangenen Tagen. Und so kann ich endlich auch Quellcode und Software (!) von vor über 10 Jahren präsentieren.</p>
<h1>Mastermind</h1>
<p>Das Spiel Mastermind hat mich eine Zeit begleitet. Der erste Anlauf mit Turbo Pascal hatte geschätzt 500 Zeilen Code um die Eingabe zu validieren und das Ergebnis zu präsentieren. Später habe ich dann mit VB 3 eine neue Version mit Control-Arrays und viel schlankerem Validierungscode geschieben, ca. 30 Zeilen. Leider konnte ich den SourceCode nicht finden, aber dafür könnt ihr <a href='http://mentzel.name/2010/04/10/was-hast-du-vor-uber-zehn-jahren-programmiert-update-1/mastermind_vb/' rel='attachment wp-att-143'>hier das Programm herunterladen</a> (incl. vbrun300.dll).</p>
<h1>Client-Server-Chat</h1>
<p>Das bis dahin größte Projekt war eine Client Server Applikation. Geschrieben habe ich das Programm mit Delphi 3, eine sehr lange Heimat für meine Programmierung. Mit Delphi habe ich die ersten multithreaded Applikationen entwickelt, Datenbankapplikationen geschrieben und Client Server Applikationen gebaut.<br />
Das geniale an diesem Projekt war nicht der Chat, der über eine WinSock Client-Server TCP Verbindung statt fand sondern das &#8220;Malbrett&#8221;. Mit dieser Zeichenfläche konnten mehrere Benutzer an einem Bild malen. Falls jemand an dem Programm interessiert ist, könnt ihr die <a rel="attachment wp-att-131" href="http://mentzel.name/2010/04/10/was-hast-du-vor-uber-zehn-jahren-programmiert-update-1/intrachat21_delphi/">Sourcen und das Setup hier herunterladen</a>.
</p>
<div id="attachment_138" class="wp-caption aligncenter" style="width: 310px"><a href="http://mentzel.name/?attachment_id=138"><img class="size-medium wp-image-138" title="IntraChat_ScreenShort" src="http://mentzel.name/wp-content/uploads/2010/05/IntraChat_ScreenShort-300x274.png" alt="Screenshots des IntraChat" width="300" height="274" /></a><p class="wp-caption-text">Screenshots des IntraChat</p></div>
<p>Hier ist noch ein bißchen Turbo Pascal Code. Ich habe mal den Code des &#8220;Malfensters&#8221; eingefügt. Man sieht, dass die Kommunikation über ein WinSock Control funktioniert.</p>
<p>
<pre><code>
unit uniMalen;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  Menus, Buttons, ExtCtrls, StdCtrls, Spin, ColorGrd;

type TMalen = class(TObject)
            x1, x2, y1, y2, Dicke: Integer;
            Farbe: TColor;
            Werkzeug: Char;
            Absender: ShortString;
     end;
type
  TfrmMalen = class(TForm)
    imgPapier: TImage;
    MainMenu1: TMainMenu;
    Fenster1: TMenuItem;
    Schliessen1: TMenuItem;
    spbRectangle: TSpeedButton;
    spbEllipse: TSpeedButton;
    speWidth: TSpinEdit;
    Label1: TLabel;
    cdbColor: TColorDialog;
    ShapeColor: TShape;
    Label2: TLabel;
    spbLine: TSpeedButton;
    N1: TMenuItem;
    Neu1: TMenuItem;
    spbPixel: TSpeedButton;
    tmrPuffer: TTimer;
    procedure Schliessen1Click(Sender: TObject);
    procedure imgPapierMouseMove(Sender: TObject; Shift: TShiftState; X,
      Y: Integer);
    procedure imgPapierMouseUp(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure GetPaint(text: ShortString);
    procedure Send(Text: ShortString);
    procedure imgPapierMouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure FormCreate(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure ShapeColorMouseUp(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure tmrPufferTimer(Sender: TObject);
    procedure Neu1Click(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

procedure SendToPuffer(MyWerkzeug: Char);

var
  frmMalen: TfrmMalen;
  Startx, Starty, Currentx, Currenty: Integer;
  LMBGedruckt, MMBGedruckt, RMBGedruckt: Boolean;
  MPuffer: TList;
  Malen: TMalen;

implementation

uses uniMain;

{$R *.DFM}

procedure SendToPuffer(MyWerkzeug: Char);
// var text: String;
begin
        with Malen do begin
             x1 := Startx;
             y1 := Starty;
             x2 := Currentx;
             y2 := Currenty;
             Dicke := frmMalen.SpeWidth.Value;
             Farbe := frmMalen.ShapeColor.Brush.Color;
             Werkzeug := MyWerkzeug;
             Absender := frmMain.csoClient.Socket.LocalHost;
        end;
        MPuffer.Add(Malen);

{     Text := '%p%' + Malen.Werkzeug + '%' + IntToStr(Malen.x1) + '%' + IntToStr(Malen.y1) + '%' + IntToStr(Malen.x2) + '%' + IntToStr(Malen.y2) + '%' + IntToStr(Malen.Dicke) + '%';
     Text := Text + ColorToString(Malen.Farbe) + '%' + Malen.Absender + '%';
     frmMalen.Send(Text);
}end;

procedure TfrmMalen.Send(Text: ShortString);
begin
     frmMain.csoClient.Socket.SendText(Text);
end;

procedure TfrmMalen.GetPaint(Text: ShortString);
begin
     imgPapier.Canvas.Brush.Color := StringToColor(GetString('%', text, 7));
     imgPapier.Canvas.Pen.Color := imgPapier.Canvas.Brush.Color;
     imgPapier.Canvas.Pen.Width := GetInteger('%', Text, 6);
     imgPapier.Canvas.Brush.Style := bsClear;
     Case text[2] of
          'n': Begin
               imgPapier.Canvas.Brush.Color := clWhite;
               imgPapier.Canvas.Pen.Color := imgPapier.Canvas.Brush.Color;
               imgPapier.Canvas.Pen.Width := 1;
               imgPapier.Canvas.Brush.Style := bsSolid;
               frmMalen.imgPapier.Canvas.Rectangle(0, 0, imgPapier.Width, imgPapier.Height);
               end;
          'p': Begin
               frmMalen.imgPapier.Canvas.Pixels[GetInteger('%', Text, 2), GetInteger('%', Text, 3)] := imgPapier.Canvas.Brush.Color;
          end;
          'r': Begin
               frmMalen.imgPapier.Canvas.Rectangle(GetInteger('%', Text, 2), GetInteger('%', Text, 3), GetInteger('%', Text, 4), GetInteger('%', Text, 5));
          end;
          'e': Begin
               frmMalen.imgPapier.Canvas.Ellipse(GetInteger('%', Text, 2), GetInteger('%', Text, 3), GetInteger('%', Text, 4), GetInteger('%', Text, 5));
          end;
          'm': Begin
               frmMalen.imgPapier.Canvas.MoveTo(GetInteger('%', Text, 2), GetInteger('%', Text, 3));
               frmMalen.imgPapier.Canvas.LineTo(GetInteger('%', Text, 4), GetInteger('%', Text, 5));
          end;
     end; //Case
end;

procedure TfrmMalen.Schliessen1Click(Sender: TObject);
begin
     frmMalen.hide;
end;

procedure TfrmMalen.imgPapierMouseMove(Sender: TObject; Shift: TShiftState;
  X, Y: Integer);
begin
     Currentx := x; Currenty := y;
     If LMBGedruckt then begin
      frmMalen.Canvas.Pen.Width := speWidth.Value;
      If spbRectangle.Down then begin
         frmMalen.ImgPapier.Refresh;
         frmMalen.Canvas.Brush.Style := bsClear;
         frmMalen.Canvas.Rectangle(Startx + frmMalen.ImgPapier.Left, Starty + frmMalen.ImgPapier.Top, Currentx + frmMalen.ImgPapier.Left, Currenty + frmMalen.ImgPapier.Top);
      end;
      If spbEllipse.Down then begin
         frmMalen.ImgPapier.Refresh;
         frmMalen.Canvas.Brush.Style := bsClear;
         frmMalen.Canvas.Ellipse(Startx + frmMalen.ImgPapier.Left, Starty + frmMalen.ImgPapier.Top, Currentx + frmMalen.ImgPapier.Left, Currenty + frmMalen.ImgPapier.Top);
      end;
      if spbLine.Down then begin
         frmMalen.ImgPapier.Refresh;
         frmMalen.Canvas.Brush.Style := bsClear;
         frmMalen.Canvas.MoveTo(Startx + frmMalen.ImgPapier.Left, Starty + frmMalen.ImgPapier.Top);
         frmMalen.Canvas.LineTo(Currentx + frmMalen.ImgPapier.Left, Currenty + frmMalen.ImgPapier.Top);
      end;
     end;
end;

procedure TfrmMalen.imgPapierMouseUp(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
   Currentx := x; currenty := y;
   IF LMBGedruckt then begin
      If spbRectangle.Down then SendToPuffer('r');
      If spbEllipse.Down then SendToPuffer('e');
      if spbLine.Down then SendToPuffer('m');
   end;
   LMBGedruckt := false;
   MMBGedruckt := false;
   RMBGedruckt := false;
end;

procedure TfrmMalen.imgPapierMouseDown(Sender: TObject;
  Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
   Startx :=  X; Starty := Y;
   If Button = mbLeft then LMBGedruckt := true;
   If Button = mbMiddle then MMBGedruckt := true;
   If Button = mbRight then RMBGedruckt := true;
end;

procedure TfrmMalen.FormCreate(Sender: TObject);
begin
   frmMalen.imgPapier.Canvas.Create;
   LMBGedruckt := false;
   MMBGedruckt := false;
   RMBGedruckt := false;
end;

procedure TfrmMalen.FormClose(Sender: TObject; var Action: TCloseAction);
begin
     MPuffer.Free;
     Malen.Free;
end;

procedure TfrmMalen.ShapeColorMouseUp(Sender: TObject;
  Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
     frmMalen.cdbColor.Execute;
     frmMalen.ShapeColor.Brush.Color := frmMalen.cdbColor.Color;
     frmMalen.Canvas.Brush.Color := frmMalen.cdbColor.Color;
     frmMalen.Canvas.Pen.Color := frmMalen.cdbColor.Color;
end;

procedure TfrmMalen.tmrPufferTimer(Sender: TObject);
var Text: ShortString;
begin
   If MPuffer.Count &gt; 0 then begin
     Malen := MPuffer.Items[0];
     Text := '%p%' + Malen.Werkzeug + '%' + IntToStr(Malen.x1) + '%' + IntToStr(Malen.y1) + '%' + IntToStr(Malen.x2) + '%' + IntToStr(Malen.y2) + '%' + IntToStr(Malen.Dicke) + '%';
     Text := Text + ColorToString(Malen.Farbe) + '%' + Malen.Absender + '%';
     frmMalen.Send(Text);
     MPuffer.Delete(0);
   end else begin
       MPuffer.Clear;
   end;
end;

procedure TfrmMalen.Neu1Click(Sender: TObject);
begin
     SendToPuffer('n');
end;

begin
     MPuffer := TList.Create;
     Malen := TMalen.Create;
end.
</code></pre></p>
]]></content:encoded>
			<wfw:commentRss>http://mentzel.name/2010/04/10/was-hast-du-vor-uber-zehn-jahren-programmiert-update-1/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Was hast Du vor über zehn Jahren programmiert?</title>
		<link>http://mentzel.name/2010/03/05/was-hast-du-vor-uber-zehn-jahren-programmiert/</link>
		<comments>http://mentzel.name/2010/03/05/was-hast-du-vor-uber-zehn-jahren-programmiert/#comments</comments>
		<pubDate>Fri, 05 Mar 2010 21:17:50 +0000</pubDate>
		<dc:creator>Thomas Mentzel</dc:creator>
				<category><![CDATA[Allgemeines]]></category>
		<category><![CDATA[Programmieren]]></category>

		<guid isPermaLink="false">http://thomas.mentzel.name/?p=72</guid>
		<description><![CDATA[Hier ist noch eine Antwort auf den Twitter Tweet, in dem die Frage aufkam, was man vor 10 Jahren programmiert hat. Vor genau 10 Jahren steckte ich mitten im Abitur und habe mit einem Freund zusammen ein Netzwerkmanagement-Tool entwickelt. Entwicklungsumgebung war Borland Delphi (Client) und Borland C++ Builder (Server). Damit konnten wir in dem kleinen [...]]]></description>
			<content:encoded><![CDATA[<p>Hier ist noch eine Antwort auf den Twitter Tweet, in dem die Frage aufkam, was man vor 10 Jahren programmiert hat.<br />
Vor genau 10 Jahren steckte ich mitten im Abitur und habe mit einem Freund zusammen ein Netzwerkmanagement-Tool entwickelt. Entwicklungsumgebung war Borland Delphi (Client) und Borland C++ Builder (Server). Damit konnten wir in dem kleinen Schulnetzwerk Programme auf den Clients ausführen, Informationen über den Status abrufen und die Clients neu Starten. Der Server hatte ein fest codiertes Bild des Computerraumes mit den Clients, dem Staus und den Funktionen. Der Code ist leider im Laufe der Zeit verschwunden.</p>
<p>Im Jahr 1997 habe ich mir die Mühe gemacht, nicht &#8220;nur&#8221; die Aufgaben zu lösen sondern auch die Lösungen schriftlich auszuarbeiten. Die Rede ist von meiner Teilnahme am 16. Bundeswettbewerb Informatik. Meine Ausarbeitung war leider so schlecht, dass ich noch nicht einmal die erste Runde geschafft habe. Für alle, die sich den Aufgaben auch einmal stellen möchten, sind <a href="http://www.bwinf.de/uploads/media/download/161aufgaben.pdf">hier</a> die Aufgaben.</p>
<p>Das erste Programm oder der erste Algorithmus, an den ich mich erinnern kann war -wie könnte es anders sein- ein Programm zum Berechnen von Primzahlen. Es war 1993(!) auf einem C64 und die Berechnung hat echt lange gedauert. Der Nadel-Drucker hat mich Nacht um Nacht wach gehalten, um alle paar Minuten eine Zeile mit 5 oder 6 Primzahlen zu drucken&#8230;auf Endlospapier -Gott hab es seelig.<br />
Ich werde wohl die nächsten Tage mal meine alten Disketten vom Speicher holen und mal schauen, was sich dort alles findet.</p>
]]></content:encoded>
			<wfw:commentRss>http://mentzel.name/2010/03/05/was-hast-du-vor-uber-zehn-jahren-programmiert/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>VS2008 + TFS2010 = TF31002</title>
		<link>http://mentzel.name/2009/12/04/vs2008-tfs2010-tf31002/</link>
		<comments>http://mentzel.name/2009/12/04/vs2008-tfs2010-tf31002/#comments</comments>
		<pubDate>Fri, 04 Dec 2009 13:55:07 +0000</pubDate>
		<dc:creator>Thomas Mentzel</dc:creator>
				<category><![CDATA[Clean Code]]></category>
		<category><![CDATA[TFS2010]]></category>
		<category><![CDATA[Bug]]></category>
		<category><![CDATA[TF31002]]></category>
		<category><![CDATA[VS2008]]></category>

		<guid isPermaLink="false">http://thomas.mentzel.name/?p=63</guid>
		<description><![CDATA[Team Foundation Server 2010 ist eine interessante Weiterentwicklung des Team Foundation Servers 2008. Da möchte man gerne mit dem &#8220;alten&#8221; Visual Studio 2008 diesen benutzen. Das geht auch, wenn man zum Visual Studio mit Team Explorer folgendes installiert: Visual Studio 2008 SP1 (hier) Hotfix für TFS 2010 (hier) Nun gibt es nur noch eine Sache [...]]]></description>
			<content:encoded><![CDATA[<p>Team Foundation Server 2010 ist eine interessante Weiterentwicklung des Team Foundation Servers 2008. Da möchte man gerne mit dem &#8220;alten&#8221; Visual Studio 2008 diesen benutzen. Das geht auch, wenn man zum Visual Studio mit Team Explorer folgendes installiert:</p>
<ol>
<li>Visual Studio 2008 SP1 (<a href="http://www.microsoft.com/downloads/details.aspx?FamilyId=FBEE1648-7106-44A7-9649-6D9F6D58056E&#038;displaylang=en">hier</a>)</li>
<li>Hotfix für TFS 2010 (<a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=CF13EA45-D17B-4EDC-8E6C-6C5B208EC54D&#038;displaylang=en">hier</a>)</li>
</ol>
<p>Nun gibt es nur noch eine Sache zu berücksichtigen, die mich mehrere Stunden gekostet hat: <strong>Der Team Explorer 2008 kann nicht mit Team Project Collections umgehen</strong>. Also muss zum einen die URL vollständig angegeben werden und zusätzlich der Name der Team Project Collection angehängt werden.</p>
<div id="attachment_156" class="wp-caption aligncenter" style="width: 310px"><a href="http://mentzel.name/2009/12/04/vs2008-tfs2010-tf31002/tfs2010_tf31002/" rel="attachment wp-att-156"><img src="http://mentzel.name/wp-content/uploads/2009/12/tfs2010_tf31002-300x189.png" alt="Team Foundation Server 2010 mit Visual Studio 2008" title="tfs2010_tf31002" width="300" height="189" class="size-medium wp-image-156" /></a><p class="wp-caption-text">Visual Studio 2008 Konfiguration</p></div>
]]></content:encoded>
			<wfw:commentRss>http://mentzel.name/2009/12/04/vs2008-tfs2010-tf31002/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Dreimol NULL es NULL, es NULL</title>
		<link>http://mentzel.name/2009/09/14/dreimol-null-es-null-es-null/</link>
		<comments>http://mentzel.name/2009/09/14/dreimol-null-es-null-es-null/#comments</comments>
		<pubDate>Mon, 14 Sep 2009 06:41:47 +0000</pubDate>
		<dc:creator>Thomas Mentzel</dc:creator>
				<category><![CDATA[C#]]></category>

		<guid isPermaLink="false">http://thomas.mentzel.name/?p=53</guid>
		<description><![CDATA[Wer kennt das nicht: &#8220;NullReferenceException&#8221;. Entweder prüft man im Code ständig auf NULL oder man riskiert unschöne Programmabstürze. Durch ständige &#8220;if (&#8230; == null) {} else {}&#8221; Blöcke wird der Code schnell unleserlich und damit schwierig zu verstehen. Hier sind ein paar Varianten von NULL-Prüfungen und anderen schlanken, aber effektiven Varianten, um den Code leserlicher [...]]]></description>
			<content:encoded><![CDATA[<p>Wer kennt das nicht: &#8220;NullReferenceException&#8221;. Entweder prüft man im Code ständig auf NULL oder man riskiert unschöne Programmabstürze. Durch ständige &#8220;if (&#8230; == null) {} else {}&#8221; Blöcke wird der Code schnell unleserlich und damit schwierig zu verstehen. Hier sind ein paar Varianten von NULL-Prüfungen und anderen schlanken, aber effektiven Varianten, um den Code leserlicher zu gestalten.</p>
<h3>Beispiel</h3>
<p>Das folgende Beispiel zeigt eine klassische &#8220;if&#8230;then..else&#8221; Abfrage mit vielen Zeilen Code um lediglich den Standardtext &#8220;leer&#8221; zurück zu geben, falls die Eigenschaft &#8220;Name&#8221; des Objekt NULL ist, ansonsten die Eigenschaft &#8220;Name&#8221; des Objektes.</p>
<p><code>
<pre>
if (myObject.Name == null)
{
    return "leer";
}
else
{
    return myObject.Name;
}
</pre>
<p></code></p>
<h3>Variante 1</h3>
<p><code>
<pre>
if (myObject.Name == null)
    return "leer";
else
    return myObject.Name;
</pre>
<p></code></p>
<h3>Variante 2</h3>
<p><code>
<pre>
// entweder so ...
myObject.Name == null ? return "leer" : return myObject.Name;
// oder so ...
return myObject.Name == null ? "leer" : myObject.Name;
</pre>
<p></code></p>
<h3>Variante 3</h3>
<p><code>
<pre>
return myObject.Name ?? "leer";
</pre>
<p></code></p>
]]></content:encoded>
			<wfw:commentRss>http://mentzel.name/2009/09/14/dreimol-null-es-null-es-null/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Wie gefährlich ist “cool”?</title>
		<link>http://mentzel.name/2009/06/20/wie-gefhrlich-ist-cool/</link>
		<comments>http://mentzel.name/2009/06/20/wie-gefhrlich-ist-cool/#comments</comments>
		<pubDate>Sat, 20 Jun 2009 07:17:57 +0000</pubDate>
		<dc:creator>Thomas Mentzel</dc:creator>
				<category><![CDATA[Allgemeines]]></category>
		<category><![CDATA[Architektur]]></category>

		<guid isPermaLink="false">http://thomas.mentzel.name/2009/06/20/wie-gefhrlich-ist-cool/</guid>
		<description><![CDATA[Schon einmal einen Programmierer sagen hören “Diese neue Technologie ist cool. Die sollten wir einsetzen”. Hört man auf den Programmierer und setzt die Technologie einfach ein? Wie ist das denn wenn der Kunde sagt “Diese neue Technologie ist cool. Die solltet ihr einsetzen”. Sollte man die Technologie jetzt einsetzen? Neue Technologien bieten auch neue Chancen [...]]]></description>
			<content:encoded><![CDATA[<p>Schon einmal einen Programmierer sagen hören “Diese neue Technologie ist cool. Die sollten wir einsetzen”. Hört man auf den Programmierer und setzt die Technologie einfach ein? Wie ist das denn wenn der Kunde sagt “Diese neue Technologie ist cool. Die solltet ihr einsetzen”. Sollte man die Technologie jetzt einsetzen? Neue Technologien bieten auch neue Chancen für das Produkt und neue Motivation für Entwickler.</p>
<p>Der erste Schritt liegt auf der Hand. Mittels eines Proof Of Concept wird die neue Technologie getestet und verifiziert, ob die Technologie zur Architektur passt. Aber wie geht es weiter? Die folgenden fünf Fragen geben eine Entscheidungshilfe für die Entscheidung.</p>
<ul>
<li>Erfüllt die Technologie die Anforderungen an die Architektur?</li>
<li>Will der Kunde diese Technologie haben?</li>
<li>Wollen die Entwickler diese Technologie einsetzen?</li>
<li>Wie groß ist der Einfluss der Technologie auf den bestehenden Code?</li>
<li>Wie leicht lässt sich diese Technologie bei einer Fehlauswahl wieder entfernen?</li>
</ul>
<p>Zu guter letzt muss wieder der Architekt entscheiden, aber doch bitte bewusst und nach objektiven Kriterien und nicht nach Bauchgefühl.</p>
]]></content:encoded>
			<wfw:commentRss>http://mentzel.name/2009/06/20/wie-gefhrlich-ist-cool/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Die 10 Gebote des Programmierens</title>
		<link>http://mentzel.name/2009/06/03/die-10-gebote-des-programmierens/</link>
		<comments>http://mentzel.name/2009/06/03/die-10-gebote-des-programmierens/#comments</comments>
		<pubDate>Wed, 03 Jun 2009 19:22:37 +0000</pubDate>
		<dc:creator>Thomas Mentzel</dc:creator>
				<category><![CDATA[Clean Code]]></category>
		<category><![CDATA[CCD]]></category>
		<category><![CDATA[Programmierrichtlinien]]></category>

		<guid isPermaLink="false">http://thomas.mentzel.name/?p=37</guid>
		<description><![CDATA[Heute wurde ich von einem Kollegen gebeten, aus meiner Sicht die 10 wichtigsten Regeln zum Programmieren aufzuschreiben. Diese Regeln sollen Programmierern helfen, besser und schneller stabilen Code zu programmieren. Hier sind meine 10 wichtigsten Regeln aus meiner heutigen Sicht. Zeit für Sauberkeit. Wenn du etwas machst, mache es direkt ordentlich. Später wirst du keine Lust [...]]]></description>
			<content:encoded><![CDATA[<p>Heute wurde ich von einem Kollegen gebeten, aus meiner Sicht die 10 wichtigsten Regeln zum Programmieren aufzuschreiben. Diese Regeln sollen Programmierern helfen, besser und schneller stabilen Code zu programmieren. Hier sind meine 10 wichtigsten Regeln aus meiner heutigen Sicht.</p>
<p><strong>Zeit für Sauberkeit.</strong> Wenn du etwas machst, mache es direkt ordentlich. Später wirst du keine Lust zum Aufräumen haben. Wer hat schon Lust tausende Zeilen von Code nachträglich zu kommentieren und aufzuräumen.</p>
<p><strong>Geh’ in kleinen Schritten.</strong> Definiere genau dein Ziel und teile es sinnvoll in möglichst kleine Schritte ein. Gestalte erst ein Formular und schreibe anschließend die Logik. Programmier die Logik in kleinen aber abgeschlossenen Schritten und nicht alles auf einmal.</p>
<p><strong>Erst denken, dann programmieren.</strong> Wenn du nicht in der Lage bist, dein Programm auf Papier zu formulieren, wirst du es erst recht nicht schaffen, dieses dann in Code umzusetzen.</p>
<p><strong>Buy it, don’t make it.</strong> Bevor du ein Modul programmierst, überlege ob es nicht bereits etwas Fertiges auf dem Markt gibt. Goggle ist dein Orakel: Frag was du suchst und Google wird dir mit OpenSource und kommerziellen Projekten antworten…ganz sicher!</p>
<p><strong>Fragen kostet nix.</strong> Es gibt immer jemanden, den man fragen kann. Also wenn du dir mit irgend etwas nicht sicher bist frag nach. 10 Minuten fragen bringt dich weiter als 3 Stunden ‘try and error’.</p>
<p><strong>Halte dich an Coding Guidelines.</strong> Coding Guidelines dienen dem allgemeinen Verständnis von Code. Jede Programmiersprache hat ein grundsätzliches Verständnis von “schönem Code”. Halte dich daran. Falls es in deinem Projekt keine Coding Guidelines gibt berufe dich auf allgemein gültige Regeln.</p>
<p><strong>Code muss verständlich sein-für alle.</strong> Du entwickelst zwar den Code, aber normalerweise mit anderen zusammen oder andere übernehmen unter Umständen deinen Code. Jeder muss verstehen können was du gemacht hast und warum du es gemacht hast. Sogar du musst noch nach Monaten oder Jahren den Code warten und erweitern können. Und bedenke immer: Je mehr du dokumentierst und deinen Code verständlich programmierst, umso weniger (blöde) Fragen muss man zum Code beantworten.</p>
<p><strong>Logging nicht vergessen.</strong> Du musst jederzeit die Möglichkeit haben, dein Programm auch nach der Auslieferung (intern fürs Testen oder beim Kunden in Produktion) verfolgen und debuggen zu können. Fehler müssen immer Persistiert werden. Das erste was der Anwender vergessen hat ist, was er gemacht hat und wie die Fehlermeldung lautete.</p>
<p><strong>Testen, testen, testen.</strong> Jeder würde jetzt schreiben, “Unit Testes sind das wichtigste” oder “Test Driven Development ist essentiell”. Es ist viel wichtiger, dass du Bestandteile deiner Applikation isoliert testen und dabei alle Variationen verifizieren kannst. Und wenn es <em>nur</em> eine Test-GUI ist, ist es immerhin ein Test und besser als nichts. (@Stefan Lieser: Sorry <img src='http://mentzel.name/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' />  )</p>
<p><strong>Mehrmals täglich einchecken.</strong> Wenn du kleine Arbeitspäckchen schnürst, kannst du auch mehrmals täglich diese nach dem Implementieren einchecken. Spätestens aber wenn du abends nach Hause gehst. Wichtig sind folgende Punkte für ein gutes und sicheres Einchecken:</p>
<ul>
<li>Code zuerst aktualisieren und kompilieren und erst dann einchecken.</li>
<li>Nur kompilierbaren Code einchecken.</li>
<li>Immer einen Kommentar für das Einchecken angeben.</li>
<li>Immer mit einem personalisierten Benutzerkonto Code einchecken.</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://mentzel.name/2009/06/03/die-10-gebote-des-programmierens/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Observer Pattern wird zum Message Dispatcher (I)</title>
		<link>http://mentzel.name/2009/05/05/observer-pattern-wird-zum-message-dispatcher/</link>
		<comments>http://mentzel.name/2009/05/05/observer-pattern-wird-zum-message-dispatcher/#comments</comments>
		<pubDate>Tue, 05 May 2009 20:28:52 +0000</pubDate>
		<dc:creator>Thomas Mentzel</dc:creator>
				<category><![CDATA[Architektur]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[Design Pattern]]></category>
		<category><![CDATA[Message Dispatcher]]></category>
		<category><![CDATA[Observer Pattern]]></category>

		<guid isPermaLink="false">http://thomas.mentzel.name/2009/05/05/observer-pattern-wird-zum-message-dispatcher/</guid>
		<description><![CDATA[Dieses mal ein etwas ausführlicher Blog zum Thema meines Vortrages bei bonn-to-code. Meine viel zu kurzen 20 Minuten hatten eine volle Agenda mit verschiedenen Varianten des Observer Pattern bis hin zu einem Message Dispatcher . Log geht’s!   Events statt Attach/Detach Das Observer Pattern nach GOF war den meisten (oder allen) Zuhörern bereits bekannt, also [...]]]></description>
			<content:encoded><![CDATA[<p>Dieses mal ein etwas ausführlicher Blog zum Thema meines <a href="http://mentzel.name/vortrage/#observer200904" target="_blank">Vortrages bei <a href="http://www.bonn-to-code.net" target="_blank">bonn-to-code</a>. Meine viel zu kurzen 20 Minuten hatten eine volle Agenda mit verschiedenen Varianten des Observer Pattern bis hin zu einem Message Dispatcher <img src='http://mentzel.name/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> . Log geht’s!</p>
<p><a href="http://mentzel.name/wp-content/uploads/2009/05/GOF_Observer.png"><img src="http://mentzel.name/wp-content/uploads/2009/05/GOF_Observer-300x99.png" alt="" title="Observer Pattern nach GOF" width="300" height="99" class="aligncenter size-medium wp-image-196" /></a>
<p> </p>
<h3>Events statt Attach/Detach</h3>
<p>Das <a href="http://de.wikipedia.org/wiki/Observer_(Entwurfsmuster)" target="_blank">Observer Pattern</a> nach GOF war den meisten (oder allen) Zuhörern bereits bekannt, also konnte direkt mit der ersten .NET Modifikation begonnen werden. Die Logik des Attach und Detach von Beobachtern lässt sich wunderbar durch Events und EventHandler ersetzen. Events implementieren genau diese Funktionalität: Eine Liste von Funktionen zu verwalten und letztlich diese aufzurufen. Durch diesen Umbau ist der Code deutlich schlanker geworden und der Verwaltungscode wurde aus dem Subjekt entfernt.</p>
<p><a href="http://mentzel.name/wp-content/uploads/2009/05/Event_Observer.png"><img src="http://mentzel.name/wp-content/uploads/2009/05/Event_Observer-300x73.png" alt="" title="Event Based Observer Pattern" width="300" height="73" class="aligncenter size-medium wp-image-197" /></a></p>
<h3>Statusänderungen im größeren Kontext</h3>
<p>Das Observer Pattern bietet eine sehr gute Möglichkeit, Statusänderungen an betroffene Ansichten durchzureichen. Dabei wird das Hollywood Prinzip (“Don’t call us, we call you”) beachtet, nachdem das Subjekt die Beobachter informiert und nicht die Beobachter regenmäßig das Subjekt überprüfen. Ein Problem entsteht, wenn mehrere Subjekte zu unterschiedlichen Zeitpunkten angezeigt werden sollen. Ein gutes Beispiel ist eine Liste aus Subjekten mit verschiedenen Vorschau-Ansichten. Nun wird es schwierig, das neue Subjekt an die unbekannte Anzahl an Ansichten zu senden.</p>
<p>Die Lösung hierfür ist ein SubjectNotifier mit statischen Events zum Verteilen von Nachrichten an alle Beobachter. Jeder Beobachter kann mittels SubjectStateChanged eine auf Statusänderung und mittels SubjectSelected auf eine Subjektänderung reagieren. Über die Raise* Methoden können beliebige Ansichten die entsprechenden Event auslösen, falls sich der Status oder das Subjekt geändert hat.</p>
<p><a href="http://mentzel.name/wp-content/uploads/2009/05/SubjectNotifier.png"><img src="http://mentzel.name/wp-content/uploads/2009/05/SubjectNotifier-300x81.png" alt="" title="Subject Notifier" width="300" height="81" class="aligncenter size-medium wp-image-198" /></a></p>
<h3>Fazit</h3>
<p>Diese Variante, Statusänderungen eines Subjekts über einen SubjectNotifier zu publizieren, hat mehrere Vorteile. Alle Subjekte (auch neue Instanzen) können über einen zentralen Dispatcher publiziert werden. Es erweitert das Hollywood Prinzip aus dem klassischen Observer Pattern insoweit, dass nicht nur der Beobachter mit DEM Subjekt verbunden ist, sondern das der Beobachter noch nicht einmal das Subjekt kennt sondern von irgendwelchen Subjekten benachrichtigt wird. Ein weiterer Vorteil ist, dass das Subjekt absolut keine Logik zum Verteilen und Verwalten von Statusänderungen enthält. Das Subjekt ist unabhängig von interner Verwaltungslogik die nur einzelne Applikationen betrifft und z.B. in Konsolenanwendung nicht benötigt wird.</p>
<p>… dieses war der erste Streich, doch der zweite folgt sogleich!</p>
]]></content:encoded>
			<wfw:commentRss>http://mentzel.name/2009/05/05/observer-pattern-wird-zum-message-dispatcher/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>.NET WebControl ist ein ActiveX</title>
		<link>http://mentzel.name/2009/03/05/net-webcontrol-ist-ein-activex/</link>
		<comments>http://mentzel.name/2009/03/05/net-webcontrol-ist-ein-activex/#comments</comments>
		<pubDate>Thu, 05 Mar 2009 19:46:27 +0000</pubDate>
		<dc:creator>Thomas Mentzel</dc:creator>
				<category><![CDATA[C#]]></category>
		<category><![CDATA[Exception]]></category>
		<category><![CDATA[ActiceX]]></category>
		<category><![CDATA[Fehler]]></category>
		<category><![CDATA[Internet Explorer]]></category>

		<guid isPermaLink="false">http://thomas.mentzel.name/2009/03/05/net-webcontrol-ist-ein-activex/</guid>
		<description><![CDATA[Ich habe ja meinen Augen nicht getraut als ich feststellen musste, dass das WebBrowser Control ein ActiveX ist. Da ich aber von anderen immer zunächst nur das beste denke habe ich mal in die Registry geschaut und siehe an, die GUID ist wirklich ein Internet Explorer Active X. Jetzt bleibt nur noch offen, ob die [...]]]></description>
			<content:encoded><![CDATA[<p>Ich habe ja meinen Augen nicht getraut als ich feststellen musste, dass das WebBrowser Control ein ActiveX ist.</p>
<p><a href="http://mentzel.name/wp-content/uploads/2009/03/vs_exception.png"><img src="http://mentzel.name/wp-content/uploads/2009/03/vs_exception.png" alt="" title="Visual Studio Exception" width="640" height="53" class="aligncenter size-full wp-image-192" /></a></p>
<p>Da ich aber von anderen immer zunächst nur das beste denke habe ich mal in die Registry geschaut und siehe an, die GUID ist wirklich ein Internet Explorer Active X.</p>
<p><a href="http://mentzel.name/wp-content/uploads/2009/03/ieframe_regedit.png"><img src="http://mentzel.name/wp-content/uploads/2009/03/ieframe_regedit.png" alt="" title="IE Frame Regedit" width="640" height="209" class="aligncenter size-full wp-image-193" /></a></p>
<p>Jetzt bleibt nur noch offen, ob die “Read Exception” direkt und unmittelbar damit zusammen hängt (bestimmt! <img src='http://mentzel.name/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' />  ) und was ich da gegen machen kann.</p>
<p><a href="http://mentzel.name/wp-content/uploads/2009/03/Bug_itextsharp_svn_revision_18.png"><img src="http://mentzel.name/wp-content/uploads/2009/03/Bug_itextsharp_svn_revision_18.png" alt="" title="Bug iTextSharp SVN Revision 18" width="482" height="146" class="aligncenter size-full wp-image-194" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://mentzel.name/2009/03/05/net-webcontrol-ist-ein-activex/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>AOP mit PostSharp</title>
		<link>http://mentzel.name/2009/03/03/aop-mit-postsharp/</link>
		<comments>http://mentzel.name/2009/03/03/aop-mit-postsharp/#comments</comments>
		<pubDate>Tue, 03 Mar 2009 20:38:38 +0000</pubDate>
		<dc:creator>Thomas Mentzel</dc:creator>
				<category><![CDATA[Architektur]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[Design Pattern]]></category>

		<guid isPermaLink="false">http://thomas.mentzel.name/2009/03/03/aop-mit-postsharp/</guid>
		<description><![CDATA[Nachdem ich mich die letzte Woche mit PostSharp beschäftigt habe schreibe ich hier nun mein Ergebnis: AOP mit PostSharp ist einfach genial. So einfach möchte ich es auch nicht machen, also etwas mehr Informationen. PostSharp ist ein Framework zum Implementieren von Aspekt Orientierter Programmierung (AOP). Das Ziel ist eine nachträgliche und separate Implementierung von Aspekten [...]]]></description>
			<content:encoded><![CDATA[<p class="example">Nachdem ich mich die letzte Woche mit PostSharp beschäftigt habe schreibe ich hier nun mein Ergebnis: <strong>AOP mit PostSharp ist einfach genial</strong>. So einfach möchte ich es auch nicht machen, also etwas mehr Informationen.</p>
<p>PostSharp ist ein Framework zum Implementieren von Aspekt Orientierter Programmierung (AOP). Das Ziel ist eine nachträgliche und separate Implementierung von Aspekten in eine Applikation. Klassische Beispiele hierfür sind Logging und Security. PostSharp ist so implementiert, dass die Aspekte mittels Attribut an Methoden, Eigenschaften usw. gehangen werden. Der Post-Compiler von PostSharp ändert nach dem Kompilieren durch Visual Studio die Assembly. PostSharp kann <a href="http://www.postsharp.org/">hier</a> heruntergeladen werden. Zum Abschluss noch ein interessanter Hinweis. PostSharp kopiert die Assemblies in das Ausgabeverzeichnis die auf dem Client benötigt werden. PostSharp muss auf den Client nicht installiert werden.</p>
<p><a href="http://mentzel.name/wp-content/uploads/2009/03/PostSharp_Funktionsweise.png"><img class="aligncenter size-full wp-image-189" title="Funktionsweise von Postaharp" src="http://mentzel.name/wp-content/uploads/2009/03/PostSharp_Funktionsweise.png" alt="" width="493" height="175" /></a></p>
<p><em>Funktionsweise von PostSharp (Bild: PostSharp)</em></p>
<p>Das folgende Beispiel zeigt eine DoSomething Methode, welche über einen Logging-Aspect nachträglich geloggt wird. Der Code der LoggingAspect Klasse zeigt die Implementierung der Aspects über das PostSharp Framework. Dem Projekt müssen die Referenzen auf die Assemblies &#8220;PostSharp.Laos&#8221; und &#8220;PostSharp.Public&#8221; hinzugefügt werden.</p>
<pre>    public class Program
    {
        public static int Main(string[] args)
        {
            DoSomething();

            Console.Read();
            return 0;
        }

        [LogAcpect()]
        private static void DoSomething()
        {
            Console.WriteLine("Hello World");
        }
    }

    [Serializable()]
    public class LogAcpect : OnMethodBoundaryAspect
    {
        public override void OnEntry(MethodExecutionEventArgs eventArgs)
        {
            Console.WriteLine("--- Calling: {0} ---", eventArgs.Method);
        }

        public override void OnExit(MethodExecutionEventArgs eventArgs)
        {
            Console.WriteLine("--- Leaving: {0} ---", eventArgs.Method);
        }

        public override void OnSuccess(MethodExecutionEventArgs eventArgs)
        {
            Console.WriteLine("--- Success: {0} ---", eventArgs.Method);
        }

        public override void OnException(MethodExecutionEventArgs eventArgs)
        {
            Console.WriteLine("--- Exception: {0} @ {1} ---", eventArgs.Exception.Message, eventArgs.Method);
        }
    }</pre>
<p>An dieser Stelle noch einen paar Hinweise. Die Klasse LogAspect muss als Serializable deklariert werden, ansonsten gibt es beim Starten einen Fehler. Weiterhin ist die Klasse LogAspect eine Attribut-Klasse und kann wie eine solche mit Eigenschaften und überladenen Konstruktoren implementiert werden. Der folgende Code zeigt eine disassemblierte Version der Funktion. Hier sieht man genau, welche Methoden an welcher Stelle aufgerufen werden und das man mittels FlowBehaviour eine Methode kontrolliert abbrechen kann und das eine Exception in der Aspect-Klasse nach &#8220;oben&#8221; durchgereicht wird.</p>
<pre>private static void DoSomething()
{
    MethodExecutionEventArgs ~laosEventArgs~1;
    try
    {
        ~laosEventArgs~1 = new MethodExecutionEventArgs(~PostSharp~Laos~Implementation.~targetMethod~1, null, null);
        ~PostSharp~Laos~Implementation.LogAcpect~1.OnEntry(~laosEventArgs~1);
        if (~laosEventArgs~1.FlowBehavior != FlowBehavior.Return)
        {
            Console.WriteLine("Hello World");
            ~PostSharp~Laos~Implementation.LogAcpect~1.OnSuccess(~laosEventArgs~1);
        }
    }
    catch (Exception ~exception~0)
    {
        ~laosEventArgs~1.Exception = ~exception~0;
        ~PostSharp~Laos~Implementation.LogAcpect~1.OnException(~laosEventArgs~1);
        switch (~laosEventArgs~1.FlowBehavior)
        {
            case FlowBehavior.Continue:
            case FlowBehavior.Return:
                return;
        }
        throw;
    }
    finally
    {
        ~PostSharp~Laos~Implementation.LogAcpect~1.OnExit(~laosEventArgs~1);
    }
}</pre>
<p>Die Implementierung eines Security-Aspect hängt von den Bedürfnissen der Applikation ab. In meinem aktuellen Projekt haben wir in einer Datenbank einem Benutzer eine oder mehrere Funktionen zugewiesen. Der SecurityAspect prüft gegen eine IFunctionProvider-Schnittstelle, ob dem Benutzer die entsprechenden Funktion zugeordnet wurde. Die Funktion wird über den Konstruktor der SecurityAspect-Attibutes angegeben. Besteht der Anwender die Sicherheitsabfrage nicht, wird eine SecurityException geworfen. Diese Exception kann mittels Try-Catch abgefangen werden. Eine solche Implementierung stellt sicher, dass Methoden nur dann ausgeführt werden, wenn die Sicherheitsrichtlinien erfüllt werden. Die GUI stellt selbstverständlich a priori sicher, dass eine solche Methode nicht aufgerufen werden kann, wenn der Anwender keine hinreichenden Berechtigungen besitzt.</p>
<pre>        [SecurityAcpect(FunctionEnumeration.DoSomething)]
        private static void DoSomething()
        {
            Console.WriteLine("Hello World");
        }</pre>
<p>Die aspektorientierte Programmierung ist nur ein Aspekt des Postsharp Frameworks. Die Stärke des Frameworks liegt in der, wie auch immer gearteten, nachträglichen Modifizierung des Codes.</p>
]]></content:encoded>
			<wfw:commentRss>http://mentzel.name/2009/03/03/aop-mit-postsharp/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Stsadm.exe mit eigenen Operationen erweitern</title>
		<link>http://mentzel.name/2009/03/02/stsadmexe-mit-eigenen-operationen-erweitern/</link>
		<comments>http://mentzel.name/2009/03/02/stsadmexe-mit-eigenen-operationen-erweitern/#comments</comments>
		<pubDate>Mon, 02 Mar 2009 08:25:18 +0000</pubDate>
		<dc:creator>Thomas Mentzel</dc:creator>
				<category><![CDATA[MOSS 2007]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[STSADM]]></category>

		<guid isPermaLink="false">http://thomas.mentzel.name/2009/03/02/stsadmexe-mit-eigenen-operationen-erweitern/</guid>
		<description><![CDATA[Das Erweitern des Tools “stsadm.exe” zum Verwalten des MOSS 2007 ist mit .NET nicht sehr aufwändig. Es muss eine Klasse geschrieben werden, welche die “ISPStsadmCommand” Schnittstelle implementiert. Die Assembly in der sich die Klasse befindet muss Signiert werden und anschließend muss eine XML Konfigurationsdatei, die eine Verbindung mit dem stsadm-Command herstellt, geschrieben werden. Dieses Beispiel [...]]]></description>
			<content:encoded><![CDATA[<p>Das Erweitern des Tools “stsadm.exe” zum Verwalten des MOSS 2007 ist mit .NET nicht sehr aufwändig. Es muss eine Klasse geschrieben werden, welche die “ISPStsadmCommand” Schnittstelle implementiert. Die Assembly in der sich die Klasse befindet muss Signiert werden und anschließend muss eine XML Konfigurationsdatei, die eine Verbindung mit dem stsadm-Command herstellt, geschrieben werden.</p>
<p>Dieses Beispiel ist in der Lage, eine Seite rekursiv zu löschen, da das “deleteweb” Command ist nicht in der Lage ist, ein SPWeb mit Unterseiten zu löschen.</p>
<p><code>
<pre>    /// &lt;summary&gt;
    /// Klasse für die Schnittstelle ISPStsadmCommand zum Bereitstellen des stsadm Befehls.
    /// &lt;/summary&gt;
    public class RDeleteWeb : ISPStsadmCommand
    {
        #region ISPStsadmCommand Members

        /// &lt;summary&gt;
        /// Anzeigen der Hilfe
        /// &lt;/summary&gt;
        public string GetHelpMessage(string command)
        {
            StringBuilder res = new StringBuilder();
            Assembly asm = Assembly.GetAssembly(this.GetType());
            res.AppendLine(&quot;Thomas Mentzel - (C) 2007 Softwareküche&quot;);
            res.AppendLine(&quot;STSADM Extensions Version &quot; + asm.ToString());
            res.AppendLine();
            res.AppendLine(&quot;usage:&quot;);
            res.AppendLine(&quot;   -url &lt;URL&gt;&quot;);
            res.AppendLine(&quot;&quot;);
            return res.ToString();
        }

        /// &lt;summary&gt;
        /// Einstiegspunkt üfr das STSADM
        /// &lt;/summary&gt;
        public int Run(string command, System.Collections.Specialized.StringDictionary keyValues, out string output)
        {
            Assembly asm = Assembly.GetAssembly(this.GetType());
            output = &quot;Thomas Mentzel - (C) 2007 Softwareküche&quot;;
            output += &quot;STSADM Extensions Version &quot; + asm.ToString();

            //Wenn kein Parameter, dann Infofenster
            if (keyValues.Count &lt;= 1)
            {
                output = GetHelpMessage(command);
                return 0;
            }

            // Nur Command &quot;RemoveInheritedPermissions&quot; durchführen
            if (String.Compare(command, &quot;RDeleteWeb&quot;, true) == 0)
            {
                output += DoRDeleteWeb(keyValues);
                return 0;
            }
            else
            {
                throw new InvalidOperationException(&quot;Funktion wird nicht unterstützt. &quot; + command);
            }
        }

        #endregion

        #region DoRDeleteWeb

        /// &lt;summary&gt;
        /// Recursive deletes then web and all subwebs.
        /// &lt;/summary&gt;
        private string RDeleteAWeb(SPWeb web)
        {
            StringBuilder res = new StringBuilder();
            res.AppendLine(&quot;Deleting &quot; + web.Url);

            if (web.Webs.Count &gt; 0)
            {
                foreach (SPWeb subweb in web.Webs)
                {
                    res.Append(RDeleteAWeb(subweb));
                }
            }
            web.Delete();

            return res.ToString();
        }

        /// &lt;summary&gt;
        /// Recursive deletes then web and all subwebs.
        /// &lt;/summary&gt;
        private string DoRDeleteWeb(System.Collections.Specialized.StringDictionary keyValues)
        {
            SPSite site = new SPSite(keyValues[&quot;url&quot;]);
            SPWeb web = site.OpenWeb();
            StringBuilder res = new StringBuilder();
            res.AppendLine(RDeleteAWeb(web));
            return res.ToString();
        }

        #endregion
    }</pre>
<p></code></p>
<p>Der nächste Schritt ist das Erzeugen einer signierten Assembly und das Erzeugen der XML Datei mit folgender Beispieldaten:</p>
<pre><code>&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot; ?&gt;
&lt;commands&gt;  

    &lt;command class=&quot;StsadmCommand.RDeleteWeb, StsadmCommand, Version=1.0.0.0, Culture=neutral, PublicKeyToken=affe000020021980&quot; name=&quot;RDeleteWeb&quot; /&gt;  

&lt;/commands&gt;</pre>
<p></code></p>
<p>Der .NET Reflector hilft dabei, die vollständigen Assembly-Informationen auszulesen. </p>
<p>Schließlich muss die Assembly nach “%CommonProgramFiles%Microsoft SharedWeb Server Extensions12bin” und das XML nach “%CommonProgramFiles%Microsoft SharedWeb Server Extensions12conf” kopiert werden. </p>
<p>Nun sollte beim Aufruf von “stsadm.exe” ohne Parameter eine Liste die Operation des “stsadm.exe” inklusive “rdeleteweb” erscheinen. </p>
]]></content:encoded>
			<wfw:commentRss>http://mentzel.name/2009/03/02/stsadmexe-mit-eigenen-operationen-erweitern/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>C# Extension Methods</title>
		<link>http://mentzel.name/2009/03/01/c-extension-methods/</link>
		<comments>http://mentzel.name/2009/03/01/c-extension-methods/#comments</comments>
		<pubDate>Sun, 01 Mar 2009 08:19:51 +0000</pubDate>
		<dc:creator>Thomas Mentzel</dc:creator>
				<category><![CDATA[C#]]></category>
		<category><![CDATA[Extension Method]]></category>

		<guid isPermaLink="false">http://thomas.mentzel.name/?p=3</guid>
		<description><![CDATA[Ich habe mich endlich mal mit den Extension Methods von C# auseinander gesetzt. Das ist ja um vieles einfacher als ich dachte Hier mal ein kleines Beispiel, das den String Datentyp um eine Methode &#8220;ToInt32()&#8221; erweitert. /// &#60;summary&#62; /// Erweiterungsfunktionen für Strings /// &#60;/summary&#62; public static class StringExtensions { /// &#60;summary&#62; /// Wandelt einen String [...]]]></description>
			<content:encoded><![CDATA[<p>Ich habe mich endlich mal mit den Extension Methods von C# auseinander gesetzt. Das ist ja um vieles einfacher als ich dachte <img src='http://mentzel.name/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' />  Hier mal ein kleines Beispiel, das den String Datentyp um eine Methode &#8220;ToInt32()&#8221; erweitert.
</p>
<p><code>
<pre>
    /// &lt;summary&gt;
    /// Erweiterungsfunktionen für Strings
    /// &lt;/summary&gt;
    public static class StringExtensions
    {
         /// &lt;summary&gt;
         /// Wandelt einen String in eine Zahl um.
         /// ExtensionMethod für den Datentyp "String"
         /// &lt;/summary&gt;
         /// &lt;param name="s"&gt;Erweiterter Datentyp&lt;/param&gt;
         /// &lt;returns&gt;&lt;/returns&gt;
         public static int ToInt32(this string s)
         {
             int res;

             // Umwandeln des String, sonst default zurück geben
             if (int.TryParse(s, out res))
                 return res;
             else
                 return default(int);
         }
    }
</pre>
<p></code></p>
<p>Die anschließende Verwendung ist denkbar einfach. Im IntelliSense des Visual Studio erscheint die Methode als ganz normale Methode der String Klasse. Diese kann wie jede andere Funktion z.B. &#8220;.ToString()&#8221; ausgewählt und benutzt werden.</p>
<p><code>
<pre>
    class Program
    {

        static void Main(string[] args)
        {
            string aNumberAsString = Console.ReadLine();

            Console.WriteLine("IsOdd: " + IsOdd(aNumberAsString.ToInt32()));
            Console.WriteLine("IsEven: " + IsEven(aNumberAsString.ToInt32()));

            Console.ReadKey();
        }

        public static bool IsEven(int number)
        {
            return (number % 2 == 0);
        }

        private static bool IsOdd(int number)
        {
            return (number % 2 == 1);
        }
    }
</pre>
<p></code></p>
]]></content:encoded>
			<wfw:commentRss>http://mentzel.name/2009/03/01/c-extension-methods/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
