<?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>build broken &#187; How-To</title>
	<atom:link href="http://blog.aztec-project.org/category/how-to/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.aztec-project.org</link>
	<description>but we can fix it! Sometimes :)</description>
	<lastBuildDate>Fri, 11 Jun 2010 12:52:34 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=abc</generator>
		<item>
		<title>Beispiel Model-View-Presenter mit WinForms</title>
		<link>http://blog.aztec-project.org/2010/02/16/beispiel-model-view-presenter-winforms/</link>
		<comments>http://blog.aztec-project.org/2010/02/16/beispiel-model-view-presenter-winforms/#comments</comments>
		<pubDate>Tue, 16 Feb 2010 07:48:46 +0000</pubDate>
		<dc:creator>Stefan Kölle</dc:creator>
				<category><![CDATA[How-To]]></category>
		<category><![CDATA[MVC]]></category>
		<category><![CDATA[Contract-First]]></category>
		<category><![CDATA[MVP]]></category>
		<category><![CDATA[WinForms]]></category>

		<guid isPermaLink="false">http://blog.aztec-project.org/?p=888</guid>
		<description><![CDATA[Im Teil 1 (MVP mit WinForms) habe ich die Grundgedanken zur Implementierung von MVP in WinForms vorgestellt, mit der man WinForm-Anwendungen mit UnitTests abdecken kann. In einer komplexeren WinForm-Anwendung gibt es neben dem Startform auch mehrere Unterforms, die durch das Hauptform aufgerufen werden müssen. Das Beispielprojekt Zur Demonstration habe ich ein Beispielprogramm mit MVP entwickelt, [...]]]></description>
			<content:encoded><![CDATA[<p>Im Teil 1 (<a href="/2009/12/02/mvp-mit-WinForms-model-view-presenter/">MVP mit WinForms</a>) habe ich die Grundgedanken zur Implementierung von MVP in WinForms vorgestellt, mit der man WinForm-Anwendungen mit UnitTests abdecken kann. In einer komplexeren WinForm-Anwendung gibt es neben dem Startform auch mehrere Unterforms, die durch das Hauptform aufgerufen werden müssen.</p>
<p><strong>Das Beispielprojekt<br />
</strong><br />
Zur Demonstration habe ich ein Beispielprogramm mit MVP entwickelt, welches einen sehr einfachen Twitterclient darstellt. Das Beispiel wurde nach Contract-First komponentenorientiert gebaut und besteht neben der MVP-Komponente aus weiteren Komponenten.</p>
<p><a href="http://blog.aztec-project.org/wp-content/uploads/2010/02/Foto1.jpg"><img class="alignnone size-full wp-image-900" title="TwitterClient Architektur" src="http://blog.aztec-project.org/wp-content/uploads/2010/02/Foto1.jpg" alt="" width="200" height="159" /></a></p>
<p>Die weiteren Komponenten haben nichts mit MVP zu tun, sondern sollen nur zeigen, wie man MVP in diesem Umfeld integriert. -&gt; <a href="http://blog.aztec-project.org/wp-content/uploads/2010/02/TwitterClient.zip">Den kompletten Sourcecode downloaden</a></p>
<p>Die Funktionen des Twitter-Clients sollen sein:<br />
1. Anzeige der 20 neuesten Meldungen aus der Timeline im Hauptfenster<br />
2. Der Benutzer soll Status-Updates bei Twitter posten können<br />
3. Die Zugangsdaten des Twitter-Accounts sollen gespeichert werden können</p>
<p><strong>Die WinForm-Komponente<br />
</strong></p>
<p>Um die Funktionen abzubilden, sind 3 Screens notwendig:<br />
1. Hauptbildschirm mit der Timeline des Twitter-Accounts<br />
2. Form für das Absenden eines Twitter-Status-Updates<br />
3. Konfigurationsbildschirm für den Twitter-Account</p>
<p><a href="http://blog.aztec-project.org/wp-content/uploads/2010/02/Foto2.jpg"><img class="alignnone size-medium wp-image-901" title="TwitterClient UI" src="http://blog.aztec-project.org/wp-content/uploads/2010/02/Foto2-300x143.jpg" alt="" width="300" height="143" /></a></p>
<p>Jedes WinForm besteht aus einer View-Klasse (dem WinForm), einem Model, welches als Singleton im IoC-Container konfiguriert wird und einem Presenter. Die einzelnen Funktionen in den Views sind im Beispielprojekt durch Tests abgedeckt und zeigen die notwendigen Tests für diese Art der Implementierung. Gerade durch geringen Funktionsumfang kann man das Muster der Verwendung gut erkennen.</p>
<p>In der MVP-Komponente befindet sich auch der &#8220;Inversion of Control&#8221;-Container, der die einzelnen Komponenten zusammenfügt. Dies könnte auch in einer extra Runner-Komponente ausgelagert sein.</p>
<p><strong>Aufrufen eines weiteren WinForms<br />
</strong><br />
Alle Abhängigkeiten werden per Dependency-Injection-Container an den Presenter übergeben. Da das Hauptform alle weiteren Views und Presenter instanziert, müssten diese alle bereits beim Programmstart instanziert werden. Um dies zu verhindern, habe ich eine IPresenterFactory eingeführt, die zur Laufzeit weitere Presenter nachinstanzieren kann. Die Factory selbst hält eine Referenz auf den Container und wird bei Programmstart im Container hinzugefügt. Um sicherzustellen, dass weiterhin alle anderen Abhängigkeiten über den Konstruktor definiert werden, können aus dieser Factory nur Klassen instanziert werden, die IPresenter implementieren.</p>
<p><strong>Fazit</strong><br />
Mit dieser Beispielanwendung kann man eine mögliche Implementierung von Model View Presenter in der Variante Supervising Controller sehen. Es ist also auch mit WinForms eine voll getestete MVP-Implementierung zu erstellen.</p>
<p>Anhang:<br />
<a href="http://blog.aztec-project.org/wp-content/uploads/2010/02/TwitterClient.zip">Kompletter Sourcecode der Beispielanwendung als ZIP</a></p>
<p><a href="http://dotnet-kicks.de/kick/?url=http%3a%2f%2fblog.aztec-project.org%2f2010%2f02%2f16%2fbeispiel-model-view-presenter-winforms%2f"><img src="http://dotnet-kicks.de/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fblog.aztec-project.org%2f2010%2f02%2f16%2fbeispiel-model-view-presenter-winforms%2f" border="0" alt="kick it on dotnet-kicks.de" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.aztec-project.org/2010/02/16/beispiel-model-view-presenter-winforms/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>MVP mit WinForms (Model-View-Presenter)</title>
		<link>http://blog.aztec-project.org/2009/12/02/mvp-mit-winforms-model-view-presenter/</link>
		<comments>http://blog.aztec-project.org/2009/12/02/mvp-mit-winforms-model-view-presenter/#comments</comments>
		<pubDate>Wed, 02 Dec 2009 12:30:32 +0000</pubDate>
		<dc:creator>Stefan Kölle</dc:creator>
				<category><![CDATA[How-To]]></category>
		<category><![CDATA[MVC]]></category>

		<guid isPermaLink="false">http://blog.aztec-project.org/?p=728</guid>
		<description><![CDATA[Wir setzen seit langer Zeit interne Tools mit WinForms um und hatten seit Anfang an Probleme bei der Testbarkeit dieser Anwendungen. Auch wenn man bei WinForms versucht, jeglichen Code aus der Codebehind-Datei zu entfernen, tut man sich mit dem Unit-Testing weiterhin schwer. Auf der Suche nach einer Lösung zur besseren Testbarkeit stößt man immer wieder [...]]]></description>
			<content:encoded><![CDATA[<p>Wir setzen seit langer Zeit interne Tools mit WinForms um und hatten seit Anfang an Probleme bei der Testbarkeit dieser Anwendungen. Auch wenn man bei WinForms versucht, jeglichen Code  aus der Codebehind-Datei zu entfernen, tut man sich mit dem Unit-Testing weiterhin schwer.</p>
<p>Auf der Suche nach einer Lösung zur besseren Testbarkeit stößt man immer wieder auf ein MVC- oder MVP-Modell, aber nirgends gibt es echte Beispiele in Verbindung mit WinForms. Ich möchte nun in einer Demo-Anwendung einen möglichen Ansatz zur Umsetzung des MVP-Patterns bei WinForms beschreiben.</p>
<p><strong>Die einzelnen Bestandteile von MVP</strong></p>
<p>Das Model repräsentiert den gesamten Zustand und die Logik der Ansicht. Das Model wird über den Presenter gefüllt. Die View enthält keinerlei Anwendungslogik, während der Presenter den Programmablauf steuert.</p>
<p>MVP gibt es in zwei Varianten &#8211; &#8220;Passive View&#8221; und &#8220;Supervising Controller&#8221;. Ich habe mich bei der Implementierung für &#8220;Supervising Controller&#8221; entschieden, da es auf den ersten Blick weniger Code erfordert. Der Unterschied von beiden Varianten besteht darin, dass bei &#8220;Passive View&#8221; die View weder Presenter noch Model kennt und als dumme View nur über den Presenter befüllt wird. Mir gefällt dabei jedoch nicht, dass der Presenter dabei die View genau kennen muss.</p>
<p>Bei &#8220;Supervising Controller&#8221; kennt nun jeweils die View als auch der Presenter das Model, darüber findet der Datenaustausch statt.</p>
<p><strong>Die konkrete Implementierung</strong></p>
<p>Der Presenter wird mit der View und dem Model instanziert.</p>
<div style="font-family: Courier New; font-size: 10pt; color: black; background: white;">
<p style="margin: 0px;"><span style="color: #2b91af;"> 10</span> <span style="color: blue;">public</span> <span style="color: blue;">class</span> <span style="color: #2b91af;">MainPresenter</span> : <span style="color: #2b91af;">IMainPresenter</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 11</span> {</p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 12</span> <span style="color: blue;">private</span> <span style="color: blue;">readonly</span> <span style="color: #2b91af;">IMainView</span> m_view;</p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 13</span> <span style="color: blue;">private</span> <span style="color: blue;">readonly</span> <span style="color: #2b91af;">IMainModel</span> m_model;</p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 14</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 15</span> <span style="color: blue;">public</span> MainPresenter(<span style="color: #2b91af;">IMainView</span> view, <span style="color: #2b91af;">IMainModel</span> model)</p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 16</span> {</p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 17</span> m_view = view;</p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 18</span> m_model = model;</p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 19</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 20</span> InitializeModelAndRefreshView();</p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 21</span> InitializeAndShowView();</p>
</div>
<p>Die View ist das WinForm und wird auch mit dem Model instanziert. Das Model selbst ist ein über den IoC-Container realisiertes Singleton.</p>
<div style="font-family: Courier New; font-size: 10pt; color: black; background: white;">
<p style="margin: 0px;"><span style="color: #2b91af;"> 10</span> <span style="color: blue;">public</span> <span style="color: blue;">partial</span> <span style="color: blue;">class</span> <span style="color: #2b91af;">MainView</span> : <span style="color: #2b91af;">Form</span>, <span style="color: #2b91af;">IMainView</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 11</span> {</p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 12</span> <span style="color: blue;">private</span> <span style="color: blue;">readonly</span> <span style="color: #2b91af;">IMainModel</span> m_model;</p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 13</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 14</span> <span style="color: blue;">public</span> MainView(<span style="color: #2b91af;">IMainModel</span> model)</p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 15</span> {</p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 16</span> m_model = model;</p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 17</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 18</span> InitializeComponent();</p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 19</span> <span style="color: blue;">this</span>.Closed += <span style="color: blue;">delegate</span> { ViewClosed(<span style="color: blue;">this</span>, <span style="color: blue;">new</span> <span style="color: #2b91af;">EventArgs</span>()); };</p>
</div>
<p>Das Model beinhaltet nur Properties mit allen Daten, die zur Anzeige der View notwendig sind.</p>
<p>Wenn der Presenter Daten im Model ändert, ruft dieser explizit eine UpdateMethode in der View  auf. Die View selbst stellt EventHandler zur Verfügung, auf die sich der Presenter hängt, um Aktionen auf der View weiter zu bearbeiten.</p>
<div style="font-family: Courier New; font-size: 10pt; color: black; background: white;">
<p style="margin: 0px;"><span style="color: #2b91af;"> 60</span> <span style="color: blue;">public</span> <span style="color: blue;">event</span> <span style="color: #2b91af;">EventHandler</span>&lt;<span style="color: #2b91af;">EventArgs</span>&gt; ViewClosed;</p>
</div>
<p>Im Presenter sieht dies folgendermaßen aus:</p>
<div style="font-family: Courier New; font-size: 10pt; color: black; background: white;">
<p style="margin: 0px;"><span style="color: #2b91af;"> 31</span> <span style="color: blue;">private</span> <span style="color: blue;">void</span> InitializeAndShowView()</p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 32</span> {</p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 33</span> m_view.Title = <span style="color: #a31515;">&#8220;ResourcerClient V1.0&#8243;</span>;</p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 34</span> m_view.ViewClosed += <span style="color: blue;">new</span> <span style="color: #2b91af;">EventHandler</span>&lt;<span style="color: #2b91af;">EventArgs</span>&gt;(mainView_ViewClosed);</p>
</div>
<div style="font-family: Courier New; font-size: 10pt; color: black; background: white;">
<p style="margin: 0px;"><span style="color: #2b91af;"> 42</span> <span style="color: blue;">void</span> mainView_ViewClosed(<span style="color: blue;">object</span> sender, <span style="color: #2b91af;">EventArgs</span> e)</p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 43</span> {</p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 44</span> <span style="color: #2b91af;">Application</span>.Exit();</p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 45</span> }</p>
</div>
<p>Damit ist die Grundlage des MVP Patterns bei WinForms angelegt. Der Presenter ist damit schon voll testbar, da er komplett von der View abgekoppelt ist. Bis jetzt sieht alles sehr einfach aus. Auch einige andere Beispiele aus dem Netz gehen soweit. Doch wie instanziert man jetzt eine weitere View bzw. einen weiteren Presenter?</p>
<p><a href="/2010/02/16/beispiel-model-view-presenter-winforms/"><br />
Mehr dazu im zweiten Teil</a></p>
<p><a href="http://dotnet-kicks.de/kick/?url=http%3a%2f%2fblog.aztec-project.org%2f2009%2f12%2f02%2fmvp-mit-winforms-model-view-presenter%2f"><img src="http://dotnet-kicks.de/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fblog.aztec-project.org%2f2009%2f12%2f02%2fmvp-mit-winforms-model-view-presenter%2f" border="0" alt="kick it on dotnet-kicks.de" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.aztec-project.org/2009/12/02/mvp-mit-winforms-model-view-presenter/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Unit-Tests für WebForms</title>
		<link>http://blog.aztec-project.org/2009/09/07/unit-tests-fur-webforms/</link>
		<comments>http://blog.aztec-project.org/2009/09/07/unit-tests-fur-webforms/#comments</comments>
		<pubDate>Mon, 07 Sep 2009 07:22:16 +0000</pubDate>
		<dc:creator>Christina Hirth</dc:creator>
				<category><![CDATA[How-To]]></category>
		<category><![CDATA[Unit Testing]]></category>
		<category><![CDATA[Webanwendungen]]></category>
		<category><![CDATA[Unit-Tests]]></category>
		<category><![CDATA[Webapplication]]></category>

		<guid isPermaLink="false">http://blog.aztec-project.org/?p=606</guid>
		<description><![CDATA[Obwohl die allgemeine Meinung ist, dass es sehr schwierig sei, kann man mit folgendem Workaround Webforms sehr einfach und sehr umfangreich testen. Bedingung 1: als Projekt kein Web Site Project sondern eine Web Application erstellen. Bedingung 2: Business Logic in die entsprechende Schicht auslagern. Nehmen wir zum Beispiel ein einfaches Formular. Nach Absenden des Formulars [...]]]></description>
			<content:encoded><![CDATA[<p>Obwohl die allgemeine Meinung ist, dass es sehr schwierig sei, kann man mit folgendem Workaround Webforms sehr einfach und sehr umfangreich testen. Bedingung 1: als Projekt kein Web Site Project sondern eine Web Application erstellen. Bedingung 2: Business Logic in die entsprechende Schicht auslagern.</p>
<p>Nehmen wir zum Beispiel ein einfaches Formular. Nach Absenden des Formulars sollen die Werte aus den 2 Feldern addiert werden. Wenn man per QueryString einen Parameter <code>multiple</code> übergibt, soll das Ergebnis damit multipliziert werden.</p>
<p><img src="http://blog.aztec-project.org/wp-content/uploads/2009/09/TestableWebForm.jpg" alt="Testable WebForm" /> &nbsp; <img src="http://blog.aztec-project.org/wp-content/uploads/2009/09/TestableWebForm_Sent.jpg" alt="Testable WebForm Sent" /></p>
<p>Und nun zum Quellcode: Die automatisch erstellte .designer.cs muss entfernt werden, was man sowieso tun sollte, da man automatisch erstellten Code &#8211; also Code, den keiner außer Microsoft unter Kontrolle hat &#8211; vermeiden sollte.<br />
Die Inhalte der .designer.cs &#8211; also die Definitionen der Web-Elemente &#8211; werden in der Klasse als <code>Public Properties</code> erstellt und instantiiert, um bei Zugriffen wie <code>TextBox.Text</code> keine NullReferenceException zu bekommen.</p>
<div style="font-family: Courier New; font-size: 9pt; color: black; background: white;">
<p style="margin: 0px;"><span style="color: #2b91af;">&nbsp;&nbsp;&nbsp;&nbsp;1</span>&nbsp;<span style="color: blue;">using</span> System;</p>
<p style="margin: 0px;"><span style="color: #2b91af;">&nbsp;&nbsp;&nbsp;&nbsp;2</span>&nbsp;<span style="color: blue;">using</span> System.Web.UI.HtmlControls;</p>
<p style="margin: 0px;"><span style="color: #2b91af;">&nbsp;&nbsp;&nbsp;&nbsp;3</span>&nbsp;<span style="color: blue;">using</span> System.Web.UI.WebControls;</p>
<p style="margin: 0px;"><span style="color: #2b91af;">&nbsp;&nbsp;&nbsp;&nbsp;4</span>&nbsp;<span style="color: blue;">using</span> framework.Testable.Web.UI;</p>
<p style="margin: 0px;"><span style="color: #2b91af;">&nbsp;&nbsp;&nbsp;&nbsp;5</span>&nbsp;</p>
<p style="margin: 0px;"><span style="color: #2b91af;">&nbsp;&nbsp;&nbsp;&nbsp;6</span>&nbsp;<span style="color: blue;">namespace</span> TestableWebForm</p>
<p style="margin: 0px;"><span style="color: #2b91af;">&nbsp;&nbsp;&nbsp;&nbsp;7</span>&nbsp;{</p>
<p style="margin: 0px;"><span style="color: #2b91af;">&nbsp;&nbsp;&nbsp;&nbsp;8</span>&nbsp;&nbsp;&nbsp;&nbsp; <span style="color: blue;">public</span> <span style="color: blue;">class</span> <span style="color: #2b91af;">DefaultPage</span> : System.Web.UI.<span style="color: #2b91af;">Page</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;">&nbsp;&nbsp;&nbsp;&nbsp;9</span>&nbsp;&nbsp;&nbsp;&nbsp; {</p>
<p style="margin: 0px;"><span style="color: #2b91af;">&nbsp;&nbsp;&nbsp;10</span>&nbsp;</p>
<p style="margin: 0px;"><span style="color: #2b91af;">&nbsp;&nbsp;&nbsp;11</span>&nbsp;<span style="color: blue;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; #region</span> Controls</p>
<p style="margin: 0px;"><span style="color: #2b91af;">&nbsp;&nbsp;&nbsp;12</span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue;">public</span> <span style="color: #2b91af;">HtmlForm</span> Formular;</p>
<p style="margin: 0px;"><span style="color: #2b91af;">&nbsp;&nbsp;&nbsp;13</span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue;">public</span> <span style="color: #2b91af;">TextBox</span> Value1 = <span style="color: blue;">new</span> <span style="color: #2b91af;">TextBox</span>();</p>
<p style="margin: 0px;"><span style="color: #2b91af;">&nbsp;&nbsp;&nbsp;14</span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue;">public</span> <span style="color: #2b91af;">TextBox</span> Value2 = <span style="color: blue;">new</span> <span style="color: #2b91af;">TextBox</span>();</p>
<p style="margin: 0px;"><span style="color: #2b91af;">&nbsp;&nbsp;&nbsp;15</span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue;">public</span> <span style="color: #2b91af;">Label</span> Result = <span style="color: blue;">new</span> <span style="color: #2b91af;">Label</span>();</p>
<p style="margin: 0px;"><span style="color: #2b91af;">&nbsp;&nbsp;&nbsp;16</span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue;">public</span> <span style="color: #2b91af;">Button</span> Submit = <span style="color: blue;">new</span> <span style="color: #2b91af;">Button</span>();</p>
<p style="margin: 0px;"><span style="color: #2b91af;">&nbsp;&nbsp;&nbsp;17</span>&nbsp;<span style="color: blue;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; #endregion</span></p>
</div>
<p>Um das Verhalten testen zu können, haben wir Adapter für die Klassen <code>System.Web.UI.Page</code>, <code>System.Web.HttpRequest</code> und <code>System.Web.HttpResponse</code> geschrieben, und zwar für die Properties und Methoden die uns vorerst interessieren: z.B. <code>Page.IsPostBack, Page.Request, Response.Redirect(string url, bool endResponse)</code>. Bei der Benennung haben wir einfach den Namespace <code>System</code> mit <code>framework.Testable</code> ersetzt und wir haben natürlich zu jedem Testable-Objekt einen Interface erstellt.</p>
<div style="font-family: Courier New; font-size: 9pt; color: black; background: white;">
<p style="margin: 0px;"><span style="color: #2b91af;">&nbsp;&nbsp;&nbsp;&nbsp;1</span>&nbsp;</p>
<p style="margin: 0px;"><span style="color: #2b91af;">&nbsp;&nbsp;&nbsp;&nbsp;2</span>&nbsp;<span style="color: blue;">namespace</span> framework.Testable.Web</p>
<p style="margin: 0px;"><span style="color: #2b91af;">&nbsp;&nbsp;&nbsp;&nbsp;3</span>&nbsp;{</p>
<p style="margin: 0px;"><span style="color: #2b91af;">&nbsp;&nbsp;&nbsp;&nbsp;4</span>&nbsp;&nbsp;&nbsp;&nbsp; <span style="color: blue;">namespace</span> UI</p>
<p style="margin: 0px;"><span style="color: #2b91af;">&nbsp;&nbsp;&nbsp;&nbsp;5</span>&nbsp;&nbsp;&nbsp;&nbsp; {</p>
<p style="margin: 0px;"><span style="color: #2b91af;">&nbsp;&nbsp;&nbsp;&nbsp;6</span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue;">public</span> <span style="color: blue;">interface</span> <span style="color: #2b91af;">IPage</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;">&nbsp;&nbsp;&nbsp;&nbsp;7</span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</p>
<p style="margin: 0px;"><span style="color: #2b91af;">&nbsp;&nbsp;&nbsp;&nbsp;8</span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue;">bool</span> IsPostBack{ <span style="color: blue;">get</span>; }</p>
<p style="margin: 0px;"><span style="color: #2b91af;">&nbsp;&nbsp;&nbsp;&nbsp;9</span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: #2b91af;">IHttpRequest</span> Request{ <span style="color: blue;">get</span>; <span style="color: blue;">set</span>; }</p>
<p style="margin: 0px;"><span style="color: #2b91af;">&nbsp;&nbsp;&nbsp;10</span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: #2b91af;">IHttpResponse</span> Response{ <span style="color: blue;">get</span>; <span style="color: blue;">set</span>; }</p>
<p style="margin: 0px;"><span style="color: #2b91af;">&nbsp;&nbsp;&nbsp;11</span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</p>
<p style="margin: 0px;"><span style="color: #2b91af;">&nbsp;&nbsp;&nbsp;12</span>&nbsp;</p>
<p style="margin: 0px;"><span style="color: #2b91af;">&nbsp;&nbsp;&nbsp;13</span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue;">public</span> <span style="color: blue;">class</span> <span style="color: #2b91af;">Page</span> : <span style="color: #2b91af;">IPage</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;">&nbsp;&nbsp;&nbsp;14</span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</p>
<p style="margin: 0px;"><span style="color: #2b91af;">&nbsp;&nbsp;&nbsp;15</span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue;">private</span> <span style="color: blue;">readonly</span> System.Web.UI.<span style="color: #2b91af;">Page</span> m_page;</p>
<p style="margin: 0px;"><span style="color: #2b91af;">&nbsp;&nbsp;&nbsp;16</span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue;">private</span> <span style="color: #2b91af;">IHttpRequest</span> m_request;</p>
<p style="margin: 0px;"><span style="color: #2b91af;">&nbsp;&nbsp;&nbsp;17</span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue;">private</span> <span style="color: #2b91af;">IHttpResponse</span> m_response;</p>
<p style="margin: 0px;"><span style="color: #2b91af;">&nbsp;&nbsp;&nbsp;18</span>&nbsp;</p>
<p style="margin: 0px;"><span style="color: #2b91af;">&nbsp;&nbsp;&nbsp;19</span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue;">public</span> Page( System.Web.UI.<span style="color: #2b91af;">Page</span> page )</p>
<p style="margin: 0px;"><span style="color: #2b91af;">&nbsp;&nbsp;&nbsp;20</span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</p>
<p style="margin: 0px;"><span style="color: #2b91af;">&nbsp;&nbsp;&nbsp;21</span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; m_page = page;</p>
<p style="margin: 0px;"><span style="color: #2b91af;">&nbsp;&nbsp;&nbsp;22</span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; m_request = <span style="color: blue;">new</span> <span style="color: #2b91af;">HttpRequest</span>( m_page );</p>
<p style="margin: 0px;"><span style="color: #2b91af;">&nbsp;&nbsp;&nbsp;23</span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; m_response = <span style="color: blue;">new</span> <span style="color: #2b91af;">HttpResponse</span>( m_page );</p>
<p style="margin: 0px;"><span style="color: #2b91af;">&nbsp;&nbsp;&nbsp;24</span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</p>
<p style="margin: 0px;"><span style="color: #2b91af;">&nbsp;&nbsp;&nbsp;25</span>&nbsp;</p>
<p style="margin: 0px;"><span style="color: #2b91af;">&nbsp;&nbsp;&nbsp;26</span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue;">public</span> <span style="color: blue;">bool</span> IsPostBack</p>
<p style="margin: 0px;"><span style="color: #2b91af;">&nbsp;&nbsp;&nbsp;27</span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</p>
<p style="margin: 0px;"><span style="color: #2b91af;">&nbsp;&nbsp;&nbsp;28</span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue;">get</span>{ <span style="color: blue;">return</span> m_page.IsPostBack; }</p>
<p style="margin: 0px;"><span style="color: #2b91af;">&nbsp;&nbsp;&nbsp;29</span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</p>
<p style="margin: 0px;"><span style="color: #2b91af;">&nbsp;&nbsp;&nbsp;30</span>&nbsp;</p>
<p style="margin: 0px;"><span style="color: #2b91af;">&nbsp;&nbsp;&nbsp;31</span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue;">public</span> <span style="color: #2b91af;">IHttpRequest</span> Request</p>
<p style="margin: 0px;"><span style="color: #2b91af;">&nbsp;&nbsp;&nbsp;32</span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</p>
<p style="margin: 0px;"><span style="color: #2b91af;">&nbsp;&nbsp;&nbsp;33</span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue;">get</span>{ <span style="color: blue;">return</span> m_request; }</p>
<p style="margin: 0px;"><span style="color: #2b91af;">&nbsp;&nbsp;&nbsp;34</span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue;">set</span> { m_request = <span style="color: blue;">value</span>; }</p>
<p style="margin: 0px;"><span style="color: #2b91af;">&nbsp;&nbsp;&nbsp;35</span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</p>
<p style="margin: 0px;"><span style="color: #2b91af;">&nbsp;&nbsp;&nbsp;36</span>&nbsp;</p>
<p style="margin: 0px;"><span style="color: #2b91af;">&nbsp;&nbsp;&nbsp;37</span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue;">public</span> <span style="color: #2b91af;">IHttpResponse</span> Response</p>
<p style="margin: 0px;"><span style="color: #2b91af;">&nbsp;&nbsp;&nbsp;38</span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</p>
<p style="margin: 0px;"><span style="color: #2b91af;">&nbsp;&nbsp;&nbsp;39</span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue;">get</span>{ <span style="color: blue;">return</span> m_response; }</p>
<p style="margin: 0px;"><span style="color: #2b91af;">&nbsp;&nbsp;&nbsp;40</span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue;">set</span> { m_response = <span style="color: blue;">value</span>; }</p>
<p style="margin: 0px;"><span style="color: #2b91af;">&nbsp;&nbsp;&nbsp;41</span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</p>
<p style="margin: 0px;"><span style="color: #2b91af;">&nbsp;&nbsp;&nbsp;42</span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</p>
<p style="margin: 0px;"><span style="color: #2b91af;">&nbsp;&nbsp;&nbsp;43</span>&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p style="margin: 0px;"><span style="color: #2b91af;">&nbsp;&nbsp;&nbsp;44</span>&nbsp;}</p>
</div>
<p>Um alle gemockte Objekte setzen zu können, haben wir unserer <code>Page</code>-Klasse auch Setter für <code>Request</code> und <code>Response</code> gegeben. Da man <code>Request.Params</code> nicht setzen kann, d.h. <code>Request.Params[]</code> immer ein NullReferenceException verursachen würde, haben wir das Auslesen der <code>Request</code>-Parameter in eine Methode <code>Request.GetParamValue(string name)</code> ausgelagert.</p>
<p>Das war ungefähr alles: in der Seite nutzt man dann anstelle der eigenen Request und Response-Objekten die <code>Testable</code>-Objekte.</p>
<div style="font-family: Courier New; font-size: 9pt; color: black; background: white;">
<p style="margin: 0px;"><span style="color: #2b91af;">&nbsp;&nbsp;&nbsp;&nbsp;8</span>&nbsp;&nbsp;&nbsp;&nbsp; <span style="color: blue;">public</span> <span style="color: blue;">class</span> <span style="color: #2b91af;">DefaultPage</span> : System.Web.UI.<span style="color: #2b91af;">Page</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;">&nbsp;&nbsp;&nbsp;&nbsp;9</span>&nbsp;&nbsp;&nbsp;&nbsp; {</p>
<p style="margin: 0px;"><span style="color: #2b91af;">&nbsp;&nbsp;&nbsp;&#8230;</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;">&nbsp;&nbsp;&nbsp;19</span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue;">private</span> <span style="color: #2b91af;">IPage</span> m_page;</p>
<p style="margin: 0px;"><span style="color: #2b91af;">&nbsp;&nbsp;&nbsp;20</span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue;">public</span> <span style="color: blue;">void</span> SetTestableObjects( <span style="color: #2b91af;">IPage</span> page )</p>
<p style="margin: 0px;"><span style="color: #2b91af;">&nbsp;&nbsp;&nbsp;21</span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</p>
<p style="margin: 0px;"><span style="color: #2b91af;">&nbsp;&nbsp;&nbsp;22</span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; m_page = page;</p>
<p style="margin: 0px;"><span style="color: #2b91af;">&nbsp;&nbsp;&nbsp;23</span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</p>
<p style="margin: 0px;"><span style="color: #2b91af;">&nbsp;&nbsp;&nbsp;24</span>&nbsp;</p>
<p style="margin: 0px;"><span style="color: #2b91af;">&nbsp;&nbsp;&nbsp;25</span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue;">public</span> <span style="color: blue;">void</span> Page_Load( <span style="color: blue;">object</span> sender, <span style="color: #2b91af;">EventArgs</span> e )</p>
<p style="margin: 0px;"><span style="color: #2b91af;">&nbsp;&nbsp;&nbsp;26</span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</p>
<p style="margin: 0px;"><span style="color: #2b91af;">&nbsp;&nbsp;&nbsp;27</span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue;">if</span> (m_page == <span style="color: blue;">null</span>) m_page = <span style="color: blue;">new</span> <span style="color: #2b91af;">Page</span>( <span style="color: blue;">this</span> );</p>
<p style="margin: 0px;"><span style="color: #2b91af;">&nbsp;&nbsp;&nbsp;28</span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue;">int</span> multiple = 1;</p>
<p style="margin: 0px;"><span style="color: #2b91af;">&nbsp;&nbsp;&nbsp;29</span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue;">if</span> (!<span style="color: blue;">string</span>.IsNullOrEmpty( m_page.Request.GetParamValue( <span style="color: #a31515;">&quot;multiple&quot;</span> ) )) multiple = <span style="color: #2b91af;">Convert</span>.ToInt32( m_page.Request.GetParamValue( <span style="color: #a31515;">&quot;multiple&quot;</span> ) );</p>
<p style="margin: 0px;"><span style="color: #2b91af;">&nbsp;&nbsp;&nbsp;30</span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue;">if</span> (m_page.IsPostBack)</p>
<p style="margin: 0px;"><span style="color: #2b91af;">&nbsp;&nbsp;&nbsp;31</span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</p>
<p style="margin: 0px;"><span style="color: #2b91af;">&nbsp;&nbsp;&nbsp;32</span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; Result.Text = ( (<span style="color: #2b91af;">Convert</span>.ToInt32( Value1.Text ) + <span style="color: #2b91af;">Convert</span>.ToInt32( Value2.Text ))*multiple ).ToString();</p>
<p style="margin: 0px;"><span style="color: #2b91af;">&nbsp;&nbsp;&nbsp;33</span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</p>
<p style="margin: 0px;"><span style="color: #2b91af;">&nbsp;&nbsp;&nbsp;34</span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</p>
</div>
<p>Damit ist die Web-Anwendung bereit zum Testen. So schaut zum Beispiel ein Test für das Laden der Seite aus:</p>
<div style="font-family: Courier New; font-size: 9pt; color: black; background: white;">
<p style="margin: 0px;"><span style="color: #2b91af;">&nbsp;&nbsp;&nbsp;&nbsp;1</span>&nbsp;<span style="color: blue;">using</span> framework.Testable.Web;</p>
<p style="margin: 0px;"><span style="color: #2b91af;">&nbsp;&nbsp;&nbsp;&nbsp;2</span>&nbsp;<span style="color: blue;">using</span> framework.Testable.Web.UI;</p>
<p style="margin: 0px;"><span style="color: #2b91af;">&nbsp;&nbsp;&nbsp;&nbsp;3</span>&nbsp;<span style="color: blue;">using</span> NUnit.Framework;</p>
<p style="margin: 0px;"><span style="color: #2b91af;">&nbsp;&nbsp;&nbsp;&nbsp;4</span>&nbsp;<span style="color: blue;">using</span> Rhino.Mocks;</p>
<p style="margin: 0px;"><span style="color: #2b91af;">&nbsp;&nbsp;&nbsp;&nbsp;5</span>&nbsp;<span style="color: blue;">using</span> TestableWebForm;</p>
<p style="margin: 0px;"><span style="color: #2b91af;">&nbsp;&nbsp;&nbsp;&nbsp;6</span>&nbsp;</p>
<p style="margin: 0px;"><span style="color: #2b91af;">&nbsp;&nbsp;&nbsp;&nbsp;7</span>&nbsp;<span style="color: blue;">namespace</span> Tests</p>
<p style="margin: 0px;"><span style="color: #2b91af;">&nbsp;&nbsp;&nbsp;&nbsp;8</span>&nbsp;{</p>
<p style="margin: 0px;"><span style="color: #2b91af;">&nbsp;&nbsp;&nbsp;&nbsp;9</span>&nbsp;&nbsp;&nbsp;&nbsp; [<span style="color: #2b91af;">TestFixture</span>]</p>
<p style="margin: 0px;"><span style="color: #2b91af;">&nbsp;&nbsp;&nbsp;10</span>&nbsp;&nbsp;&nbsp;&nbsp; <span style="color: blue;">public</span> <span style="color: blue;">class</span> <span style="color: #2b91af;">WebFormTests</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;">&nbsp;&nbsp;&nbsp;11</span>&nbsp;&nbsp;&nbsp;&nbsp; {</p>
<p style="margin: 0px;"><span style="color: #2b91af;">&nbsp;&nbsp;&nbsp;12</span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue;">private</span> <span style="color: #2b91af;">IPage</span> m_page;</p>
<p style="margin: 0px;"><span style="color: #2b91af;">&nbsp;&nbsp;&nbsp;13</span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue;">private</span> <span style="color: #2b91af;">IHttpRequest</span> m_request;</p>
<p style="margin: 0px;"><span style="color: #2b91af;">&nbsp;&nbsp;&nbsp;14</span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue;">private</span> <span style="color: #2b91af;">IHttpResponse</span> m_response;</p>
<p style="margin: 0px;"><span style="color: #2b91af;">&nbsp;&nbsp;&nbsp;15</span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue;">private</span> <span style="color: #2b91af;">DefaultPage</span> m_defaultPage;</p>
<p style="margin: 0px;"><span style="color: #2b91af;">&nbsp;&nbsp;&nbsp;16</span>&nbsp;</p>
<p style="margin: 0px;"><span style="color: #2b91af;">&nbsp;&nbsp;&nbsp;17</span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; [<span style="color: #2b91af;">SetUp</span>]</p>
<p style="margin: 0px;"><span style="color: #2b91af;">&nbsp;&nbsp;&nbsp;18</span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue;">public</span> <span style="color: blue;">void</span> Init()</p>
<p style="margin: 0px;"><span style="color: #2b91af;">&nbsp;&nbsp;&nbsp;19</span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</p>
<p style="margin: 0px;"><span style="color: #2b91af;">&nbsp;&nbsp;&nbsp;20</span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; m_page = <span style="color: #2b91af;">MockRepository</span>.GenerateStub&lt;<span style="color: #2b91af;">IPage</span>&gt;();</p>
<p style="margin: 0px;"><span style="color: #2b91af;">&nbsp;&nbsp;&nbsp;21</span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; m_request = <span style="color: #2b91af;">MockRepository</span>.GenerateStub&lt;<span style="color: #2b91af;">IHttpRequest</span>&gt;();</p>
<p style="margin: 0px;"><span style="color: #2b91af;">&nbsp;&nbsp;&nbsp;22</span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; m_response = <span style="color: #2b91af;">MockRepository</span>.GenerateStub&lt;<span style="color: #2b91af;">IHttpResponse</span>&gt;();</p>
<p style="margin: 0px;"><span style="color: #2b91af;">&nbsp;&nbsp;&nbsp;23</span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; m_page.Request = m_request;</p>
<p style="margin: 0px;"><span style="color: #2b91af;">&nbsp;&nbsp;&nbsp;24</span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; m_page.Response = m_response;</p>
<p style="margin: 0px;"><span style="color: #2b91af;">&nbsp;&nbsp;&nbsp;25</span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</p>
<p style="margin: 0px;"><span style="color: #2b91af;">&nbsp;&nbsp;&nbsp;26</span>&nbsp;</p>
<p style="margin: 0px;"><span style="color: #2b91af;">&nbsp;&nbsp;&nbsp;27</span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; [<span style="color: #2b91af;">Test</span>]</p>
<p style="margin: 0px;"><span style="color: #2b91af;">&nbsp;&nbsp;&nbsp;28</span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue;">public</span> <span style="color: blue;">void</span> PageLoad_Loading_EmptyFields()</p>
<p style="margin: 0px;"><span style="color: #2b91af;">&nbsp;&nbsp;&nbsp;29</span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</p>
<p style="margin: 0px;"><span style="color: #2b91af;">&nbsp;&nbsp;&nbsp;30</span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: green;">// Arrange</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;">&nbsp;&nbsp;&nbsp;31</span>&nbsp;</p>
<p style="margin: 0px;"><span style="color: #2b91af;">&nbsp;&nbsp;&nbsp;32</span>&nbsp;</p>
<p style="margin: 0px;"><span style="color: #2b91af;">&nbsp;&nbsp;&nbsp;33</span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: green;">// Act</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;">&nbsp;&nbsp;&nbsp;34</span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; m_defaultPage = <span style="color: blue;">new</span> <span style="color: #2b91af;">DefaultPage</span>();</p>
<p style="margin: 0px;"><span style="color: #2b91af;">&nbsp;&nbsp;&nbsp;35</span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; m_defaultPage.SetTestableObjects(m_page);</p>
<p style="margin: 0px;"><span style="color: #2b91af;">&nbsp;&nbsp;&nbsp;36</span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; m_defaultPage.Page_Load( <span style="color: blue;">null</span>, <span style="color: blue;">null</span> );</p>
<p style="margin: 0px;"><span style="color: #2b91af;">&nbsp;&nbsp;&nbsp;37</span>&nbsp;</p>
<p style="margin: 0px;"><span style="color: #2b91af;">&nbsp;&nbsp;&nbsp;38</span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: green;">// Assert</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;">&nbsp;&nbsp;&nbsp;39</span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: #2b91af;">Assert</span>.IsEmpty( m_defaultPage.Value1.Text );</p>
<p style="margin: 0px;"><span style="color: #2b91af;">&nbsp;&nbsp;&nbsp;40</span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: #2b91af;">Assert</span>.IsEmpty( m_defaultPage.Value2.Text );</p>
<p style="margin: 0px;"><span style="color: #2b91af;">&nbsp;&nbsp;&nbsp;41</span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: #2b91af;">Assert</span>.IsEmpty(m_defaultPage.Result.Text);</p>
<p style="margin: 0px;"><span style="color: #2b91af;">&nbsp;&nbsp;&nbsp;42</span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</p>
</div>
<p>Und so für PostBack inklusive QueryString-Parameter:</p>
<div style="font-family: Courier New; font-size: 9pt; color: black; background: white;">
<p style="margin: 0px;"><span style="color: #2b91af;">&nbsp;&nbsp;&nbsp;63</span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; [<span style="color: #2b91af;">Test</span>]</p>
<p style="margin: 0px;"><span style="color: #2b91af;">&nbsp;&nbsp;&nbsp;64</span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue;">public</span> <span style="color: blue;">void</span> PageLoad_PostBackWithRequestValue_ResultIsCorrect()</p>
<p style="margin: 0px;"><span style="color: #2b91af;">&nbsp;&nbsp;&nbsp;65</span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</p>
<p style="margin: 0px;"><span style="color: #2b91af;">&nbsp;&nbsp;&nbsp;66</span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: green;">// Arrange</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;">&nbsp;&nbsp;&nbsp;67</span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue;">const</span> <span style="color: blue;">int</span> value1 = 1;</p>
<p style="margin: 0px;"><span style="color: #2b91af;">&nbsp;&nbsp;&nbsp;68</span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue;">const</span> <span style="color: blue;">int</span> value2 = 2;</p>
<p style="margin: 0px;"><span style="color: #2b91af;">&nbsp;&nbsp;&nbsp;69</span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue;">const</span> <span style="color: blue;">int</span> value3 = 3;</p>
<p style="margin: 0px;"><span style="color: #2b91af;">&nbsp;&nbsp;&nbsp;70</span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; m_request.Expect( a =&gt; a.GetParamValue( <span style="color: #a31515;">&quot;multiple&quot;</span> ) ).IgnoreArguments().Repeat.Twice().Return( value3.ToString() );</p>
<p style="margin: 0px;"><span style="color: #2b91af;">&nbsp;&nbsp;&nbsp;71</span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; m_page.Expect( a =&gt; a.IsPostBack ).Return( <span style="color: blue;">true</span> );</p>
<p style="margin: 0px;"><span style="color: #2b91af;">&nbsp;&nbsp;&nbsp;72</span>&nbsp;</p>
<p style="margin: 0px;"><span style="color: #2b91af;">&nbsp;&nbsp;&nbsp;73</span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: green;">// Act</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;">&nbsp;&nbsp;&nbsp;74</span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; m_defaultPage = <span style="color: blue;">new</span> <span style="color: #2b91af;">DefaultPage</span>();</p>
<p style="margin: 0px;"><span style="color: #2b91af;">&nbsp;&nbsp;&nbsp;75</span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; m_defaultPage.SetTestableObjects( m_page );</p>
<p style="margin: 0px;"><span style="color: #2b91af;">&nbsp;&nbsp;&nbsp;76</span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; m_defaultPage.Value1.Text = value1.ToString();</p>
<p style="margin: 0px;"><span style="color: #2b91af;">&nbsp;&nbsp;&nbsp;77</span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; m_defaultPage.Value2.Text = value2.ToString();</p>
<p style="margin: 0px;"><span style="color: #2b91af;">&nbsp;&nbsp;&nbsp;78</span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; m_defaultPage.Page_Load( <span style="color: blue;">null</span>, <span style="color: blue;">null</span> );</p>
<p style="margin: 0px;"><span style="color: #2b91af;">&nbsp;&nbsp;&nbsp;79</span>&nbsp;</p>
<p style="margin: 0px;"><span style="color: #2b91af;">&nbsp;&nbsp;&nbsp;80</span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: green;">// Assert</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;">&nbsp;&nbsp;&nbsp;81</span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: #2b91af;">Assert</span>.IsTrue( m_defaultPage.Result.Text == ( (value1 + value2)*value3 ).ToString() );</p>
<p style="margin: 0px;"><span style="color: #2b91af;">&nbsp;&nbsp;&nbsp;82</span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</p>
</div>
<p>Dieses Vorgehen hat uns nicht nur den seit langen gesuchten Weg zum Testen von Webanwendungen geebnet, sondern zwingt auch den Entwickler dazu, alle Funktionalitäten, die nicht in einer Webseite sondern in die dll-s gehören, auszulagern. Damit dürfte es auch der richtige Weg der Clean Code Developers für die Arbeit mit WebForms sein.</p>
<p>Was die Adapter-Klassen betrifft: inzwischen haben wir auch System.IO &#8220;adaptiert&#8221; und bald werden die anderen System-Klassen folgen, je nach Bedarf.<br />
<a href="http://blog.aztec-project.org/wp-content/uploads/2009/09/TestableWebForm.zip">Download VS2008-Projekt</a></p>
<p><a href="http://dotnet-kicks.de/kick/?url=http%3a%2f%2fblog.aztec-project.org%2f2009%2f09%2f07%2ftesten-von-webforms%2f"><img src="http://dotnet-kicks.de/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fblog.aztec-project.org%2f2009%2f09%2f07%2ftesten-von-webforms%2f" border="0" alt="kick it on dotnet-kicks.de" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.aztec-project.org/2009/09/07/unit-tests-fur-webforms/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Testen von nicht öffentlichen Methoden</title>
		<link>http://blog.aztec-project.org/2009/08/12/testen-von-nicht-offentlichen-methoden/</link>
		<comments>http://blog.aztec-project.org/2009/08/12/testen-von-nicht-offentlichen-methoden/#comments</comments>
		<pubDate>Wed, 12 Aug 2009 10:32:12 +0000</pubDate>
		<dc:creator>Christina Hirth</dc:creator>
				<category><![CDATA[How-To]]></category>
		<category><![CDATA[Unit Testing]]></category>

		<guid isPermaLink="false">http://blog.aztec-project.org/?p=567</guid>
		<description><![CDATA[Wir fragen uns seit langem, wie man internal Methoden testen kann, da eins klar ist, die Kapselung darf nicht wegen der Testfähigkeit verletzt werden. Letzte Woche hatte zum Glück auch jemand anderer dieses Problem und er hat gleich bei CCD-GoogleGroup nachgefragt. Und so haben wir auch erfahren, wie die Lösung lautet: für &#8220;internal&#8221;-Elemente gibt es [...]]]></description>
			<content:encoded><![CDATA[<p>Wir fragen uns seit langem, wie man <code>internal</code> Methoden testen kann, da eins klar ist, die Kapselung darf nicht wegen der Testfähigkeit verletzt werden.<br />
Letzte Woche hatte zum Glück auch jemand anderer dieses Problem und er hat gleich bei <a href="http://groups.google.com/group/clean-code-developer" target="_blank">CCD-GoogleGroup</a> nachgefragt. Und so haben wir auch erfahren, wie die Lösung lautet:</p>
<blockquote><p>für &#8220;internal&#8221;-Elemente gibt es auch die Option mit [assembly:<br />
InternalsVisibleTo("TestAssembly")] zu arbeiten. Alternativ kannst du die zu<br />
testenden Klassen auch per &#8220;Add existing item&#8221; und dann &#8220;Add as link&#8221; (siehe<br />
kleines Dreieck neben dem &#8220;Add&#8221;-Button) zum Testprojekt hinzufügen. </p></blockquote>
<p> (Danke <a href="http://groups.google.com/groups/profile?enc_user=oc5IRhcAAAAuR_jK16wX7vC61npQCQRRuMwB60D2RE2h9ZtdV0_Uhw">Alex</a>)</p>
<p>Danach war nur noch ein wenig Surfen nötig, um alles zu erfahren:</p>
<p><a href="http://msdn.microsoft.com/en-us/library/system.runtime.compilerservices.internalsvisibletoattribute.aspx">msdn </a> sagt:</p>
<div style="margin:10pt;color:#003399;font-family:Arial, Helvetica, sans-serif;font-size:11px;">
<div style="font-size:12px;font-weight:bold;">InternalsVisibleToAttribute Class</div>
<p>Specifies that types that are ordinarily visible only within the current assembly are visible to another assembly.</p>
<p><strong>User comment:</strong><br />
It is not documented anywhere to my knowledge, but if you want to grant &#8220;InternalsVisibleTo&#8221; permission to more than one assembly, you need to understand the syntax.</p>
<p>To do this you should NOT insert multiples instances of:  </p>
<p><code style="color:#000000">[assembly: InternalsVisibleTo("FirstAssembly")]</code></p>
<p>Instead do this:  </p>
<p><code style="color:#000000">[assembly: InternalsVisibleTo("FirstAssembly"),<br />
InternalsVisibleTo("SecondAssembly"),<br />
InternalsVisibleTo("ThirdAssembly")]</code></p>
<p>The former syntax is legal but fails, because each instance simply redefines and replaces any earlier ones, the latter syntax works as required.
</p></div>
<p><a href="http://dotnet-kicks.de/kick/?url=http%3a%2f%2fblog.aztec-project.org%2f2009%2f08%2f12%2ftesten-von-nicht-offentlichen-methoden%2f"><img src="http://dotnet-kicks.de/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fblog.aztec-project.org%2f2009%2f08%2f12%2ftesten-von-nicht-offentlichen-methoden%2f" border="0" alt="kick it on dotnet-kicks.de" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.aztec-project.org/2009/08/12/testen-von-nicht-offentlichen-methoden/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Wozu dient Reflection</title>
		<link>http://blog.aztec-project.org/2009/06/24/wozu-dient-reflection/</link>
		<comments>http://blog.aztec-project.org/2009/06/24/wozu-dient-reflection/#comments</comments>
		<pubDate>Wed, 24 Jun 2009 10:13:06 +0000</pubDate>
		<dc:creator>Thomas Christian</dc:creator>
				<category><![CDATA[How-To]]></category>
		<category><![CDATA[Assemblies]]></category>
		<category><![CDATA[Assembly]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[Reflection]]></category>

		<guid isPermaLink="false">http://blog.aztec-project.org/?p=280</guid>
		<description><![CDATA[Über Reflection kann man zur Laufzeit relativ einfach an alle Informationen eines Assembly herankommen. So ist es möglich, dass man von einem Assembly den Namen, Klassen, Methoden mit ihren Parametern, Eigenschaften und Rückgabewerte, usw. auslesen kann. Aber nicht nur das Auslesen ist möglich, sondern auch das Setzen.

Jetzt stellt sich für den einen oder anderen vielleicht die Frage, warum man zur Laufzeit auf diese Daten zugreifen kann. Jede Assembly verfügt über Module in denen sich die einzelnen Typen(Klassen) befinden. Für jedes Modul gibt es Metadaten, in denen die einzelnen Typen beschrieben werden. Die Assembly selbst verfügt noch über ein Manifest, in dem sich alle Informationen zum Assembly (z.B. Name, Version) befinden. Wenn man über Reflection auf Assemblies zugreift, dann werden diese Metadaten und das Manifest dafür herangezogen. Die Metadaten verfügen zwar noch über die Informationen, welche Modifizierer für Methoden, Properties, usw. verwendet wurden, aber der MSIL-Code (die Zwischensprache, die vom Endcompiler in die plattformspezifische Sprache übersetzt wird) nicht mehr. Die Modifizierer sind nur für den Compiler relevant und werden nach dem Kompilieren nicht mehr berücksichtigt. Somit ist es auch möglich über Reflection Properties, Methoden, usw. zu verwenden, die nicht öffentlich sind.

Für dieses Beispiel habe ich eine kleine Konsolen-Anwendung geschrieben (TestApplication), welche eine Referenz auf das Assembly TestProject.dll hat. Dieses Assembly hat zwei von mir erstellte Typen (Klassen) TestClass und SecondTestClass. In den beiden Klassen steckt keine Logik. Sie sind ausschließlich für dieses Beispiel erstellt worden, um ein paar Daten zu modifizieren und um zu zeigen wie die Informationen aus dem Assembly ausgelesen und verändert werden können und dass es möglich ist an nicht-öffentliche Methoden heranzukommen.  <a href="http://blog.aztec-project.org/2009/06/24/wozu-dient-reflection/">weiter lesen...</a>]]></description>
			<content:encoded><![CDATA[<h2><span style="color: #ffffff;">.</span></h2>
<h2>Vorbereitung</h2>
<p>Über Reflection kann man zur Laufzeit relativ einfach an alle Informationen eines Assembly herankommen. So ist es möglich, dass man von einem Assembly den Namen, Klassen, Methoden mit ihren Parametern, Eigenschaften und Rückgabewerte, usw. auslesen kann. Aber nicht nur das Auslesen ist möglich, sondern auch das Setzen.</p>
<p>Jetzt stellt sich für den einen oder anderen vielleicht die Frage, warum man zur Laufzeit auf diese Daten zugreifen kann. Jede Assembly verfügt über Module in denen sich die einzelnen Typen(Klassen) befinden. Für jedes Modul gibt es Metadaten, in denen die einzelnen Typen beschrieben werden. Die Assembly selbst verfügt noch über ein Manifest, in dem sich alle Informationen zum Assembly (z.B. Name, Version) befinden. Wenn man über Reflection auf Assemblies zugreift, dann werden diese Metadaten und das Manifest dafür herangezogen. Die Metadaten verfügen zwar noch über die Informationen, welche Modifizierer für Methoden, Properties, usw. verwendet wurden, aber der MSIL-Code (die Zwischensprache, die vom Endcompiler in die plattformspezifische Sprache übersetzt wird) nicht mehr. Die Modifizierer sind nur für den Compiler relevant und werden nach dem Kompilieren nicht mehr berücksichtigt. Somit ist es auch möglich über Reflection Properties, Methoden, usw. zu verwenden, die nicht öffentlich sind.</p>
<p>Für dieses Beispiel habe ich eine kleine Konsolen-Anwendung geschrieben (TestApplication), welche eine Referenz auf das Assembly TestProject.dll hat. Dieses Assembly hat zwei von mir erstellte Typen (Klassen) TestClass und SecondTestClass. In den beiden Klassen steckt keine Logik. Sie sind ausschließlich für dieses Beispiel erstellt worden, um ein paar Daten zu modifizieren und um zu zeigen wie die Informationen aus dem Assembly ausgelesen und verändert werden können und dass es möglich ist an nicht-öffentliche Methoden heranzukommen.</p>
<p><span style="text-decoration: underline;"><strong>TestClass.cs</strong></span></p>
<div style="background: white none repeat scroll 0% 0%; font-family: Courier New; font-size: 10pt; color: black;">
<pre style="margin: 0px;"><span style="color: blue;">using</span> System.Security.Cryptography;</pre>
<pre style="margin: 0px;"><span style="color: blue;">using</span> System.Text;</pre>
<pre style="margin: 0px;"><span style="color: blue;">namespace</span> TestProject {</pre>
<pre style="margin: 0px;"><span style="color: blue;">class</span> <span style="color: #2b91af;">TestClass</span> {</pre>
<pre style="margin: 0px;">    <span style="color: blue;">public</span> <span style="color: blue;">string</span> Name { <span style="color: blue;">get</span>; <span style="color: blue;">set</span>; }</pre>
<pre style="margin: 0px;">    <span style="color: blue;">public</span> <span style="color: blue;">string</span> Surname { <span style="color: blue;">get</span>; <span style="color: blue;">set</span>; }</pre>
<pre style="margin: 0px;">    <span style="color: blue;">private</span> <span style="color: blue;">string</span> Password { <span style="color: blue;">get</span>; <span style="color: blue;">set</span>; }</pre>
<pre style="margin: 0px;">    <span style="color: blue;">public</span> <span style="color: blue;">string</span> GetFullName() {</pre>
<pre style="margin: 0px;">        <span style="color: blue;">return</span> <span style="color: blue;">string</span>.Format(<span style="color: #a31515;">"{0} {1}"</span>, Name ?? <span style="color: blue;">string</span>.Empty, Surname ?? <span style="color: blue;">string</span>.Empty).Trim();</pre>
<pre style="margin: 0px;">    }</pre>
<pre style="margin: 0px;">    <span style="color: blue;">public</span> <span style="color: blue;">void</span> SetPasswort(<span style="color: blue;">string</span> password){</pre>
<pre style="margin: 0px;">        Password = password;</pre>
<pre style="margin: 0px;">    }</pre>
<pre style="margin: 0px;">    <span style="color: blue;">private</span> <span style="color: blue;">static</span> <span style="color: blue;">string</span> CalcPassword(<span style="color: blue;">string</span> password){</pre>
<pre style="margin: 0px;">        <span style="color: #2b91af;">MD5</span> md5 = <span style="color: #2b91af;">MD5</span>.Create();</pre>
<pre style="margin: 0px;">        <span style="color: blue;">byte</span>[] data = md5.ComputeHash(<span style="color: #2b91af;">Encoding</span>.Default.GetBytes(password));</pre>
<pre style="margin: 0px;">        <span style="color: #2b91af;">StringBuilder</span> hashPassword = <span style="color: blue;">new</span> <span style="color: #2b91af;">StringBuilder</span>();</pre>
<pre style="margin: 0px;">        <span style="color: blue;">foreach</span> (<span style="color: blue;">byte</span> b <span style="color: blue;">in</span> data){</pre>
<pre style="margin: 0px;">            hashPassword.Append(b);</pre>
<pre style="margin: 0px;">        }</pre>
<pre style="margin: 0px;">        <span style="color: blue;">return</span> hashPassword.ToString();</pre>
<pre style="margin: 0px;">    }</pre>
<pre style="margin: 0px;">    <span style="color: blue;">public</span> <span style="color: blue;">static</span> <span style="color: blue;">string</span> DoSomething(<span style="color: blue;">string</span> value) {</pre>
<pre style="margin: 0px;">        <span style="color: green;">// do something</span></pre>
<pre style="margin: 0px;">        <span style="color: blue;">return</span> value;</pre>
<pre style="margin: 0px;">    }</pre>
<pre style="margin: 0px;">}</pre>
</div>
<p><span style="text-decoration: underline;"><strong>SecondTestClass.cs</strong></span></p>
<div style="background: white none repeat scroll 0% 0%; font-family: Courier New; font-size: 10pt; color: black;">
<pre style="margin: 0px;"><span style="color: blue;">namespace</span> TestProject {</pre>
<pre style="margin: 0px;">    <span style="color: blue;">public</span> <span style="color: blue;">class</span> <span style="color: #2b91af;">SecondTestClass</span> {</pre>
<pre style="margin: 0px;">        <span style="color: blue;">public</span> <span style="color: blue;">int</span> Addition(<span style="color: blue;">int</span> a, <span style="color: blue;">int</span> b) {</pre>
<pre style="margin: 0px;">            <span style="color: blue;">return</span> a + b;</pre>
<pre style="margin: 0px;">        }</pre>
<pre style="margin: 0px;">        <span style="color: blue;">public</span> <span style="color: blue;">int</span> Multiply(<span style="color: blue;">int</span> a, <span style="color: blue;">int</span> b) {</pre>
<pre style="margin: 0px;">            <span style="color: blue;">return</span> a * b;</pre>
<pre style="margin: 0px;">        }</pre>
<pre style="margin: 0px;">        <span style="color: blue;">public</span> <span style="color: blue;">double</span> Divide(<span style="color: blue;">int</span> a, <span style="color: blue;">int</span> b) {</pre>
<pre style="margin: 0px;">            <span style="color: blue;">if</span> (b == 0) <span style="color: blue;">return</span> 0;</pre>
<pre style="margin: 0px;">            <span style="color: blue;">return</span> a / b;</pre>
<pre style="margin: 0px;">        }</pre>
<pre style="margin: 0px;">    }</pre>
<pre style="margin: 0px;">}
<span style="color: #ffffff;">.
.</span></pre>
</div>
<h2>Auslesen von Assembly- Type-Informationen</h2>
<p>Mit der Methode Thread.GetDomain().GetAssemblies() bekommt man alle referenzierten Assemblies der aktuellen Domäne. Damit die TestProject-Assembly auch in dieser Domäne vorhanden ist, muss vor dem Aufruf dieser Methode eine Instanz von einem Objekt dieses Assemblies erzeugt werden.</p>
<p>Um sich nun alle Assemblies der aktuellen Domäne anzeigen zu lassen, könnte man folgendes schreiben:</p>
<div style="background: white none repeat scroll 0% 0%; font-family: Courier New; font-size: 10pt; color: black;">
<pre style="margin: 0px;"><span style="color: blue;">static</span> <span style="color: blue;">void</span> Main(<span style="color: blue;">string</span>[] args) {</pre>
<pre style="margin: 0px;">    <span style="color: #2b91af;">SecondTestClass</span> secondTestClass = <span style="color: blue;">new</span> <span style="color: #2b91af;">SecondTest</span><span style="color: #2b91af;"> </span><span style="color: #2b91af;">Class</span>();</pre>
<pre style="margin: 0px;">    <span style="color: #2b91af;">Assembly</span>[] assemblies = <span style="color: #2b91af;">Thread</span>.GetDomain().GetAssemblies();</pre>
<pre style="margin: 0px;">    <span style="color: blue;">foreach</span> (<span style="color: blue;">var</span> assembly <span style="color: blue;">in</span> assemblies) {</pre>
<pre style="margin: 0px;">        <span style="color: #2b91af;">Console</span>.WriteLine(<span style="color: blue;">string</span>.Format(<span style="color: #a31515;">"-- {0} ver.: {1}"</span>, assembly.GetName().Name
                                                          , assembly.GetName().Version));</pre>
<pre style="margin: 0px;">    }</pre>
<pre style="margin: 0px;">    <span style="color: #2b91af;">Console</span>.ReadLine();</pre>
<pre style="margin: 0px;">}
<img class="size-full wp-image-281 aligncenter" src="http://blog.aztec-project.org/wp-content/uploads/2009/06/1.png" alt="1" width="549" height="120" /></pre>
</div>
<p><span style="color: #ffffff;">.</span></p>
<p>Nun könnte man noch alle zur Verfügung stehenden Typen(Klassen) aus der TestProject-Assembly anzeigen.</p>
<div style="background: white none repeat scroll 0% 0%; font-family: Courier New; font-size: 10pt; color: black;">
<div style="background: white none repeat scroll 0% 0%; font-family: Courier New; font-size: 10pt; color: black;">
<pre style="margin: 0px;"><span style="color: blue;">static</span> <span style="color: blue;">void</span> Main(<span style="color: blue;">string</span>[] args) {</pre>
<pre style="margin: 0px;">    <span style="color: #2b91af;">SecondTestClass</span> secondTestClass = <span style="color: blue;">new</span> <span style="color: #2b91af;">SecondTestClass</span>();</pre>
<pre style="margin: 0px;">    <span style="color: #2b91af;">Assembly</span>[] assemblies = <span style="color: #2b91af;">Thread</span>.GetDomain().GetAssemblies();</pre>
<pre style="margin: 0px;">    <span style="color: blue;">foreach</span> (<span style="color: blue;">var</span> assembly <span style="color: blue;">in</span> assemblies) {</pre>
<pre style="margin: 0px;">        <span style="color: #2b91af;">Console</span>.WriteLine(<span style="color: blue;">string</span>.Format(<span style="color: #a31515;">"-- {0} ver.: {1}"</span>, assembly.GetName().Name
<pre style="margin: 0px;">                                                          , assembly.GetName().Version));</pre>
</pre>
<pre style="margin: 0px;">        <span style="color: blue;">if</span> (assembly.GetName().Name.Equals(<span style="color: #a31515;">"TestProject"</span>)) {</pre>
<pre style="margin: 0px;">            <span style="color: #2b91af;">Type</span>[] types = assembly.GetTypes();</pre>
<pre style="margin: 0px;">            <span style="color: blue;">foreach</span> (<span style="color: blue;">var</span> type <span style="color: blue;">in</span> types) {</pre>
<pre style="margin: 0px;">                <span style="color: #2b91af;">Console</span>.WriteLine(<span style="color: #a31515;">"  ++{0}"</span>, type.Name);</pre>
<pre style="margin: 0px;">            }</pre>
<pre style="margin: 0px;">        }</pre>
<pre style="margin: 0px;">    }</pre>
<pre style="margin: 0px;">    <span style="color: #2b91af;">Console</span>.ReadLine();</pre>
<pre style="margin: 0px; text-align: left;">}

<img class="size-full wp-image-284 aligncenter" title="2" src="http://blog.aztec-project.org/wp-content/uploads/2009/06/2.png" alt="2" width="533" height="130" /></pre>
</div>
</div>
<p><span style="color: #ffffff;">.</span></p>
<p>Wenn man nun allerdings Informationen eines bestimmten Types haben möchte, so werden diese Informationen aus den Metadaten des Moduls geladen, in dem sich der Type befindet. Um zum Beispiel alle öffentlichen Methoden eines Types anzuzeigen, könnte man folgendes schreiben:</p>
<div style="background: white none repeat scroll 0% 0%; font-family: Courier New; font-size: 10pt; color: black;">
<pre style="margin: 0px;"><span style="color: blue;">static</span> <span style="color: blue;">void</span> Main(<span style="color: blue;">string</span>[] args) {</pre>
<pre style="margin: 0px;">    <span style="color: #2b91af;">SecondTestClass</span> secondTestClass = <span style="color: blue;">new</span> <span style="color: #2b91af;">SecondTestClass</span>();</pre>
<pre style="margin: 0px;">    <span style="color: #2b91af;">Assembly</span>[] assemblies = <span style="color: #2b91af;">Thread</span>.GetDomain().GetAssemblies();</pre>
<pre style="margin: 0px;">    <span style="color: blue;">foreach</span> (<span style="color: blue;">var</span> assembly <span style="color: blue;">in</span> assemblies) {</pre>
<pre style="margin: 0px;">        <span style="color: #2b91af;">Console</span>.WriteLine(<span style="color: blue;">string</span>.Format(<span style="color: #a31515;">"-- {0} ver.: {1}"</span>, assembly.GetName().Name
                                                          , assembly.GetName().Version));</pre>
<pre style="margin: 0px;">        <span style="color: blue;">if</span> (assembly.GetName().Name.Equals(<span style="color: #a31515;">"TestProject"</span>)) {</pre>
<pre style="margin: 0px;">            <span style="color: #2b91af;">Type</span>[] types = assembly.GetTypes();</pre>
<pre style="margin: 0px;">            <span style="color: blue;">foreach</span> (<span style="color: blue;">var</span> type <span style="color: blue;">in</span> types) {</pre>
<pre style="margin: 0px;">                <span style="color: #2b91af;">Console</span>.WriteLine(<span style="color: #a31515;">"  ++ {0}"</span>, type.Name);</pre>
<pre style="margin: 0px;">                <span style="color: #2b91af;">MethodInfo</span>[] methodInfos = type.GetMethods();</pre>
<pre style="margin: 0px;">                <span style="color: blue;">foreach</span> (<span style="color: blue;">var</span> info <span style="color: blue;">in</span> methodInfos) {</pre>
<pre style="margin: 0px;">                    <span style="color: #2b91af;">Console</span>.WriteLine(<span style="color: #a31515;">"    ++ {0}"</span>, info.Name);</pre>
<pre style="margin: 0px;">                }</pre>
<pre style="margin: 0px;">            }</pre>
<pre style="margin: 0px;">        }</pre>
<pre style="margin: 0px;">    }</pre>
<pre style="margin: 0px;">    <span style="color: #2b91af;">Console</span>.ReadLine();</pre>
<pre style="margin: 0px;">}</pre>
</div>
<p align="center">
<p style="text-align: center;"><img class="size-full wp-image-285 aligncenter" title="3" src="http://blog.aztec-project.org/wp-content/uploads/2009/06/3.png" alt="3" width="629" height="383" /></p>
<p><span style="color: #ffffff;">.</span></p>
<p>Es fällt auf, dass auch die Methoden ToString, Equals, GetHashCode und GetType in beiden Klassen angezeigt werden, obwohl diese in den Klassen überhaupt nicht deklariert wurden. Das liegt daran, dass alle Typen von <span style="color: blue;">object </span>ableiten und <span style="color: blue;">object</span> diese Methoden implementiert. Was noch auffällt ist, dass nur öffentliche Methoden angezeigt werden. Möchte man sich auch die privaten Methoden anzeigen lassen, so muss man der Methode type.GetMethods Parameter übergeben. Diese Methode verlangt BindingFlags, die man mit dem Bitweise ODER-Operator (|) miteinander verknüpfen kann. Um sich nun öffentliche und private Methoden anzeigen zu lassen, muss der Aufruf der Methode type.GetMethods folgendermaßen lauten:</p>
<div style="background: white none repeat scroll 0% 0%; font-family: Courier New; font-size: 10pt; color: black; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;">
<pre style="margin: 0px;"><span style="color: #2b91af;">MethodInfo</span>[] methodInfos = type.GetMethods(<span style="color: #2b91af;">BindingFlags</span>.Public | <span style="color: #2b91af;">BindingFlags</span>.NonPublic | <span style="color: #2b91af;">BindingFlags</span>.Instance);</pre>
</div>
<p>Dieser Aufruf gibt an, dass man alle öffentlichen und nicht-öffentlichen Instanz-Methoden bekommen möchte. Instanz-Methoden bedeutet, dass es sich um Methoden handelt, die nur mit dem Instanzieren eines Objektes zur Verfügung stehen. D.h. es werden keine static-Methoden angezeigt. Es gibt noch weitere BindingFlags, auf die ich hier allerdings nicht weiter eingehen möchte.</p>
<p>Das ganze könnte man natürlich noch in der Form weiter treiben, dass man sich die kompletten Methodensignaturen mit Modifizierer, Schlüsselwort und Rückgabewert anzeigen lässt:</p>
<div style="background: white none repeat scroll 0% 0%; font-family: Courier New; font-size: 10pt; color: black;">
<pre style="margin: 0px;"><span style="color: blue;">static</span> <span style="color: blue;">void</span> Main(<span style="color: blue;">string</span>[] args) {</pre>
<pre style="margin: 0px;">    <span style="color: #2b91af;">SecondTestClass</span> secondTestClass = <span style="color: blue;">new</span> <span style="color: #2b91af;">SecondTestClass</span>();</pre>
<pre style="margin: 0px;">    <span style="color: #2b91af;">Assembly</span>[] assemblies = <span style="color: #2b91af;">Thread</span>.GetDomain().GetAssemblies();</pre>
<pre style="margin: 0px;">    <span style="color: blue;">foreach</span> (<span style="color: blue;">var</span> assembly <span style="color: blue;">in</span> assemblies) {</pre>
<pre style="margin: 0px;">        <span style="color: #2b91af;">Console</span>.WriteLine(<span style="color: blue;">string</span>.Format(<span style="color: #a31515;">"-- {0} ver.: {1}"</span>, assembly.GetName().Name, assembly.GetName().Version));</pre>
<pre style="margin: 0px;">        <span style="color: blue;">if</span> (assembly.GetName().Name.Equals(<span style="color: #a31515;">"TestProject"</span>)) {</pre>
<pre style="margin: 0px;">            <span style="color: #2b91af;">Type</span>[] types = assembly.GetTypes();</pre>
<pre style="margin: 0px;">            <span style="color: blue;">foreach</span> (<span style="color: blue;">var</span> type <span style="color: blue;">in</span> types) {</pre>
<pre style="margin: 0px;">                <span style="color: #2b91af;">Console</span>.WriteLine(<span style="color: #a31515;">"  ++ {0}"</span>, type.Name);</pre>
<pre style="margin: 0px;">                <span style="color: #2b91af;">MethodInfo</span>[] methodInfos = type.GetMethods(<span style="color: #2b91af;">BindingFlags</span>.Public | <span style="color: #2b91af;">BindingFlags</span>.NonPublic
                                                                               | <span style="color: #2b91af;">BindingFlags</span>.Instance
<pre style="margin: 0px;">                                                                               | <span style="color: #2b91af;">BindingFlags</span>.Static);</pre>
</pre>
<pre style="margin: 0px;">                <span style="color: blue;">foreach</span> (<span style="color: blue;">var</span> info <span style="color: blue;">in</span> methodInfos) {</pre>
<pre style="margin: 0px;">                    <span style="color: blue;">string</span> modifier = GetModifier(info);</pre>
<pre style="margin: 0px;">                    <span style="color: blue;">string</span> keyword = GetKeyword(info);</pre>
<pre style="margin: 0px;">                    <span style="color: blue;">string</span> parameters = GetParameters(info);</pre>
<pre style="margin: 0px;">                    <span style="color: blue;">if</span> (!<span style="color: blue;">string</span>.IsNullOrEmpty(keyword)) {</pre>
<pre style="margin: 0px;">                        keyword = <span style="color: blue;">string</span>.Format(<span style="color: #a31515;">"{0} "</span>, keyword);</pre>
<pre style="margin: 0px;">                    }</pre>
<pre style="margin: 0px;">                    <span style="color: #2b91af;">Console</span>.WriteLine(<span style="color: #a31515;">"    ++ {0} {1}{2}{3}({4})"</span>, modifier, keyword
                                                                 , info.ReturnParameter, info.Name, parameters);</pre>
<pre style="margin: 0px;">                }</pre>
<pre style="margin: 0px;">            }</pre>
<pre style="margin: 0px;">        }</pre>
<pre style="margin: 0px;">    }</pre>
<pre style="margin: 0px;">    <span style="color: #2b91af;">Console</span>.ReadLine();</pre>
<pre style="margin: 0px;">}</pre>
<pre style="margin: 0px;"><span style="color: blue;">private</span> <span style="color: blue;">static</span> <span style="color: blue;">string</span> GetModifier(<span style="color: #2b91af;">MethodInfo</span> info) {</pre>
<pre style="margin: 0px;">    <span style="color: blue;">if</span> (info.IsPublic) <span style="color: blue;">return</span> <span style="color: #a31515;">"public"</span>;</pre>
<pre style="margin: 0px;">    <span style="color: blue;">return</span> <span style="color: #a31515;">"private"</span>;</pre>
<pre style="margin: 0px;">}</pre>
<pre style="margin: 0px;"><span style="color: blue;">private</span> <span style="color: blue;">static</span> <span style="color: blue;">string</span> GetKeyword(<span style="color: #2b91af;">MethodInfo</span> info) {</pre>
<pre style="margin: 0px;">    <span style="color: blue;">if</span> (info.IsStatic) <span style="color: blue;">return</span> <span style="color: #a31515;">"static"</span>;</pre>
<pre style="margin: 0px;">    <span style="color: blue;">if</span> (info.IsVirtual) <span style="color: blue;">return</span> <span style="color: #a31515;">"virtual"</span>;</pre>
<pre style="margin: 0px;">    <span style="color: blue;">return</span> <span style="color: blue;">string</span>.Empty;</pre>
<pre style="margin: 0px;">}</pre>
<pre style="margin: 0px;"><span style="color: blue;">private</span> <span style="color: blue;">static</span> <span style="color: blue;">string</span> GetParameters(<span style="color: #2b91af;">MethodInfo</span> info) {</pre>
<pre style="margin: 0px;">    <span style="color: #2b91af;">StringBuilder</span> parameters = <span style="color: blue;">new</span> <span style="color: #2b91af;">StringBuilder</span>();</pre>
<pre style="margin: 0px;">    <span style="color: #2b91af;">ParameterInfo</span>[] parameterInfos = info.GetParameters();</pre>
<pre style="margin: 0px;">    <span style="color: blue;">if</span> (parameterInfos != <span style="color: blue;">null</span>) {</pre>
<pre style="margin: 0px;">        <span style="color: blue;">foreach</span> (<span style="color: #2b91af;">ParameterInfo</span> parameterInfo <span style="color: blue;">in</span> parameterInfos) {</pre>
<pre style="margin: 0px;">            <span style="color: blue;">if</span> (!<span style="color: blue;">string</span>.IsNullOrEmpty(parameters.ToString())) {</pre>
<pre style="margin: 0px;">                parameters.Append(<span style="color: #a31515;">", "</span>);</pre>
<pre style="margin: 0px;">            }</pre>
<pre style="margin: 0px;">            parameters.AppendFormat(<span style="color: #a31515;">"{0} {1}"</span>, parameterInfo.ParameterType.Name, parameterInfo.Name);</pre>
<pre style="margin: 0px;">        }</pre>
<pre style="margin: 0px;">    }</pre>
<pre style="margin: 0px;">    <span style="color: blue;">return</span> parameters.ToString();</pre>
<pre style="margin: 0px;">}</pre>
</div>
<p style="text-align: center;"><img class="size-full wp-image-287 aligncenter" title="4" src="http://blog.aztec-project.org/wp-content/uploads/2009/06/4.png" alt="4" width="605" height="443" /></p>
<p><span style="color: #ffffff;">.</span></p>
<p>Nicht immer ist bereits während der Entwicklung bekannt, aus welchem Assembly man Informationen benötigt. Sodass die Methode Thread.GetDomain().GetAssemblies() nicht verwendet werden kann. Eine weitere Möglichkeit an ein Assembly zu kommen ist es direkt zu laden. Dafür bietet die Klasse Assembly die statische Methode Assembly.LoadFrom zum Laden von Assemblies. Statt dem Laden des Assembly über die aktuelle Domäne, wird das nächste Beispiel so modifiziert, dass die TestProject-Assembly direkt aus einem Verzeichnis heraus geladen wird.</p>
<div style="background: white none repeat scroll 0% 0%; font-family: Courier New; font-size: 10pt; color: black; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;">
<pre style="margin: 0px;"><span style="color: blue;">static</span> <span style="color: blue;">void</span> Main(<span style="color: blue;">string</span>[] args) {</pre>
<pre style="margin: 0px;">    <span style="color: #2b91af;">Assembly</span> assembly = <span style="color: #2b91af;">Assembly</span>.LoadFrom(<span style="color: #a31515;">@"c:\TestProject.dll"</span>);</pre>
<pre style="margin: 0px;">    <span style="color: blue;">if</span> (assembly != <span style="color: blue;">null</span>) {</pre>
<pre style="margin: 0px;">        <span style="color: #2b91af;">Console</span>.WriteLine(<span style="color: blue;">string</span>.Format(<span style="color: #a31515;">"-- {0} ver.: {1}"</span>, assembly.GetName().Name, assembly.GetName().Version));</pre>
<pre style="margin: 0px;">        <span style="color: #2b91af;">Type</span>[] types = assembly.GetTypes();</pre>
<pre style="margin: 0px;">        <span style="color: blue;">foreach</span> (<span style="color: blue;">var</span> type <span style="color: blue;">in</span> types) {</pre>
<pre style="margin: 0px;">            <span style="color: #2b91af;">Console</span>.WriteLine(<span style="color: #a31515;">"  ++ {0}"</span>, type.Name);</pre>
<pre style="margin: 0px;">            <span style="color: #2b91af;">MethodInfo</span>[] methodInfos =</pre>
<pre style="margin: 0px;">            type.GetMethods(<span style="color: #2b91af;">BindingFlags</span>.Public | <span style="color: #2b91af;">BindingFlags</span>.NonPublic | <span style="color: #2b91af;">BindingFlags</span>.Instance |</pre>
<pre style="margin: 0px;">            <span style="color: #2b91af;">BindingFlags</span>.Static);</pre>
<pre style="margin: 0px;">            <span style="color: blue;">foreach</span> (<span style="color: blue;">var</span> info <span style="color: blue;">in</span> methodInfos) {</pre>
<pre style="margin: 0px;">                <span style="color: blue;">string</span> modifier = GetModifier(info);</pre>
<pre style="margin: 0px;">                <span style="color: blue;">string</span> keyword = GetKeyword(info);</pre>
<pre style="margin: 0px;">                <span style="color: blue;">string</span> parameters = GetParameters(info);</pre>
<pre style="margin: 0px;">                <span style="color: blue;">if</span> (!<span style="color: blue;">string</span>.IsNullOrEmpty(keyword)) {</pre>
<pre style="margin: 0px;">                    keyword = <span style="color: blue;">string</span>.Format(<span style="color: #a31515;">"{0} "</span>, keyword);</pre>
<pre style="margin: 0px;">                }</pre>
<pre style="margin: 0px;">                <span style="color: #2b91af;">Console</span>.WriteLine(<span style="color: #a31515;">"    ++ {0} {1}{2}{3}({4})"</span>, modifier, keyword, info.ReturnParameter,</pre>
<pre style="margin: 0px;">                info.Name, parameters);</pre>
<pre style="margin: 0px;">            }</pre>
<pre style="margin: 0px;">        }</pre>
<pre style="margin: 0px;">    }</pre>
<pre style="margin: 0px;">    <span style="color: #2b91af;">Console</span>.ReadLine();</pre>
<pre style="margin: 0px;">}</pre>
</div>
<p align="center">
<div id="attachment_288" class="wp-caption aligncenter" style="width: 687px"><img class="size-full wp-image-288" title="5" src="http://blog.aztec-project.org/wp-content/uploads/2009/06/5.png" alt="5" width="677" height="419" /><p class="wp-caption-text">Man sieht, dass die gleiche Ausgabe wie bereits im vorherigen Beispiel generiert wird.</p></div>
<p style="text-align: center;">
<h2><span style="color: #ffffff;">.</span></h2>
<h2>Interaktionen</h2>
<p>Nachdem die Vorgehensweise nun klar sein sollte, möchte ich nun den eigentlich interessanten Teil demonstrieren. Wie kann man nun auf Methoden usw. zugreifen und wie können Werte aus einem Type gelesen und veränder werden? Wenn man die Methode SecondTestClass.Addition(int a, int b) aufrufen möchte, dann braucht man die Methodeninformationen von dem Type SecondTestClass aus dem TestProject-Assembly. D.h. man muss wie in den obigen Beispielen auch über alle Typen iterieren, um an den gesuchten Type SecondTestClass zu kommen. Hat man den gesuchten Type gefunden, so kann man sich von diesem alle Methoden in einem Array zurückgeben lassen. Dieses Array kann dann wieder ganz normal durchlaufen und nach der gewünschten Methode durchsucht werden. Hat man die Methode gefunden so muss zuerst eine Instanz von dem Objekt erzeugt werden und dafür gibt es den Activator, der die statische Methode CreateInstance beinhaltet. Als Parameter übergibt man ihr den Type von dem eine Instanz erzeugt werden soll. Jetzt kann man über die MethodInfo die Methode aufrufen. Dazu muss der Methode die Instanz des Objektes übergeben werden, von welchem die Methode aufgerufen werden soll und zusätzlich noch ein Array von Objekten, welche die zu übergebenen Parameter beinhaltet. Hat die Methode keine Parameter, so muss null übergeben werden. Dabei muss der Rückgabewert in den erwarteten Wert gecastet werden. Das ganze könnte dann folgendermaßen aussehen:</p>
<div style="background: white none repeat scroll 0% 0%; font-family: Courier New; font-size: 10pt; color: black; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;">
<pre style="margin: 0px;"><span style="color: blue;">static</span> <span style="color: blue;">void</span> Main(<span style="color: blue;">string</span>[] args) {</pre>
<pre style="margin: 0px;">    <span style="color: #2b91af;">Assembly</span> assembly = <span style="color: #2b91af;">Assembly</span>.LoadFrom(<span style="color: #a31515;">@"c:\TestProject.dll"</span>);</pre>
<pre style="margin: 0px;">    <span style="color: blue;">if</span> (assembly != <span style="color: blue;">null</span>) {</pre>
<pre style="margin: 0px;">        <span style="color: #2b91af;">Console</span>.WriteLine(<span style="color: blue;">string</span>.Format(<span style="color: #a31515;">"-- {0} ver.: {1}"</span>, assembly.GetName().Name, assembly.GetName().Version));</pre>
<pre style="margin: 0px;">        <span style="color: #2b91af;">Type</span>[] types = assembly.GetTypes();</pre>
<pre style="margin: 0px;">        <span style="color: blue;">foreach</span> (<span style="color: blue;">var</span> type <span style="color: blue;">in</span> types) {</pre>
<pre style="margin: 0px;">            <span style="color: blue;">if</span> (type.Name.Equals(<span style="color: #a31515;">"SecondTestClass"</span>)) {</pre>
<pre style="margin: 0px;">                <span style="color: #2b91af;">Console</span>.WriteLine(<span style="color: #a31515;">"  ++ {0}"</span>, type.Name);</pre>
<pre style="margin: 0px;">                <span style="color: #2b91af;">MethodInfo</span>[] methodInfos = type.GetMethods();</pre>
<pre style="margin: 0px;">                <span style="color: blue;">foreach</span> (<span style="color: blue;">var</span> info <span style="color: blue;">in</span> methodInfos) {</pre>
<pre style="margin: 0px;">                    <span style="color: blue;">if</span> (info.Name.Equals(<span style="color: #a31515;">"Addition"</span>)) {</pre>
<pre style="margin: 0px;">                        <span style="color: blue;">object</span> obj = <span style="color: #2b91af;">Activator</span>.CreateInstance(type);</pre>
<pre style="margin: 0px;">                        <span style="color: blue;">int</span> value = (<span style="color: blue;">int</span>)info.Invoke(obj, <span style="color: blue;">new</span> <span style="color: blue;">object</span>[] { 2, 5 });</pre>
<pre style="margin: 0px;">                        <span style="color: #2b91af;">Console</span>.WriteLine(<span style="color: #a31515;">"    ++ {0}(2 + 5) = {1}"</span>, info.Name, value);</pre>
<pre style="margin: 0px;">                    }</pre>
<pre style="margin: 0px;">                }</pre>
<pre style="margin: 0px;">            }</pre>
<pre style="margin: 0px;">        }</pre>
<pre style="margin: 0px;">    }</pre>
<pre style="margin: 0px;">    <span style="color: #2b91af;">Console</span>.ReadLine();</pre>
<pre style="margin: 0px;">}</pre>
</div>
<p align="center">
<div id="attachment_289" class="wp-caption aligncenter" style="width: 543px"><img class="size-full wp-image-289" title="6" src="http://blog.aztec-project.org/wp-content/uploads/2009/06/6.png" alt="6" width="533" height="143" /><p class="wp-caption-text">Aufruf der Methode Addition</p></div>
<p style="text-align: center;">
<p><span style="color: #ffffff;">.</span></p>
<p>Bei statischen Methoden kann das Erzeugen der Instanz weggelassen werden und für den Parameter des Instanz-Objektes kann null übergeben werden.</p>
<div style="background: white none repeat scroll 0% 0%; font-family: Courier New; font-size: 10pt; color: black; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;">
<pre style="margin: 0px;"><span style="color: blue;">if</span> (type.Name.Equals(<span style="color: #a31515;">"TestClass"</span>)) {</pre>
<pre style="margin: 0px;">    <span style="color: #2b91af;">Console</span>.WriteLine(<span style="color: #a31515;">"  ++ {0}"</span>, type.Name);</pre>
<pre style="margin: 0px;">    <span style="color: #2b91af;">MethodInfo</span>[] methodInfos = type.GetMethods(<span style="color: #2b91af;">BindingFlags</span>.NonPublic | <span style="color: #2b91af;">BindingFlags</span>.Static);</pre>
<pre style="margin: 0px;">    <span style="color: blue;">foreach</span> (<span style="color: blue;">var</span> info <span style="color: blue;">in</span> methodInfos) {</pre>
<pre style="margin: 0px;">        <span style="color: blue;">if</span> (info.Name.Equals(<span style="color: #a31515;">"CalcPassword"</span>)) {</pre>
<pre style="margin: 0px;">            <span style="color: blue;">string</span> value = (<span style="color: blue;">string</span>)info.Invoke(<span style="color: blue;">null</span>, <span style="color: blue;">new</span> <span style="color: blue;">object</span>[] { <span style="color: #a31515;">"myPassword"</span> });</pre>
<pre style="margin: 0px;">            <span style="color: #2b91af;">Console</span>.WriteLine(<span style="color: #a31515;">"    ++ {0}(\"myPassword\") = {1}"</span>, info.Name, value);</pre>
<pre style="margin: 0px;">        }</pre>
<pre style="margin: 0px;">    }</pre>
<pre style="margin: 0px;">}</pre>
</div>
<p align="center">
<div id="attachment_290" class="wp-caption aligncenter" style="width: 687px"><img class="size-full wp-image-290" title="7" src="http://blog.aztec-project.org/wp-content/uploads/2009/06/7.png" alt="7" width="677" height="155" /><p class="wp-caption-text">Das übergebene Passwort wurde über eine statische Methode gehashed.</p></div>
<p style="text-align: center;">
<p><span style="color: #ffffff;">.</span></p>
<p>Um den Wert einer Property auszulesen, muss anstelle von MethodInfo die PropertyInfo verwendet werden. Aus dieser kann dann über die Methode PropertyInfo.GetValue der aktuelle Wert zurückgegeben werden. Da in diesem Beispiel nach dem Instanzieren des Objektes noch keine Werte zugewiesen wurden, sind die Properties leer.</p>
<div style="background: white none repeat scroll 0% 0%; font-family: Courier New; font-size: 10pt; color: black; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;">
<pre style="margin: 0px;"><span style="color: blue;">static</span> <span style="color: blue;">void</span> Main(<span style="color: blue;">string</span>[] args) {</pre>
<pre style="margin: 0px;">    <span style="color: #2b91af;">Assembly</span> assembly = <span style="color: #2b91af;">Assembly</span>.LoadFrom(<span style="color: #a31515;">@"C:\ TestProject.dll"</span>);</pre>
<pre style="margin: 0px;">    <span style="color: blue;">if</span> (assembly != <span style="color: blue;">null</span>) {</pre>
<pre style="margin: 0px;">        <span style="color: #2b91af;">Console</span>.WriteLine(<span style="color: blue;">string</span>.Format(<span style="color: #a31515;">"-- {0} ver.: {1}"</span>, assembly.GetName().Name, assembly.GetName().Version));</pre>
<pre style="margin: 0px;">        <span style="color: #2b91af;">Type</span>[] types = assembly.GetTypes();</pre>
<pre style="margin: 0px;">        <span style="color: blue;">foreach</span> (<span style="color: blue;">var</span> type <span style="color: blue;">in</span> types) {</pre>
<pre style="margin: 0px;">            <span style="color: blue;">if</span> (type.Name.Equals(<span style="color: #a31515;">"TestClass"</span>)) {</pre>
<pre style="margin: 0px;">                <span style="color: #2b91af;">Console</span>.WriteLine(<span style="color: #a31515;">"  ++ {0}"</span>, type.Name);
<pre style="margin: 0px;"><span style="color: blue;">                object</span> obj = <span style="color: #2b91af;">Activator</span>.CreateInstance(type);</pre>
</pre>
<pre style="margin: 0px;">                <span style="color: #2b91af;">PropertyInfo</span>[] propertyInfos = type.GetProperties(<span style="color: #2b91af;">BindingFlags</span>.Public | <span style="color: #2b91af;">BindingFlags</span>.NonPublic
                                                                                      | <span style="color: #2b91af;">BindingFlags</span>.Instance);</pre>
<pre style="margin: 0px;">                <span style="color: blue;">foreach</span> (<span style="color: blue;">var</span> info <span style="color: blue;">in</span> propertyInfos) {</pre>
<pre style="margin: 0px;">                    <span style="color: #2b91af;">Console</span>.WriteLine(<span style="color: #a31515;">"    ++ {0} = {1}"</span>, info.Name, info.GetValue(obj, <span style="color: blue;">null</span>));</pre>
<pre style="margin: 0px;">                }</pre>
<pre style="margin: 0px;">            }</pre>
<pre style="margin: 0px;">        }</pre>
<pre style="margin: 0px;">    }</pre>
<pre style="margin: 0px;">    <span style="color: #2b91af;">Console</span>.ReadLine();</pre>
<pre style="margin: 0px;">}
<img class="aligncenter size-full wp-image-373" title="8" src="http://blog.aztec-project.org/wp-content/uploads/2009/06/8.png" alt="8" width="517" height="203" /></pre>
</div>
<p><span style="color: #ffffff;">.</span></p>
<p>Wenn man nun die Properties mit Werten belegen möchte, so muss man analog zur Methode PropertyInfo.GetValue, die Methode PropertyInfo. SetValue verwenden.</p>
<div style="background: white none repeat scroll 0% 0%; font-family: Courier New; font-size: 10pt; color: black; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;">
<pre style="margin: 0px;"><span style="color: blue;">if</span> (type.Name.Equals(<span style="color: #a31515;">"TestClass"</span>)) {</pre>
<pre style="margin: 0px;">    <span style="color: #2b91af;">Console</span>.WriteLine(<span style="color: #a31515;">"  ++ {0}"</span>, type.Name);</pre>
<pre style="margin: 0px;">    <span style="color: #2b91af;">PropertyInfo</span>[] propertyInfos = type.GetProperties(<span style="color: #2b91af;">BindingFlags</span>.Public | <span style="color: #2b91af;">BindingFlags</span>.NonPublic
                                                                          | <span style="color: #2b91af;">BindingFlags</span>.Instance);</pre>
<pre style="margin: 0px;">    propertyInfos[0].SetValue(obj, <span style="color: #a31515;">"Peter"</span>, <span style="color: blue;">null</span>);</pre>
<pre style="margin: 0px;">    propertyInfos[1].SetValue(obj, <span style="color: #a31515;">"Müller"</span>, <span style="color: blue;">null</span>);</pre>
<pre style="margin: 0px;">    propertyInfos[2].SetValue(obj, <span style="color: #a31515;">"myPassword"</span>, <span style="color: blue;">null</span>);</pre>
<pre style="margin: 0px;">    <span style="color: blue;">foreach</span> (<span style="color: blue;">var</span> info <span style="color: blue;">in</span> propertyInfos) {</pre>
<pre style="margin: 0px;">        <span style="color: #2b91af;">Console</span>.WriteLine(<span style="color: #a31515;">"    ++ {0} = {1}"</span>, info.Name, info.GetValue(obj, <span style="color: blue;">null</span>));</pre>
<pre style="margin: 0px;">    }</pre>
<pre style="margin: 0px;">}
<img class="aligncenter size-full wp-image-374" title="9" src="http://blog.aztec-project.org/wp-content/uploads/2009/06/9.png" alt="9" width="477" height="167" /></pre>
</div>
<p><strong> </strong></p>
<h2><span style="color: #ffffff;">.</span></h2>
<p><span style="color: #ffffff;">.<br />
</span></p>
<h2>Wozu braucht man jetzt aber nun die Reflection?</h2>
<p>Nun ja, die meisten Programme werden Reflection wohl nie benötigen oder verwenden. Es wird vorallem bei dem Entwickeln von Debuggern, Interpretern, TestTools, Logger oder auch für O/R-Mapper verwendet. Es wird also überall dort gebraucht, wo während der Laufzeit nicht klar ist, welche Assemblies verwendet werden und welche Informationen man aus diesen lesen oder manipulieren möchte.</p>
<h2><span style="color: #ffffff;">.</span></h2>
<h2>kurze Zusammenfassung:</h2>
<p>Wie man gesehen hat, ist der Aufbau einer Assembly mit ihren Typen hierarchisch. Um zb. an einen Parameter einer Methode eines Types zu kommen, braucht man zuerst das Assembly welches den Typ enthält. Von diesem lässt man sich ein Array von Typen geben. Von dem gesuchten Typ lässt man sich dann ein Array von Methoden geben. Von der gesuchten Methode holt man sich nun ein Array von allen Parametern. Dieses Array kann dann nach dem gewünschten Parameter durchsucht werden.</p>
<p>Es gibt natürlich für all diese Methoden auch Methoden, mit denen man sich den Type, die Methodeninformation, die Parameterinformation, usw. direkt mit der entsprechenden Bezeichnung holen kann. Ich wollte hier nur auf die Hierarchie aufmerksam machen.</p>
<p>Wie man in diesen Beispielen erkennen konnte, ist es möglich, ohne Probleme auf alle Informationen von einem Assembly zuzgreifen, sich die Types zu laden, dessen öffentliche und auch nicht-öffentliche Werte zu lesen und zu manipulieren und auch Methoden auszuführen. Man kann sich auch lokale Werte anzeigen lassen, in dem man sich den MethodBody des Objekte geben lässt, von denen man die lokalen Werte ermitteln möchte.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.aztec-project.org/2009/06/24/wozu-dient-reflection/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Anonyme Datentypen</title>
		<link>http://blog.aztec-project.org/2009/06/10/anonyme-datentypen/</link>
		<comments>http://blog.aztec-project.org/2009/06/10/anonyme-datentypen/#comments</comments>
		<pubDate>Wed, 10 Jun 2009 09:43:40 +0000</pubDate>
		<dc:creator>Andreas Seebauer</dc:creator>
				<category><![CDATA[How-To]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[HowTo]]></category>

		<guid isPermaLink="false">http://blog.aztec-project.org/?p=175</guid>
		<description><![CDATA[Anonyme Datentypen sind Klassen, die erst beim Kompilieren durch den Compiler definiert werden. Die Klassendefinition befindet sich also nicht im Quellcode. Die anonymen Datentypen leiten wie jedes andere Referenzobjekt von der Klasse object ab. Sie sind als reine Datenklassen gedacht und es können keine weiteren Methoden oder Events hinzugefügt werden. Obwohl der anonyme Datentyp auf [...]]]></description>
			<content:encoded><![CDATA[<p>Anonyme Datentypen sind Klassen, die erst beim Kompilieren durch den Compiler definiert werden. Die Klassendefinition befindet sich also nicht im Quellcode. Die anonymen Datentypen leiten wie jedes andere Referenzobjekt von der Klasse object ab. Sie sind als reine Datenklassen gedacht und es können keine weiteren Methoden oder Events hinzugefügt werden. Obwohl der anonyme Datentyp auf Quellcodeebene noch nicht definiert ist, muss dank Visual Studio nicht auf die Intellisense verzichtet werden.</p>
<p>Definiert und intstanziert werden sie mit new und einem Objektinitialisierer:</p>
<div style="background: white none repeat scroll 0% 0%; font-family: Courier New; font-size: 10pt; color: black; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;">
<pre style="margin: 0px;"><span style="color: blue;">    var</span> mitarbeiter = <span style="color: blue;">new</span> { Name = <span style="color: #a31515;">"Müller"</span>, Abteilung = <span style="color: #a31515;">"IT"</span> };</pre>
</div>
<p>var ist der implizite Typ und <strong>nicht </strong>der anonyme Datentyp. Er fungiert hier lediglich als container für die Instanz des anonymen Datentyps, die mit new {} erzeugt wird.</p>
<p>Gibt man keinen Namen für die Properties an, werden die Namen der Properties verwendet, mit denen initialisiert wird.</p>
<div style="background: white none repeat scroll 0% 0%; font-family: Courier New; font-size: 10pt; color: black; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;">
<pre style="margin: 0px;">    <span style="color: blue;">var</span> abteilung = <span style="color: blue;">new</span> { Abteilungsname = <span style="color: #a31515;">"IT"</span> };</pre>
<pre style="margin: 0px;">    <span style="color: blue;">var</span> mitarbeiter = <span style="color: blue;">new</span> { Name = <span style="color: #a31515;">"Müller"</span>, abteilung.Abteilungsname };</pre>
<pre style="margin: 0px;">    <span style="color: #2b91af;">Console</span>.WriteLine(mitarbeiter.Abteilungsname);</pre>
</div>
<p>Wenn man mit Werten initialisiert, muss ein Name angegeben werden.</p>
<p>Anonyme Datentypen bieten sich an, wenn man Abfragen mit Linq ausführt und entweder nur eine Teilmenge des ursprünglichen Objekts braucht, oder wenn man ein Objekt erweitern will, ohne extra eine neue Klasse zu definieren.</p>
<p>Hier ein Beispiel aus einem Castle Monorail Projekt, in dem eine erweiterte Liste an eine vm gegeben wird, ohne eine neue Klasse definieren zu müssen. Es soll dabei eine Liste erstellt werden, in der die Mitarbeiter mit ihrem Horoskop verknüpft werden :</p>
<div style="background: white none repeat scroll 0% 0%; font-family: Courier New; font-size: 10pt; color: black;">
<div style="background: white none repeat scroll 0% 0%; font-family: Courier New; font-size: 10pt; color: black;">
<pre style="margin: 0px;">    <span style="color: blue;">public</span> <span style="color: blue;">void</span> Action() {</pre>
<pre style="margin: 0px;">        <span style="color: #2b91af;">IList</span>&lt;<span style="color: #2b91af;">Mitarbeiter</span>&gt; mitarbeiterListe = m_service.GetMitarbeiter();</pre>
<pre style="margin: 0px;">        <span style="color: blue;">var</span> mitarbeiterMitHoroskopListe = (<span style="color: blue;">from</span> mitarbeiter <span style="color: blue;">in</span> mitarbeiterListe</pre>
<pre style="margin: 0px;">            <span style="color: blue;">select</span> <span style="color: blue;">new</span> { Mitarbeiter = mitarbeiter,</pre>
<pre style="margin: 0px;">                         Horoskop = GetHoroskop(mitarbeiter.Geburtsdatum) });</pre>
<pre style="margin: 0px;">        PropertyBag[<span style="color: #a31515;">"mitarbeiterMitHoroskopListe"</span>] = mitarbeiterMitHoroskopListe;</pre>
<pre style="margin: 0px;">    }</pre>
</div>
</div>
]]></content:encoded>
			<wfw:commentRss>http://blog.aztec-project.org/2009/06/10/anonyme-datentypen/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Dynamisches Laden von Assemblies</title>
		<link>http://blog.aztec-project.org/2009/06/05/dynamisches-laden-von-assemblies/</link>
		<comments>http://blog.aztec-project.org/2009/06/05/dynamisches-laden-von-assemblies/#comments</comments>
		<pubDate>Fri, 05 Jun 2009 19:57:46 +0000</pubDate>
		<dc:creator>Thomas Christian</dc:creator>
				<category><![CDATA[How-To]]></category>
		<category><![CDATA[Assembly]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[HowTo]]></category>
		<category><![CDATA[Reflection]]></category>

		<guid isPermaLink="false">http://blog.aztec-project.org/?p=50</guid>
		<description><![CDATA[In diesem Blog-Post möchte ich kurz erläutern, wie ich mit dem Problem des dynamischen Ladens von Assemblies umgegangen bin. Vor einiger Zeit stand ich vor dem Problem, dass ich zur Laufzeit Assemblies austauschen wollte. Grund dafür war, dass ich eine Host-Applikation hatte, die Plug-Ins verwendet. Jetzt wollte ich bestehende Plug-Ins während der Laufzeit austauschen oder [...]]]></description>
			<content:encoded><![CDATA[<p>In diesem Blog-Post möchte ich kurz erläutern, wie ich mit dem Problem des dynamischen Ladens von Assemblies umgegangen bin.</p>
<p>Vor einiger Zeit stand ich vor dem Problem, dass ich zur Laufzeit Assemblies austauschen wollte. Grund dafür war, dass ich eine Host-Applikation hatte, die Plug-Ins verwendet. Jetzt wollte ich bestehende Plug-Ins während der Laufzeit austauschen oder neue Plug-Ins hinzufügen ohne die Host-Applikation zu beenden. Dazu hatte ich ein Verzeichnis in dem sich, außer den Plug-Ins, alle Assemblies befanden. Die Plug-Ins selbst befanden sich in einem eigenen Unterverzeichnis. Selbst wenn die Plug-Ins von der Host-Applikation nicht mehr verwendet wurden, war es nicht möglich, diese Assemblies zu löschen.</p>
<p>Im Normalfall ist es so, dass sobald eine Assembly von einer Applikation verwendet wird, eine Referenz auf diese existiert. Diese Referenz wird leider erst gelöscht, wenn die ganze Applikation beendet wird.</p>
<p>Bei dem dynamischen Laden von Assemblies wird die zu ladende Assembly geöffnet, ausgelesen und dann geschlossen. Aus den ausgelesenen Bytes wird dann mittels Reflection eine Assembly im Arbeitsspeicher erzeugt. Auf die lokale Assembly hängt somit keine Referenz und es ist möglich diese zu löschen.</p>
<p>Meine Umsetzung sieht folgendermaßen aus:</p>
<div style="font-family: Courier New; font-size: 10pt; color: black; background: white;">
<pre style="margin: 0px;"><span style="color: #2b91af;">    2</span> <span style="color: blue;">public</span> IList&lt;Plugin&gt; GetPlugins(<span style="color: blue;">string</span> assemblyName) {</pre>
<pre style="margin: 0px;"><span style="color: #2b91af;">    3</span>     Assembly assembly;</pre>
<pre style="margin: 0px;"><span style="color: #2b91af;">    4</span>     IList&lt;Plugin&gt; pluginList = <span style="color: blue;">new</span> IList&lt;Plugin&gt;();</pre>
<pre style="margin: 0px;"><span style="color: #2b91af;">    5</span>     <span style="color: blue;">try</span> {</pre>
<pre style="margin: 0px;"><span style="color: #2b91af;">    6</span>         <span style="color: blue;">byte</span>[] byteAssembly = File.ReadAllBytes(assemblyName);</pre>
<pre style="margin: 0px;"><span style="color: #2b91af;">    7</span>         assembly = Assembly.Load(byteAssembly);</pre>
<pre style="margin: 0px;"><span style="color: #2b91af;">    8</span>     } <span style="color: blue;">catch</span> (Exception ex) {</pre>
<pre style="margin: 0px;"><span style="color: #2b91af;">    9</span>         log.Error(ex);</pre>
<pre style="margin: 0px;"><span style="color: #2b91af;">   10</span>     }</pre>
<pre style="margin: 0px;"><span style="color: #2b91af;">   11</span>     <span style="color: blue;">try</span> {</pre>
<pre style="margin: 0px;"><span style="color: #2b91af;">   12</span>         <span style="color: blue;">if</span> (assembly != <span style="color: blue;">null</span>) {</pre>
<pre style="margin: 0px;"><span style="color: #2b91af;">   13</span>             Type[] assemblyTypes = assembly.GetTypes();</pre>
<pre style="margin: 0px;"><span style="color: #2b91af;">   14</span>             <span style="color: blue;">foreach</span> (Type assemblyTyp <span style="color: blue;">in</span> assemblyTypes) {</pre>
<pre style="margin: 0px;"><span style="color: #2b91af;">   15</span>                 <span style="color: blue;">if</span> (<span style="color: blue;">typeof</span>(Plugin).IsAssignableFrom(assemblyTyp)) {</pre>
<pre style="margin: 0px;"><span style="color: #2b91af;">   16</span>                     plugin = (Plugin)assembly.CreateInstance(assemblyTyp</pre>
<pre style="margin: 0px;"><span style="color: #2b91af;">   17</span>                                                                 .FullName);</pre>
<pre style="margin: 0px;"><span style="color: #2b91af;">   18</span>                     <span style="color: blue;">if</span> (plugin != <span style="color: blue;">null</span>) {</pre>
<pre style="margin: 0px;"><span style="color: #2b91af;">   19</span>                         pluginList.Add(plugin);</pre>
<pre style="margin: 0px;"><span style="color: #2b91af;">   20</span>                     }</pre>
<pre style="margin: 0px;"><span style="color: #2b91af;">   21</span>                 }</pre>
<pre style="margin: 0px;"><span style="color: #2b91af;">   22</span>             }</pre>
<pre style="margin: 0px;"><span style="color: #2b91af;">   23</span>         }</pre>
<pre style="margin: 0px;"><span style="color: #2b91af;">   24</span>     } <span style="color: blue;">catch</span> (ReflectionTypeLoadException ex) {</pre>
<pre style="margin: 0px;"><span style="color: #2b91af;">   25</span>         log.Error(ex);</pre>
<pre style="margin: 0px;"><span style="color: #2b91af;">   26</span>     }</pre>
<pre style="margin: 0px;"><span style="color: #2b91af;">   27</span>     <span style="color: blue;">return</span> pluginList;</pre>
<pre style="margin: 0px;"><span style="color: #2b91af;">   28</span> }</pre>
</div>
]]></content:encoded>
			<wfw:commentRss>http://blog.aztec-project.org/2009/06/05/dynamisches-laden-von-assemblies/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Umsetzung des Plug-In-Patterns</title>
		<link>http://blog.aztec-project.org/2009/06/05/umsetzung-des-plug-in-patterns/</link>
		<comments>http://blog.aztec-project.org/2009/06/05/umsetzung-des-plug-in-patterns/#comments</comments>
		<pubDate>Fri, 05 Jun 2009 19:45:57 +0000</pubDate>
		<dc:creator>Thomas Christian</dc:creator>
				<category><![CDATA[How-To]]></category>
		<category><![CDATA[Architektur]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[HowTo]]></category>
		<category><![CDATA[Plug-In]]></category>

		<guid isPermaLink="false">http://blog.aztec-project.org/?p=5</guid>
		<description><![CDATA[In meinem ersten Blog-Post möchte ich euch in vereinfachter Form meine Umsetzung des Plug-In-Patterns vorstellen. Voraussetzungen für dieses Pattern sind: eine Host-Applikation die das Plug-In laden möchte ein Plug-In welches es zu laden gilt und die Schnittstellen Plugin und IHost Zu allererst brauchen wir eine gemeinsame Schnittstelle, die sowohl vom Plug-In als auch vom Host [...]]]></description>
			<content:encoded><![CDATA[<p>In meinem ersten Blog-Post möchte ich euch in vereinfachter Form meine Umsetzung des Plug-In-Patterns vorstellen.<br />
Voraussetzungen für dieses Pattern sind:</p>
<ul>
<li> eine Host-Applikation die das Plug-In laden möchte</li>
<li> ein Plug-In welches es zu laden gilt</li>
<li> und die Schnittstellen Plugin und IHost</li>
</ul>
<p>Zu allererst brauchen wir eine gemeinsame Schnittstelle, die sowohl vom Plug-In als auch vom Host (die Applikation welche das Plug-In verwenden soll) benutzt werden soll. Über diese Schnittstelle kommuniziert der Host mit dem Plug-In.<br />
Es würde sich das Interface IPlugIn anbieten. In meinem Fall verwende ich allerdings kein Interface sondern eine abstrakte Klasse, da ich bereits Logik direkt in die Schnittstelle implementieren möchte. In meinem Fall heißt die abstrakte Klasse einfach nur Plugin. Im weiteren Verlauf werde ich zu meiner abstrakten Klasse Schnittstelle sagen.</p>
<div style="font-family: Courier New; font-size: 10pt; color: black; background: white;">
<pre style="margin: 0px;"><span style="color: #2b91af;">    1</span> <span style="color: blue;">public</span> <span style="color: blue;">abstract</span> <span style="color: blue;">class</span> <span style="color: #2b91af;">Plugin</span> {</pre>
<pre style="margin: 0px;"><span style="color: #2b91af;">    2</span>     <span style="color: blue;">private</span> IHost m_host;</pre>
<pre style="margin: 0px;"><span style="color: #2b91af;">    3</span>     <span style="color: blue;">public</span> Plugin(<span style="color: blue;">string</span> name) {</pre>
<pre style="margin: 0px;"><span style="color: #2b91af;">    4</span>         Name = name;</pre>
<pre style="margin: 0px;"><span style="color: #2b91af;">    5</span>     }</pre>
<pre style="margin: 0px;"><span style="color: #2b91af;">    6</span></pre>
<pre style="margin: 0px;"><span style="color: #2b91af;">    7</span>     <span style="color: blue;">public</span> <span style="color: blue;">string</span> Name { <span style="color: blue;">get</span>; <span style="color: blue;">set</span>; }</pre>
<pre style="margin: 0px;"><span style="color: #2b91af;">    8</span>     <span style="color: blue;">public</span> <span style="color: blue;">string</span> Author { <span style="color: blue;">get</span>; <span style="color: blue;">set</span>; }</pre>
<pre style="margin: 0px;"><span style="color: #2b91af;">    9</span>     <span style="color: blue;">public</span> <span style="color: blue;">string</span> Version { <span style="color: blue;">get</span>; <span style="color: blue;">set</span>; }</pre>
<pre style="margin: 0px;"><span style="color: #2b91af;">   10</span>     <span style="color: blue;">public</span> <span style="color: blue;">bool</span> IsRegistered { <span style="color: blue;">get</span>; <span style="color: blue;">private</span> <span style="color: blue;">set</span>; }</pre>
<pre style="margin: 0px;"><span style="color: #2b91af;">   11</span></pre>
<pre style="margin: 0px;"><span style="color: #2b91af;">   12</span>     <span style="color: gray;">///</span><span style="color: green;"> </span><span style="color: gray;">&lt;summary&gt;</span></pre>
<pre style="margin: 0px;"><span style="color: #2b91af;">   13</span>     <span style="color: gray;">///</span><span style="color: green;"> Setzt oder gibt die Host-Application.</span></pre>
<pre style="margin: 0px;"><span style="color: #2b91af;">   14</span>     <span style="color: gray;">///</span><span style="color: green;"> </span><span style="color: gray;">&lt;/summary&gt;</span></pre>
<pre style="margin: 0px;"><span style="color: #2b91af;">   15</span>     <span style="color: gray;">///</span><span style="color: green;"> </span><span style="color: gray;">&lt;value&gt;</span><span style="color: green;">Host-Application.</span><span style="color: gray;">&lt;/value&gt;</span></pre>
<pre style="margin: 0px;"><span style="color: #2b91af;">   16</span>     <span style="color: blue;">public</span> IHost Host {</pre>
<pre style="margin: 0px;"><span style="color: #2b91af;">   17</span>         <span style="color: blue;">get</span> { <span style="color: blue;">return</span> m_host; }</pre>
<pre style="margin: 0px;"><span style="color: #2b91af;">   18</span>         <span style="color: blue;">set</span> {</pre>
<pre style="margin: 0px;"><span style="color: #2b91af;">   19</span>             <span style="color: blue;">if</span> (<span style="color: blue;">value</span> != <span style="color: blue;">null</span>) {</pre>
<pre style="margin: 0px;"><span style="color: #2b91af;">   20</span>                 <span style="color: blue;">if</span> (m_host == <span style="color: blue;">null</span>) {</pre>
<pre style="margin: 0px;"><span style="color: #2b91af;">   21</span>                     m_host = <span style="color: blue;">value</span>;</pre>
<pre style="margin: 0px;"><span style="color: #2b91af;">   22</span>                     <span style="color: blue;">if</span> (m_host.Register(<span style="color: blue;">this</span>)) {</pre>
<pre style="margin: 0px;"><span style="color: #2b91af;">   23</span>                         IsRegistered = <span style="color: blue;">true</span>;</pre>
<pre style="margin: 0px;"><span style="color: #2b91af;">   24</span>                     }</pre>
<pre style="margin: 0px;"><span style="color: #2b91af;">   25</span>                 }</pre>
<pre style="margin: 0px;"><span style="color: #2b91af;">   26</span>             } <span style="color: blue;">else</span> {</pre>
<pre style="margin: 0px;"><span style="color: #2b91af;">   27</span>                 <span style="color: blue;">if</span> (m_host.Unregister(<span style="color: blue;">this</span>)) {</pre>
<pre style="margin: 0px;"><span style="color: #2b91af;">   28</span>                     m_host = <span style="color: blue;">value</span>;</pre>
<pre style="margin: 0px;"><span style="color: #2b91af;">   29</span>                     IsRegistered = <span style="color: blue;">false</span>;</pre>
<pre style="margin: 0px;"><span style="color: #2b91af;">   30</span>                 }</pre>
<pre style="margin: 0px;"><span style="color: #2b91af;">   31</span>             }</pre>
<pre style="margin: 0px;"><span style="color: #2b91af;">   32</span>         }</pre>
<pre style="margin: 0px;"><span style="color: #2b91af;">   33</span>     }</pre>
<pre style="margin: 0px;"><span style="color: #2b91af;">   34</span> }</pre>
</div>
<p>Ich glaube, der Aufbau der Schnittstelle Plugin sollte bis auf die Property “Host” klar sein. Wie man sieht, benötigt man bei diesem Pattern zusätzlich zur Schnittstelle Plugin noch das IHost-Interface.<br />
Dieses Interface ist direkter Bestandteil der Schnittstelle Plugin. Nun kann man sich natürlich die Frage stellen, warum das Plug-In den Host kennen muss und somit von diesem abhängig ist.</p>
<p>Zum einen ist es in der Regel so, dass ein Plug-In für nur einen Host entwickelt wird und zum anderen wollte ich dem Host gewisse Richtlinien zum Registrieren und Lösen des Plug-Ins vorgeben.</p>
<p>Das Interface IHost sieht folgendermaßen aus:</p>
<div style="font-family: Courier New; font-size: 10pt; color: black; background: white;">
<pre style="margin: 0px;"><span style="color: #2b91af;">    1</span> <span style="color: blue;">public</span> <span style="color: blue;">interface</span> <span style="color: #2b91af;">IHost</span> {</pre>
<pre style="margin: 0px;"><span style="color: #2b91af;">    2</span>     <span style="color: blue;">bool</span> Register(Plugin plugin);</pre>
<pre style="margin: 0px;"><span style="color: #2b91af;">    3</span>     <span style="color: blue;">bool</span> Unregister(Plugin plugin);</pre>
<pre style="margin: 0px;"><span style="color: #2b91af;">    4</span> }</pre>
</div>
<p>Dieses Interface muss von der Host-Applikation implementiert werden, damit sich das Plug-In am Host registrieren kann. Im letzten Satz habe ich es schon angedeutet. Nicht der Host registriert das Plug-In bei sich, sondern das Plug-In registriert sich am Host. Durch das setzen der Property Plugin.Host wird die Methode Register oder Unregister vom Plug-In aufgerufen, welche der Host implementiert.</p>
<p>Eine vereinfachte Darstellung der Implementierung des IHost -Interfaces sieht folgendermaßen aus:</p>
<div style="font-family: Courier New; font-size: 10pt; color: black; background: white;">
<pre style="margin: 0px;"><span style="color: #2b91af;">    1</span> <span style="color: blue;">public</span> <span style="color: blue;">class</span> <span style="color: #2b91af;">HostApplication</span> : IHost {</pre>
<pre style="margin: 0px;"><span style="color: #2b91af;">    2</span>     <span style="color: blue;">private</span> List&lt;Plugin&gt; m_pluginList;</pre>
<pre style="margin: 0px;"><span style="color: #2b91af;">    3</span></pre>
<pre style="margin: 0px;"><span style="color: #2b91af;">    4</span>     <span style="color: green;">//Konstruktor</span></pre>
<pre style="margin: 0px;"><span style="color: #2b91af;">    5</span>     <span style="color: blue;">public</span> HostApplication() {</pre>
<pre style="margin: 0px;"><span style="color: #2b91af;">    6</span>         m_pluginList = <span style="color: blue;">new</span> List&lt;Plugin&gt;();</pre>
<pre style="margin: 0px;"><span style="color: #2b91af;">    7</span></pre>
<pre style="margin: 0px;"><span style="color: #2b91af;">    8</span>         <span style="color: green;">//Lädt alle verfügbaren Plug-Ins zb. aus einem Verzeichnis</span></pre>
<pre style="margin: 0px;"><span style="color: #2b91af;">    9</span>         List&lt;Plugin&gt; plugins = GetPlugins();</pre>
<pre style="margin: 0px;"><span style="color: #2b91af;">   10</span>         <span style="color: blue;">foreach</span> (Plugin plugin <span style="color: blue;">in</span> plugins) {</pre>
<pre style="margin: 0px;"><span style="color: #2b91af;">   11</span>             <span style="color: green;">//ruft implizit die IHost.Register-Methode auf</span></pre>
<pre style="margin: 0px;"><span style="color: #2b91af;">   12</span>             plugin.Host = <span style="color: blue;">this</span>;</pre>
<pre style="margin: 0px;"><span style="color: #2b91af;">   13</span>         }</pre>
<pre style="margin: 0px;"><span style="color: #2b91af;">   14</span>     }</pre>
<pre style="margin: 0px;"><span style="color: #2b91af;">   15</span></pre>
<pre style="margin: 0px;"><span style="color: #2b91af;">   16</span>     <span style="color: blue;">public</span> <span style="color: blue;">void</span> ShowPlugins() {</pre>
<pre style="margin: 0px;"><span style="color: #2b91af;">   17</span>         <span style="color: blue;">foreach</span> (Plugin plugin <span style="color: blue;">in</span> m_pluginList) {</pre>
<pre style="margin: 0px;"><span style="color: #2b91af;">   18</span>             <span style="color: green;">//Ausgabe der Namen aller am Host registrierten Plug-Ins</span></pre>
<pre style="margin: 0px;"><span style="color: #2b91af;">   19</span>             Console.WriteLine(plugin.Name);</pre>
<pre style="margin: 0px;"><span style="color: #2b91af;">   20</span>         }</pre>
<pre style="margin: 0px;"><span style="color: #2b91af;">   21</span>     }</pre>
<pre style="margin: 0px;"><span style="color: #2b91af;">   22</span></pre>
<pre style="margin: 0px;"><span style="color: #2b91af;">   23</span>     <span style="color: blue;">public</span> <span style="color: blue;">void</span> UnloadPlugins() {</pre>
<pre style="margin: 0px;"><span style="color: #2b91af;">   24</span>         <span style="color: blue;">foreach</span> (Plugin plugin <span style="color: blue;">in</span> m_pluginList) {</pre>
<pre style="margin: 0px;"><span style="color: #2b91af;">   25</span>             <span style="color: green;">//ruft implizit die IHost.Unregister-Methode auf</span></pre>
<pre style="margin: 0px;"><span style="color: #2b91af;">   26</span>             plugin.Host = <span style="color: blue;">null</span>;</pre>
<pre style="margin: 0px;"><span style="color: #2b91af;">   27</span>         }</pre>
<pre style="margin: 0px;"><span style="color: #2b91af;">   28</span>     }</pre>
<pre style="margin: 0px;"><span style="color: #2b91af;">   29</span></pre>
<pre style="margin: 0px;"><span style="color: #2b91af;">   30</span> <span style="color: blue;">    #region</span> IHost-Implementierung</pre>
<pre style="margin: 0px;"><span style="color: #2b91af;">   31</span>     <span style="color: blue;">public</span> <span style="color: blue;">bool</span> Register(Plugin plugin) {</pre>
<pre style="margin: 0px;"><span style="color: #2b91af;">   32</span>         <span style="color: blue;">if</span> (!m_pluginList.Contains(plugin)) {</pre>
<pre style="margin: 0px;"><span style="color: #2b91af;">   33</span>             m_pluginList.Add(plugin);</pre>
<pre style="margin: 0px;"><span style="color: #2b91af;">   34</span>             <span style="color: blue;">return</span> <span style="color: blue;">true</span>;</pre>
<pre style="margin: 0px;"><span style="color: #2b91af;">   35</span>         }</pre>
<pre style="margin: 0px;"><span style="color: #2b91af;">   36</span>         <span style="color: blue;">return</span> <span style="color: blue;">false</span>;</pre>
<pre style="margin: 0px;"><span style="color: #2b91af;">   37</span>     }</pre>
<pre style="margin: 0px;"><span style="color: #2b91af;">   38</span></pre>
<pre style="margin: 0px;"><span style="color: #2b91af;">   39</span>     <span style="color: blue;">public</span> <span style="color: blue;">bool</span> Unregister(Plugin plugin) {</pre>
<pre style="margin: 0px;"><span style="color: #2b91af;">   40</span>         <span style="color: blue;">if</span> (m_pluginList.Contains(plugin)) {</pre>
<pre style="margin: 0px;"><span style="color: #2b91af;">   41</span>             m_pluginList.Remove(plugin);</pre>
<pre style="margin: 0px;"><span style="color: #2b91af;">   42</span>             <span style="color: blue;">return</span> <span style="color: blue;">true</span>;</pre>
<pre style="margin: 0px;"><span style="color: #2b91af;">   43</span>         }</pre>
<pre style="margin: 0px;"><span style="color: #2b91af;">   44</span>         <span style="color: blue;">return</span> <span style="color: blue;">false</span>;</pre>
<pre style="margin: 0px;"><span style="color: #2b91af;">   45</span>     }</pre>
<pre style="margin: 0px;"><span style="color: #2b91af;">   46</span> <span style="color: blue;">    #endregion</span></pre>
<pre style="margin: 0px;"><span style="color: #2b91af;">   47</span> }</pre>
</div>
<p>Das Registrieren und Lösen der Plug-Ins könnte man nun noch in einen Plug-In-Manager auslagern, worauf ich in diesem Blog allerdings verzichten möchte.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.aztec-project.org/2009/06/05/umsetzung-des-plug-in-patterns/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
