<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss 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/" xmlns:media="http://search.yahoo.com/mrss/" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">

<channel>
	<title>Codingly</title>
	
	<link>http://codingly.com</link>
	<description>Par Romain Verdier</description>
	<lastBuildDate>Thu, 25 Jun 2009 08:54:57 +0000</lastBuildDate>
	<generator>http://wordpress.com/</generator>
	<language>fr</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<image>
		<url>http://www.gravatar.com/blavatar/62c090a2ec42be744d871177bd874854?s=96&amp;d=http://s.wordpress.com/i/buttonw-com.png</url>
		<title>Codingly</title>
		<link>http://codingly.com</link>
	</image>
			<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" href="http://feeds.feedburner.com/Codingly" type="application/rss+xml" /><feedburner:emailServiceId>Codingly</feedburner:emailServiceId><feedburner:feedburnerHostname>http://feedburner.google.com</feedburner:feedburnerHostname><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com" /><item>
		<title>ALT.NET en France : Présentation AOP, c’est fait.</title>
		<link>http://feedproxy.google.com/~r/Codingly/~3/AAB-CmKBJwU/</link>
		<comments>http://codingly.com/2009/06/18/alt-net-en-france-presentation-aop-cest-fait/#comments</comments>
		<pubDate>Thu, 18 Jun 2009 08:09:28 +0000</pubDate>
		<dc:creator>Romain Verdier</dc:creator>
				<category><![CDATA[Posts]]></category>
		<category><![CDATA[.NET]]></category>
		<category><![CDATA[ALT.NET]]></category>
		<category><![CDATA[AOP]]></category>

		<guid isPermaLink="false">http://codingly.com/?p=716</guid>
		<description><![CDATA[Je me demande si 91 slides valent 1000 mots. Vous pourrez essayer de vous faire une idée puisqu&#8217;elles sont disponibles ci-dessous. Je vous conseille de carrément télécharger la présentation si vous êtes intéressés par les animations, puisque certaines (lire : toutes) sont très logiquement tuées par SlideShare.
Bon, pour ma part j&#8217;ai trouvé que ça s&#8217;était [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=codingly.com&blog=3510695&post=716&subd=romainverdier&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p>Je me demande si 91 slides valent 1000 mots. Vous pourrez essayer de vous faire une idée puisqu&#8217;elles sont disponibles ci-dessous. Je vous conseille de carrément télécharger la présentation si vous êtes intéressés par les animations, puisque certaines (lire : toutes) sont très logiquement tuées par SlideShare.</p>
<p>Bon, pour ma part j&#8217;ai trouvé que ça s&#8217;était plutôt bien passé considérant que je ne suis pas un speaker &#8211; au mieux un <a href="http://codingly.com/2008/12/29/degage-sale-programmeur/">sale programmeur</a> &#8211; même si j&#8217;imaginais une présentation un peu plus courte. J&#8217;ai parlé pendant 45 min, je crois, puis j&#8217;ai ouvert VS pour la &#8220;démo interactive&#8221; qui s&#8217;est un peu éternisée.</p>
<p>Je tiens encore à remercier <a href="http://fastconnect.fr/">FastConnect</a> pour la salle, l&#8217;organisation, le buffet, etc.<br />
<span id="more-716"></span><br />
<object type='application/x-shockwave-flash' wmode='transparent' data='http://static.slideshare.net/swf/ssplayer2.swf?id=1601593&#038;doc=aop-net-090618014706-phpapp01' width='720' height='590'><param name='movie' value='http://static.slideshare.net/swf/ssplayer2.swf?id=1601593&#038;doc=aop-net-090618014706-phpapp01' /><param name='allowFullScreen' value='true' /><param name='allowScriptAccess' value='always' /></object></p>
<p>En ce qui concerne le code des exemples, j&#8217;essaierai d&#8217;éditer ce post ultérieurement.</p>
<p><span class="edittag">Edit</span> Quelques liens en rapport :</p>
<ul>
<li><a href="http://codingly.com/2008/10/29/utiliser-laop-avec-postsharp-pour-implementer-inotifypropertychanged/">INotifyPropertyChanged avec PostSharp</a></li>
<li><a href="http://codingly.com/2008/11/10/introduction-a-monocecil-implementer-inotifypropertychanged/">INotifyPropertyChanged avec Mono.Cecil</a></li>
</ul>
<p><span class="edittag">Edit</span> Le <a href="http://www.altnetfr.org/2009/06/24/altnet-paris-14-compte-rendu-aop/">compte rendu de la soirée</a> est maintenant dispo sur le site ALT.NET Fr. Merci <a href="http://evain.net/blog/">Jb</a>.</p>
<p>N&#8217;hésitez pas à me faire part de vos critiques <em>positives</em>, puisque les autres, constructives ou pas, elles vexent. OK ?</p>
Posted in Posts Tagged: .NET, ALT.NET, AOP <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/romainverdier.wordpress.com/716/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/romainverdier.wordpress.com/716/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/romainverdier.wordpress.com/716/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/romainverdier.wordpress.com/716/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/romainverdier.wordpress.com/716/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/romainverdier.wordpress.com/716/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/romainverdier.wordpress.com/716/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/romainverdier.wordpress.com/716/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/romainverdier.wordpress.com/716/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/romainverdier.wordpress.com/716/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=codingly.com&blog=3510695&post=716&subd=romainverdier&ref=&feed=1" /></div><img src="http://feeds.feedburner.com/~r/Codingly/~4/AAB-CmKBJwU" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://codingly.com/2009/06/18/alt-net-en-france-presentation-aop-cest-fait/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/cb0ee4bde49708f4be24a02a5d59e52e?s=96&amp;d=http%3A%2F%2F0.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96" medium="image">
			<media:title type="html">Romain</media:title>
		</media:content>
	<feedburner:origLink>http://codingly.com/2009/06/18/alt-net-en-france-presentation-aop-cest-fait/</feedburner:origLink></item>
		<item>
		<title>ALT.NET en France : Présentation AOP à Paris le 17 juin</title>
		<link>http://feedproxy.google.com/~r/Codingly/~3/nYSO8FiGIR8/</link>
		<comments>http://codingly.com/2009/06/02/alt-net-en-france-presentation-aop-a-paris-le-17-juin/#comments</comments>
		<pubDate>Tue, 02 Jun 2009 21:18:28 +0000</pubDate>
		<dc:creator>Romain Verdier</dc:creator>
				<category><![CDATA[Posts]]></category>
		<category><![CDATA[.NET]]></category>
		<category><![CDATA[ALT.NET]]></category>
		<category><![CDATA[Annonce]]></category>
		<category><![CDATA[AOP]]></category>

		<guid isPermaLink="false">http://codingly.com/?p=655</guid>
		<description><![CDATA[Avant toute chose : Non, je ne chercherai pas à justifier le rythme misérable de mes publications sur ce blog. Et non, je ne m&#8217;excuserai pas de tricher lamentablement en postant aujourd&#8217;hui quelque chose d&#8217;aussi, heu, bref.
Je voulais vous informer, ou plus probablement vous rappeler, que j&#8217;allais commettre une présentation sur l&#8217;AOP, le 17 juin, [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=codingly.com&blog=3510695&post=655&subd=romainverdier&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p>Avant toute chose : Non, je ne chercherai pas à justifier le rythme misérable de mes publications sur ce blog. Et non, je ne m&#8217;excuserai pas de tricher lamentablement en postant aujourd&#8217;hui quelque chose d&#8217;aussi, heu, bref.</p>
<p>Je voulais vous informer, ou plus probablement vous rappeler, que j&#8217;allais commettre une présentation sur l&#8217;<a href="http://en.wikipedia.org/wiki/Aspect-oriented_programming">AOP</a>, le 17 juin, à l&#8217;occasion de la 14ème rencontre ALT.NET Parisienne. Vous trouverez les détails pratiques <a href="http://www.altnetfr.org/2009/05/28/altnet-paris-14-aspect-oriented-programming-aop/">sur notre joli site</a>. Merci à <a href="http://www.fastconnect.fr">FastConnect</a> qui sponsorise l&#8217;évènement.<br />
<span id="more-655"></span><br />
Il va sans dire que je serais plus à l&#8217;aise s&#8217;il n&#8217;y avait que 3 personnes qui jugeaient bon de se déplacer. Pourtant, je vais m&#8217;asseoir sur cette considération et vous inviter à venir nombreux. Plusieurs fois au cours des rencontres précédentes nous avons abordé la question de la programmation orientée aspect lors des discussions libres, et il semblerait donc que le sujet rende curieux, à défaut de préoccuper. Peut-être mérite-t-il que nous lui fassions plus de place le temps d&#8217;une soirée. Je ne sais pas encore exactement quel sera l&#8217;agenda, mais l&#8217;idée est de présenter l&#8217;AOP en tant que concept, de le confronter gentiment aux paradigmes traditionnels, avant de passer plus concrètement à l&#8217;étude des différentes techniques et outils qui existent en .NET.</p>
<p>D&#8217;aucuns pourraient penser que le sujet n&#8217;est pas spécialement ALT.NET.</p>
<p>Ce à quoi je répondrais :</p>
<blockquote><p>Certes, certes&#8230;</p></blockquote>
<p>Enfin. Si on compte uniquement sur Microsoft pour profiter de l&#8217;AOP on risque assez rapidement de se sentir à l&#8217;étroit. Il est possible de faire de l&#8217;AOP sans sortir de la BCL, oui, et il est possible de faire de l&#8217;AOP <em>un peu plus facilement</em> en débordant sur <a href="http://stackoverflow.com/questions/833729/built-in-aop-in-c-is-it-on-the-way/833919#833919">EntLib</a>. Cependant, les solutions les plus matures et les plus riches pour faire de l&#8217;AOP en .NET ne sont pas forcément estampillées Microsoft, ce qui risque de conduire l&#8217;utilisateur averti vers des frameworks plus spécialisés, open-source ou pas. Je veux parler de Castle.DynamicProxy, PostSharp, Linfu, Mono.Cecil, Spring.NET, etc.</p>
<p>Moi, je trouve que ça sent ALT.NET.</p>
<p>Bref, j&#8217;espère que cette rencontre verra naitre un débat et que nous pourrons collecter quelques retours d&#8217;expériences, comparer nos approches, bailler, etc. Encore une fois, toutes les infos sont disponibles sur le site <a href="http://www.altnetfr.org/">altnetfr</a>, à <a href="http://www.altnetfr.org/2009/05/28/altnet-paris-14-aspect-oriented-programming-aop/">cette adresse</a>.</p>
<p>Pensez à <a href="http://www.doodle.com/nd4f57ugtsddqk36">vous inscrire</a>, et n&#8217;hésitez pas à faire passer l&#8217;info.</p>
Posted in Posts Tagged: .NET, ALT.NET, Annonce, AOP <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/romainverdier.wordpress.com/655/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/romainverdier.wordpress.com/655/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/romainverdier.wordpress.com/655/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/romainverdier.wordpress.com/655/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/romainverdier.wordpress.com/655/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/romainverdier.wordpress.com/655/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/romainverdier.wordpress.com/655/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/romainverdier.wordpress.com/655/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/romainverdier.wordpress.com/655/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/romainverdier.wordpress.com/655/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=codingly.com&blog=3510695&post=655&subd=romainverdier&ref=&feed=1" /></div><img src="http://feeds.feedburner.com/~r/Codingly/~4/nYSO8FiGIR8" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://codingly.com/2009/06/02/alt-net-en-france-presentation-aop-a-paris-le-17-juin/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/cb0ee4bde49708f4be24a02a5d59e52e?s=96&amp;d=http%3A%2F%2F0.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96" medium="image">
			<media:title type="html">Romain</media:title>
		</media:content>
	<feedburner:origLink>http://codingly.com/2009/06/02/alt-net-en-france-presentation-aop-a-paris-le-17-juin/</feedburner:origLink></item>
		<item>
		<title>Petit rappel sur le Disposing Pattern en C#</title>
		<link>http://feedproxy.google.com/~r/Codingly/~3/zMx02ykcfH8/</link>
		<comments>http://codingly.com/2009/04/01/petit-rappel-sur-le-disposing-pattern-en-c/#comments</comments>
		<pubDate>Wed, 01 Apr 2009 09:02:14 +0000</pubDate>
		<dc:creator>Romain Verdier</dc:creator>
				<category><![CDATA[Posts]]></category>
		<category><![CDATA[.NET]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[WTF]]></category>

		<guid isPermaLink="false">http://codingly.com/?p=641</guid>
		<description><![CDATA[Ca fait longtemps que je veux faire ce post, au sujet d&#8217;une question trop souvent négligée : le disposing pattern. On peut voir ça comme un petit rappel, ou un post à classer dans la catégorie &#8220;back to basics&#8221;. En deux mots, il s&#8217;agit de gérer correctement la libération des ressources non-managées, dans un programme [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=codingly.com&blog=3510695&post=641&subd=romainverdier&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p>Ca fait longtemps que je veux faire ce post, au sujet d&#8217;une question trop souvent négligée : le <em>disposing pattern</em>. On peut voir ça comme un petit rappel, ou un post à classer dans la catégorie &#8220;back to basics&#8221;. En deux mots, il s&#8217;agit de gérer correctement la libération des ressources non-managées, dans un programme managé.</p>
<blockquote><p><strong>EDIT </strong>: Ce post est un poisson d&#8217;avril, évidemment. Il vaudrait mieux ne pas utiliser l&#8217;implémentation du disposing pattern proposée&#8230;</p></blockquote>
<p><span id="more-641"></span></p>
<h3>Quelques rappels</h3>
<p>On parle de code managé en .NET car on fait implicitement référence au garbage collector qui <em>gère automatiquement la mémoire</em>. Il n&#8217;est pas question de faire un cours sur le GC, mais retenez juste qu&#8217;il est très intelligent, et qu&#8217;il est <em>indépendant</em>. Tellement indépendant qu&#8217;on ne peut pas prévoir quand est-ce qu&#8217;il va réellement effectuer son recyclage. Par exemple, lorsque vous écrivez :</p>
<pre name="code" class="csharp">

public int Add(int a, int b)
{
    Calculator calculator = new Calculator();
    return calculator.Add(a, b);
};
</pre>
<p>Vous créez une nouvelle instance de <code>Calculator</code> qui sera référencée par la variable locale <code>calculator</code>. A la sortie de la méthode, la variable locale n&#8217;existe plus, et l&#8217;instance de <code>Calculator</code> n&#8217;est donc plus référencée. L&#8217;espace mémoire qu&#8217;elle occupe peut être récupéré, et le GC le sait. (Notez l&#8217;assonance.) Il y a un instant j&#8217;insistais sur l&#8217;indépendance du garbage collector : s&#8217;il sait qu&#8217;il peut libérer une instance, <strong>vous ne savez pas quand il le fera</strong>.</p>
<p>On considère que la collecte des miettes est indéterministe. Vous n&#8217;avez aucun moyen de savoir précisément quand le calculator que vous avez instancié précédemment sera collecté. Ca ne sera pas forcément à la sortie de la méthode, comme on pourrait naïvement s&#8217;y attendre ; ça peut être 47 ms ou 47 secondes après (pour caricaturer) et vous devriez même être heureux de ne pas avoir à vous en soucier.</p>
<p>Mais.</p>
<p>Tout n&#8217;est pas managé. Parfois, vous utilisez à partir d&#8217;objets managés des ressources non managées. Même si ça peut paraitre évident, il est bon de revenir là dessus. On parle de &#8220;ressource non managée&#8221; dans ce contexte pour décrire une ressource :</p>
<ul>
<li>Dont l&#8217;allocation est déclenchée à partir de votre code managé.</li>
<li>Qui doit être libérée.</li>
<li>Mais dont le garbage collector n&#8217;est pas responsable.</li>
</ul>
<p>Les handles de fichiers, les connexions de bases de données, les sockets réseau ou les références COM sont des exemples de ressources non managées.</p>
<h3>Comment implémenter le disposing pattern</h3>
<p>On se base sur l&#8217;interface <code>IDisposable</code>, et sur les destructeurs de C#. <code>IDisposable</code> expose une méthode <code>Dispose</code>, qui va détruire l&#8217;objet, et faire en sorte que sa mémoire soit désallouée du heap (et non pas de la pile comme je le vois souvent dans des blogs), surtout si on fait bien appel au mot clé <code>using</code> qui ne sert pas qu&#8217;à importer des namespaces.</p>
<p>Mais assez de théorie, passons au code. Imaginons la classe C# suivante, et regardons comment elle fait pour libérer le <code>IntPtr</code> qu&#8217;elle a en variable publique et qui constitue sa variable non managée dangereuse (attention aux memory leaks lol) :</p>
<blockquote><p><strong>EDIT </strong>: Ce post est un poisson d&#8217;avril, évidemment. Il vaudrait mieux ne pas utiliser l&#8217;implémentation du disposing pattern proposée&#8230;</p></blockquote>
<pre name="code" class="csharp">

public class MaClasseManagée : IDisposable // on implémente IDisposable
{
    private IntPtr m_Ressource_non_managée; // Attention !
	bool disposed = false; // pour savoir si la classe est libérée  

    public MaClasseManagée(IntPtr ptrnonmanagé)
    {
		if(ptrnonmanagé != null)
		{
			m_Ressource_non_managée = ptrnonmanagé; // allocation mémoire non managée
		}
		else // sinon
		{
			if (ptr.Equals(IntPtr.Zero) == true)
            {
                // on désalloue directement la mémoire du pointeur
				m_Ressource_non_managée = IntPtr.Zero
            }
			GC.CancelFullGCNotification(); // pas obligé, mais il vaut mieux
		}
    }

	public void FaireQuelqueChose()
	{
		// ici on utilise la ressource non managée qui a été allouée
		// ...
		// ...
	}

	// destruteur de la class
	~MaClasseManagée()
	{
		// partie un peu tricky : on interdit au CLR de supprimer l&#039;instance
		// courante car ça a déjà été fait dans le Dispose d&#039;IDisposable
		GC.SuppressFinalize(this);

		// on s&#039;assure quand même qu&#039;on garde pas de référence vers le pointeur
		m_Ressource_non_managée = IntPtr.Zero;
	}

	// methode dispose la plus importante
    public void Dispose()
    {
        if(!disposed)
        {
			// on appelle le garbage collector, et on force la libération de
			// tous les objets pour être certains de plus référencer des variables
			// non managées depuis C#
			GC.Collect();

			disposed = true; // déja disposé
        }
    }
}
</pre>
<p>Notez donc qu&#8217;il faut bien faire la différence entre le constructeur, le destructeur, et le dispose. Trop souvent les gens oublient l&#8217;un des trois, et compromettent du coup la sécurité de leur code.</p>
<p>A l&#8217;utilisation c&#8217;est simple :</p>
<pre name="code" class="csharp">

// mot clé using
using(MaClasseManagée obj = new MaClasseManagée())
{
	// manipuler obj
	obj.FaireQuelqueChose();
}
// à la sortie du bloc using, le garbage collector est appellé et libère le tas
// des instances de MaClasseManagée persistantes, donc, forcément avec notre
// pattern, des ressources non managées IntPtr aussi
</pre>
<p>Et voilà :)</p>
<p>Je compte faire un article bientôt sur une nouvelle façon d&#8217;appréhender cette problématique avec l&#8217;AOP, notamment dans les architectures distribuées où il y a trop de code à écrire pour qu&#8217;on puisse se permettre de perdre du temps avec ces considérations bas niveau dans un contexte économique délicat (c&#8217;est la crise !) qui nous force à économiser le temps et l&#8217;argent sans pour autant arrêter de produire des logiciels de qualité qui donneront satisfaction au client et permettront aux développeurs de ne pas s&#8217;arracher les cheveux sur des solutions de 50 projets où les autres ont fait n&#8217;importe quoi et qu&#8217;il faut quand même livrer coute que coute tant pis pour les nuits blanches (ça serait quand même un comble de ne plus être en mesure de maitriser son métier, ou de devoir arrêter la qualité sous prétexte que c&#8217;est les chefs de projets qui décident des planning sans rien comprendre de la technique alors que c&#8217;est la base).</p>
Posted in Posts Tagged: .NET, C#, WTF <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/romainverdier.wordpress.com/641/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/romainverdier.wordpress.com/641/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/romainverdier.wordpress.com/641/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/romainverdier.wordpress.com/641/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/romainverdier.wordpress.com/641/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/romainverdier.wordpress.com/641/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/romainverdier.wordpress.com/641/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/romainverdier.wordpress.com/641/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/romainverdier.wordpress.com/641/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/romainverdier.wordpress.com/641/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=codingly.com&blog=3510695&post=641&subd=romainverdier&ref=&feed=1" /></div><img src="http://feeds.feedburner.com/~r/Codingly/~4/zMx02ykcfH8" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://codingly.com/2009/04/01/petit-rappel-sur-le-disposing-pattern-en-c/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/cb0ee4bde49708f4be24a02a5d59e52e?s=96&amp;d=http%3A%2F%2F0.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96" medium="image">
			<media:title type="html">Romain</media:title>
		</media:content>
	<feedburner:origLink>http://codingly.com/2009/04/01/petit-rappel-sur-le-disposing-pattern-en-c/</feedburner:origLink></item>
		<item>
		<title>Nouveau site pour ALT.NET France</title>
		<link>http://feedproxy.google.com/~r/Codingly/~3/OGi0tfVaB4I/</link>
		<comments>http://codingly.com/2009/03/02/nouveau-site-pour-altnet-france/#comments</comments>
		<pubDate>Mon, 02 Mar 2009 10:21:03 +0000</pubDate>
		<dc:creator>Romain Verdier</dc:creator>
				<category><![CDATA[Posts]]></category>
		<category><![CDATA[ALT.NET]]></category>
		<category><![CDATA[Annonce]]></category>

		<guid isPermaLink="false">http://codingly.com/?p=626</guid>
		<description><![CDATA[Enfin ! Nous avions un groupe de discussion depuis le début, et nous squattions à droite et à gauche lorsqu&#8217;il était nécessaire de communiquer et de s&#8217;organiser, mais depuis quelques jours nous avons notre vrai portail. Un grand merci à Julien pour son travail, et à ceux qui ont commencé à contribuer à l&#8217;élaboration du [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=codingly.com&blog=3510695&post=626&subd=romainverdier&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p>Enfin ! Nous avions un <a href="http://groups.google.com/group/parisaltnet">groupe de discussion</a> depuis le début, et nous squattions à droite et à gauche lorsqu&#8217;il était nécessaire de communiquer et de s&#8217;organiser, mais depuis quelques jours nous avons notre vrai portail. Un grand merci à <a href="http://www.thedotnetfrog.fr/">Julien</a> pour son travail, et à ceux qui ont commencé à contribuer à l&#8217;élaboration du contenu :</p>
<p><strong><a href="http://www.altnetfr.org/">www.altnetfr.org</a></strong></p>
<blockquote><p>ALT.Net est un groupe de développeurs .NET passionnés, cherchant à améliorer la façon dont les logiciels sont développés. Nous reconnaissons qu’il n’y a pas de solution unique à un problème mais qu’il y a une multitude d’alternatives pouvant être appliquées dans différentes situations.</p></blockquote>
<p><span id="more-626"></span></p>
<p>Le but était d&#8217;offrir une façade à la communauté ALT.NET de France. Jusqu&#8217;alors il fallait être spécialement motivé pour parvenir à comprendre ce qu&#8217;était ALT.NET, et encore un peu plus pour oser venir aux rencontres. Le nouveau site devrait donc répondre à ces deux besoins, en décrivant le mouvement et ses principes d&#8217;une part, et en proposant l&#8217;agenda des différents évènements que nous organisons d&#8217;autre part.</p>
<p>La dernière réunion a permis à Nicolas Roux et Frédéric Fadel de nous présenter <a href="http://aspectize.com/">Aspectize</a>, et <a href="http://www.altnetfr.org/2009/02/22/altnet-fr-10-aspectize-compte-rendu-par-gauthier/">un compte rendu</a> a déjà été posté par Gauthier. En Mars, <a href="http://www.altnetfr.org/2009/02/20/altnet-paris-11-test-driven-development/">il sera question de TDD</a>, et c&#8217;est Djamel Zouaoui et Frédéric Schäfer qui animeront la présentation dans les locaux d&#8217;Octo. Nous comptons continuer de la sorte en annonçant les réunions futures et en proposant des comptes-rendus régulièrement. N&#8217;hésitez d&#8217;ailleurs pas à soumettre vos contributions ; un effort collaboratif ne peut qu&#8217;être profitable.</p>
<p>Pour ceux qui ne sont pas spécialement enclins à rédiger des comptes-rendus ou à proposer des articles, notez qu&#8217;il existe un <a href="http://wiki.altnetfr.org/doku.php">wiki</a>, qui offre déjà à tous la possibilité de participer sans contrainte particulière à l&#8217;enrichissement des ressources ALT.NET en français.</p>
<p>Bref, vous êtes chaudement invités à :</p>
<ul>
<li>Ajouter altnetfr.org dans vos readers</li>
<li>Proposer vos comptes-rendus, vos articles, etc.</li>
<li>Venir à la prochaine réunion (et aux autres)</li>
<li>Faire passer le mot au sujet d&#8217;ALT.NET France !</li>
<ul>
Posted in Posts Tagged: ALT.NET, Annonce <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/romainverdier.wordpress.com/626/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/romainverdier.wordpress.com/626/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/romainverdier.wordpress.com/626/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/romainverdier.wordpress.com/626/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/romainverdier.wordpress.com/626/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/romainverdier.wordpress.com/626/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/romainverdier.wordpress.com/626/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/romainverdier.wordpress.com/626/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/romainverdier.wordpress.com/626/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/romainverdier.wordpress.com/626/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=codingly.com&blog=3510695&post=626&subd=romainverdier&ref=&feed=1" /></div><img src="http://feeds.feedburner.com/~r/Codingly/~4/OGi0tfVaB4I" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://codingly.com/2009/03/02/nouveau-site-pour-altnet-france/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/cb0ee4bde49708f4be24a02a5d59e52e?s=96&amp;d=http%3A%2F%2F0.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96" medium="image">
			<media:title type="html">Romain</media:title>
		</media:content>
	<feedburner:origLink>http://codingly.com/2009/03/02/nouveau-site-pour-altnet-france/</feedburner:origLink></item>
		<item>
		<title>Si les types étaient des animaux, TypedReference serait un ornithorynque</title>
		<link>http://feedproxy.google.com/~r/Codingly/~3/-1ImBKH4ikg/</link>
		<comments>http://codingly.com/2009/01/15/si-les-types-etaient-des-animaux-typedreference-serait-un-ornithorynque/#comments</comments>
		<pubDate>Thu, 15 Jan 2009 00:08:29 +0000</pubDate>
		<dc:creator>Romain Verdier</dc:creator>
				<category><![CDATA[Articles]]></category>
		<category><![CDATA[.NET]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[CIL]]></category>
		<category><![CDATA[Optimisation]]></category>

		<guid isPermaLink="false">http://codingly.com/?p=535</guid>
		<description><![CDATA[Devinette : C&#8217;est un type valeur, mais on ne peut pas le caster en object. Il est impossible d&#8217;en déclarer des tableaux. On ne peut l&#8217;utiliser que pour typer les paramètres de méthodes et les variables locales. Il existe 4 mots clés non documentés en C# qui lui sont directement reliés, et autant d&#8217;opcodes en [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=codingly.com&blog=3510695&post=535&subd=romainverdier&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p>Devinette : C&#8217;est un type valeur, mais on ne peut pas le caster en <code>object</code>. Il est impossible d&#8217;en déclarer des tableaux. On ne peut l&#8217;utiliser que pour typer les paramètres de méthodes et les variables locales. Il existe 4 mots clés non documentés en C# qui lui sont directement reliés, et autant d&#8217;opcodes en CIL. Il permet notamment le support des varargs, et exactement 8 personnes dans le monde se sont souciées plus de 5 min de son existence.</p>
<p>Je veux parler, bien évidemment, de <code><a href="http://www.urbandictionary.com/define.php?term=PITA">TypedReference</a></code>. Je vous propose de découvrir ce type à partir d&#8217;un exemple rigolo.<br />
<span id="more-535"></span></p>
<h3>Méthodes <em>varargs</em> et interopérabilité</h3>
<p>En C#, lorsqu&#8217;on veut définir une méthode à nombre de paramètres variables, on utilise la syntaxe suivante :</p>
<pre name="code" class="csharp">

public static double Average(params int[] values)
{
    double sum = 0;
    foreach (var i in values)
        sum += i;
    return sum / values.Length;
}
</pre>
<p>Notez le mot clé <code>params</code> qui permet l&#8217;appel de la méthode en passant un tableau en paramètre, ou en listant plus librement les arguments :</p>
<pre name="code" class="csharp">

var parameters = new int[]{45, 68, 97, 45};
ManagedClass.Average (parameters)
// ou bien
ManagedClass.Average (45, 68, 97, 45)
</pre>
<p>En <a href="http://en.wikipedia.org/wiki/C%2B%2B/CLI">C++ / CLI</a>, la syntaxe est un peu différente mais le principe est le même :</p>
<pre name="code" class="c++">

double CodinglyInterop::CppCliLibrary::average(... array&lt;int,1&gt; ^values)
{
	double sum = 0;
	for each (int i  in values)
		sum += i;
	return sum/values-&gt;Length;
}
</pre>
<p>C&#8217;est pareil, en plus moche. On utilise &#8220;<code>...</code>&#8221; au lieu de &#8220;<code>params</code>&#8220;, et l&#8217;appelant peut passer un tableau ou une liste d&#8217;arguments :</p>
<pre name="code" class="csharp">

var parameters = new int[]{45, 68, 97, 45};
CppCliLibrary.average(parameters)
// ou bien
CppCliLibrary.average(45, 68, 97, 45)
</pre>
<p>Notez que l&#8217;interopérabilité entre C# et C++/CLI est native : les deux langages sont managés.</p>
<p>Et en C++ pas CLI, qu&#8217;est-ce que donnent les fonctions à nombre variable d&#8217;arguments ?</p>
<p>Bah c&#8217;est encore plus moche, et plus contraignant. Rappelez-vous :</p>
<pre name="code" class="c++">

extern &quot;C&quot; __declspec(dllexport) double average(int n, ...)
{
	double sum = 0;
	va_list args;
	va_start(args, n);
	for(int i=0 ;i &lt; n; i++)
		sum += va_arg(args, int);
	va_end(args);
	return sum/n;
}
</pre>
<p>La principale différence est finalement assez subtile on n&#8217;utilise pas explicitement un tableau, mais on fournit un pointeur vers le début de la liste d&#8217;arguments. C&#8217;est à la méthode de se débrouiller (avec des macros) pour itérer, caster et s&#8217;arrêter lorsqu&#8217;il le faut. Généralement, un autre paramètre nommé de la méthode contient les infos nécessaires à cette opération. Dans l&#8217;exemple précédent, &#8220;<code>n</code>&#8221; est utilisé pour passer directement le nombre d&#8217;arguments de la liste. Dans <code>printf</code>, c&#8217;est la <em>format string</em> qui permet à la fonction de savoir combien d&#8217;arguments elle doit lire.</p>
<p>La question rigolote, puisque nous sommes dans le contexte d&#8217;un exemple rigolo, est la suivante :</p>
<p>Mais comment appeler les fonctions natives de ce genre depuis C# ? En utilisant <code><a href="http://fr.wikipedia.org/wiki/P/Invoke">pinvoke</a></code>, probablement, mais plus précisément ?</p>
<p>Réponse : En pleurant. On est obligé de déclarer explicitement les imports pour chacune des utilisations que l&#8217;on va faire de la fonction dans notre code managé. En gros :</p>
<pre name="code" class="csharp">

[DllImport (&quot;NativeLibrary.dll&quot;)]
public static extern double average (int n, int i1);

[DllImport (&quot;NativeLibrary.dll&quot;)]
public static extern double average (int n, int i1, int i2);

[DllImport (&quot;NativeLibrary.dll&quot;)]
public static extern double average (int n, int i1, int i2, int i3);

[DllImport (&quot;NativeLibrary.dll&quot;)]
public static extern double average (int n, int i1, int i2, int i3, int i4);

// Etc.
</pre>
<p>What a <a href="http://www.urbandictionary.com/define.php?term=PITA">PITA</a>, comme qui dirait&#8230; Mais c&#8217;est ici que l&#8217;ornithorynque nous sauve la vie. Car on peut écrire :</p>
<pre name="code" class="csharp">

[DllImport (&quot;NativeLibrary.dll&quot;, CallingConvention = CallingConvention.Cdecl)]
public static extern double average (int n, __arglist );
</pre>
<p>Et appeler la fonction ainsi :</p>
<pre name="code" class="csharp">

NativeWrapper.average (4, __arglist (45, 68, 97, 45))
</pre>
<p>Hourra, donc. Mais quel est ce mot clé bizarre, <code>__arglist</code>, qui n&#8217;est même pas reconnu par Resharper ? Et bien il s&#8217;agit d&#8217;un des mots clés <em>non documentés</em> du langage, qui permettent principalement de jouer avec les <code>TypedReference</code>. Pour mieux comprendre ce qui se passe, essayons de réécrire en C# la méthode <code>Average</code>, sans utiliser le mot clé <code>params</code>, et en se reposant donc uniquement sur les &#8220;références typées&#8221;. On s&#8217;attaquera ensuite à la définition.</p>
<pre name="code" class="csharp">

public class ManagedEvil
{
    public static double Average(__arglist)
    {
        double sum = 0;
        int count = 0;
        var iterator = new ArgIterator(__arglist);
        do
        {
            TypedReference typedReference = iterator.GetNextArg();
            sum += __refvalue( typedReference,int);
            count++;
        } while (iterator.GetRemainingCount() &gt; 0);
        return sum / count;
    }
}
</pre>
<p>On note :</p>
<ul>
<li>L&#8217;apparition du type <code>ArgIterator</code>, dont on crée une instance à partir de la liste d&#8217;arguments.</li>
<li>L&#8217;élément courant retourné par l&#8217;itérateur est une référence typée : <code>TypedReference</code>.</li>
<li>Un nouveau mot clé, <code>__refvalue</code>, permet d&#8217;extraire la valeur pointée par la référence.</li>
</ul>
<p>Et tout ça compile, tout ça fonctionne, même si l&#8217;intérêt est limité. </p>
<h3><code>TypedReference</code>, <code>__makeref</code>, <code>__refvalue</code>, <code>__reftype</code></h3>
<p>Arrêtons les expériences pour décortiquer un peu plus sérieusement ce <code>TypedReference</code>. La MSDN définit <strike>très clairement</strike> la <code>TypedReference</code> :</p>
<blockquote><p>Describes objects that contain both a managed pointer to a location and a runtime representation of the type that may be stored at that location.</p></blockquote>
<p>Retenons qu&#8217;il s&#8217;agit d&#8217;une structure contenant : </p>
<ul>
<li>Un pointeur managé vers un espace mémoire</li>
<li>Le type de ce qui est pointé en mémoire</li>
</ul>
<p>Le meilleur endroit pour trouver des infos au sujet de <code>TypedReference</code> est finalement la spécification <a href="http://www.ecma-international.org/publications/standards/Ecma-335.htm">ECMA 335 du CIL</a>. Je vous laisse fouiller, mais sachez que les bases sont notamment posées dans le paragraphe suivant (cf. 8.6.1.3):</p>
<blockquote><p>La signature d&#8217;une référence typée est en fait représentée en tant que type valeur de base, comme les entiers ou nombres à virgule flottante. Dans la bibliothèque de classes du framework, le type est représenté par <code>System.TypedReference</code>, tandis que dans le langage intermédiaire il est désigné par le mot clé <code>typedref</code>. Ce type doit uniquement être utilisé pour les paramètres et les variables locales. Il ne peut ni être boxé ni être utilisé pour typer un champ, un élément de tableau, ou une valeur de retour de fonction.</p></blockquote>
<p>Pour que je ne puisse jamais justifier l&#8217;intérêt de cet article, les gens chez Microsoft ont bien fait attention à exposer ce type le moins possible. Il est pourtant assez utilisé en interne, notamment dans <code>System.Array</code>, <code>System.Threading.Interlocked</code>, les services d&#8217;intérop (<code>InteropServices</code>) ainsi que dans certains overloads cachés utilisant les varargs (<code>String.Concat</code>, <code>Console.WriteLine</code>). A vrai dire, il semblerait que la raison officielle de son existence soit justement le support par le CLR des listes d&#8217;arguments, comme nous l&#8217;avons vu plus tôt. Il existe cependant un autre endroit (parmi d&#8217;autres) où son utilisation peut s&#8217;avérer intéressante : la réflexion via les <code>FieldInfo</code>. Mais avant d&#8217;y venir, regardons plutôt comment utiliser, très mécaniquement, <code>TypedReference</code>. On peut soit utiliser les mots clés interdits, soit &#8211; lorsque c&#8217;est possible &#8211; utiliser les quelques méthodes statiques de la classe <code>TypedReference</code> elle-même.</p>
<p><strong>Création d&#8217;une référence typée</strong> : <code>__makeref</code></p>
<p>Les références typées peuvent être obtenues pour des variables de n&#8217;importe quel type (référence ou valeur) à l&#8217;aide du mot clé <code>__makeref</code>.</p>
<pre name="code" class="csharp">

int i = 42;
TypedReference typedReference = __makeref (i);
</pre>
<p>Ce mot clé dont l&#8217;usage n&#8217;est pas documenté correspond à l&#8217;instruction <code>mkrefany</code> en CIL. Le code intermédiaire correspondant à l&#8217;exemple précédant est le suivant :</p>
<pre name="code" class="c++">

int i = 42;

L_0000: ldc.i4.s 0x2a	/* push sur la pile d&#039;un int32 = 42						*/
L_0002: stloc.0			/* sauvegarde dans la variable locale i					*/

TypedReference typedReference = __makeref(i);

L_0003: ldloca.s i		/* push sur la pile de l&#039;adresse de i					*/
L_0005: mkrefany int32	/* push sur la pile de la référence typée				*/
L_000a: stloc.1			/* sauvegarde dans la variable locale typedReference	*/
</pre>
<p>La méthode statique <code>TypedReference.MakeTypedReference</code> permet aussi de créer des références typées, mais pas directement à partir d&#8217;une variable. Nous verrons un exemple d&#8217;utilisation dans la dernière partie de l&#8217;article.</p>
<p><strong>Récupérer et/ou modifier la valeur</strong> : <code>__refvalue</code></p>
<p>Une fois qu&#8217;on a une référence typée, il est possible de lire et/ou d&#8217;écrire la valeur référencée en utilisant le mot clé <code>__refvalue</code>. Il est visuellement assimilable à un appel de fonction à deux paramètres, dont le premier serait la <code>TypedReference</code>, et le second le type de la valeur référencée. En l&#8217;utilisant à droite d&#8217;une affectation, on lit la valeur, et en l&#8217;utilisant à gauche d&#8217;une affectation, on écrit la valeur. Assez troublant&#8230;</p>
<pre name="code" class="csharp">

int i = 42;
TypedReference typedReference = __makeref(i);
int j = __refvalue (typedReference, int);
__refvalue (typedReference, int) = 24;
</pre>
<p>Encore une fois, il est possible de mapper son utilisation avec un opcode spécifique, <code>refanyval</code> :</p>
<pre name="code" class="c++">

int i = 42;
TypedReference typedReference = __makeref(i);

L_0000: ldc.i4.s 0x2a	/* push sur la pile d&#039;un int32 = 42						*/
L_0002: stloc.0			/* sauvegarde dans la variable locale i					*/
L_0003: ldloca.s i		/* push sur la pile de l&#039;adresse de i					*/
L_0005: mkrefany int32	/* push sur la pile de la référence typée				*/
L_000a: stloc.1			/* sauvegarde dans la variable locale typedReference	*/

int j = __refvalue (typedReference, int);

L_000b: ldloc.1			/* push sur la pile de la typedReference				*/
L_000c: refanyval int32 /* push sur la pile de l&#039;adresse de la référence        */
L_0011: ldind.i4		/* déréférencement et push sur la pile de la valeur		*/
L_0012: stloc.2			/* sauvegarde dans la variable locale j					*/

__refvalue (typedReference, int) = 24;

L_0013: ldloc.1			/* push sur la pile de la typedReference				*/
L_0014: refanyval int32 /* push sur la pile de l&#039;adresse de la référence        */
L_0019: ldc.i4.s 0x18	/* push sur la pile d&#039;un int32 = 24						*/
L_001b: stind.i4		/* sauvegarde de la valeur à l&#039;adresse de la référence  */
</pre>
<p>La méthode <code>TypedReference.ToObject</code> permet aussi de déréférencer la <code>TypedReference</code> et d&#8217;obtenir sa valeur, boxée.</p>
<p><strong>Récupérer le type</strong> : <code>__reftype</code></p>
<p>Enfin, il est possible de récupérer l&#8217;information de type associée à la <code>TypeReference</code>, en utilisant un dernier mot clé <code>__reftype</code>.</p>
<pre name="code" class="csharp">

int i = 42;
TypedReference typedReference = __makeref(i);
Type type = __reftype(typedReference);
</pre>
<p>Là encore, on peut faire correspondre <code>__reftype</code> à l&#8217;opcode <code>refanytype</code> :</p>
<pre name="code" class="c++">

int i = 42;
TypedReference typedReference = __makeref(i);

L_0000: ldc.i4.s 0x2a	/* push sur la pile d&#039;un int32 = 42						*/
L_0002: stloc.0			/* sauvegarde dans la variable locale i					*/
L_0003: ldloca.s i		/* push sur la pile de l&#039;adresse de i					*/
L_0005: mkrefany int32	/* push sur la pile de la référence typée				*/
L_000a: stloc.1			/* sauvegarde dans la variable locale typedReference	*/

Type type = __reftype(typedReference);

L_000b: ldloc.1			/* push sur la pile de la typedReference				*/
L_000c: refanytype		/* push sur la pile du type token de la référence		*/
L_000e: call class Type::GetTypeFromHandle(RuntimeTypeHandle)
L_0013: stloc.2			/* récupération et sauvegarde du Type à partir du token */
</pre>
<p>Notons que la méthode statique <code>TypedReference.GetTargetType</code> est l&#8217;équivalent autorisé de <code>__reftype</code>, et qu&#8217;il existe aussi la méthode <code>TypedReference.TargetTypeToken</code> qui retourne le handle du type sous la forme d&#8217;un <code>RuntimeTypeHandle</code>. La version light, en somme. </p>
<p>Rien de très impressionnant ; d&#8217;ailleurs vous pouvez retourner sur youtube car la suite n&#8217;est pas mieux. Mais je persiste !</p>
<h3>Un autre exemple : <code>GetValueDirect</code> et <code>SetValueDirect</code></h3>
<p>Je vous disais tout à l&#8217;heure que j&#8217;avais trouvé un exemple d&#8217;utilisation dans lequel on pouvait faire intervenir les <code>TypedReference</code>. Il s&#8217;agit de la lecture écriture des champs par réflexion, et plus particulièrement des champs de type valeur. Et encore plus particulièrement lorsqu&#8217;ils sont imbriqués.</p>
<p>Prenons pour exemple ce modèle simpliste :</p>
<pre name="code" class="csharp">

public struct Person
{
	public Address Address;
}

public struct Address
{
	public City City;
}

public struct City
{
	public int ZipCode;
}
</pre>
<p>Il est important de bien noter que <code>Person</code>, <code>Address</code>, <code>City</code> et <code>ZipCode</code> sont des value types. Si on veut inspecter une instance de <code>Person</code> par réflexion, jusqu&#8217;à lire le <code>ZipCode</code> de son adresse, on va écrire quelque chose comme :</p>
<pre name="code" class="csharp">

// On a une instance de Person
var p = new Person();
p.Address.City.ZipCode = 75000;

// On récupère les FieldInfo
var addressField = typeof(Person).GetField(&quot;Address&quot;);
var cityField = typeof(Address).GetField(&quot;City&quot;);
var zipCodeField = typeof(City).GetField(&quot;ZipCode&quot;);

// On chaine les appels à FieldInfo.GetValue pour inspecter la Person
// et lire la valeur du ZipCode
var zipCode =  (int)zipCodeField.GetValue(cityField.GetValue(addressField.GetValue(p)));
</pre>
<p>Ca fonctionne, mais le boxing a tué mon hourra. <code>GetValue</code> prend un <code>object</code> en argument, et retourne un <code>object</code>, alors qu&#8217;on travaille ici sur des types valeurs&#8230; En lisant la dernière ligne de droite à gauche :</p>
<ul>
<li>p va être boxé pour être passé en paramètre à <code>GetValue</code></li>
<li><code>addressField.GetValue</code> va boxer la valeur du champ <code>Address</code> pour le retourner sous la forme d&#8217;un <code>object</code></li>
<li><code>cityField.GetValue</code> va boxer la valeur du champ <code>City</code> pour le retourner sous la forme d&#8217;un <code>object</code></li>
<li><code>zipCodeField.GetValue</code> va boxer la valeur du champ <code>ZipCode</code> pour le retourner sous la forme d&#8217;un <code>object</code></li>
<li>Le cast en <code>int</code> effectue l&#8217;ultime et nécessaire unboxing</li>
</ul>
<p>Pas terrible&#8230;</p>
<p>Heureusement, il existe sur <code>FieldInfo</code> la méthode <code>GetValueDirect</code>, qui prend en paramètre une <code>TypedReference</code> !</p>
<p>Si on peut directement récupérer une référence typée sur le <code>ZipCode</code>, on peut éviter quelques emboitages :</p>
<pre name="code" class="csharp">

var p = new Person();
p.Address.City.ZipCode = 75000;
FieldInfo zipCodeField = typeof(City).GetField(&quot;ZipCode&quot;);
var zipCode = (int)zipCodeField.GetValueDirect(__makeref (p.Address.City)); 
</pre>
<p>Seulement, on change les contraintes, car la création de la référence typée de cette façon implique alors que l&#8217;on connaisse <code>Address</code> et <code>City</code> au design time. Qu&#8217;à cela ne tienne : il existe la méthode statique <code>TypedReference.MakeTypedReference</code> évoquée plus tôt, qui permet de construire une référence typée à partir d&#8217;une target et d&#8217;un tableau de <code>FieldInfo</code> correspondant à l&#8217;inspection désirée de l&#8217;espace mémoire réservé par <code>p</code> :</p>
<pre name="code" class="csharp">

var p = new Person ();
p.Address.City.ZipCode = 75000;
var addressField = typeof (Person).GetField (&quot;Address&quot;);
var cityField = typeof (Address).GetField (&quot;City&quot;);
var zipCodeField = typeof (City).GetField (&quot;ZipCode&quot;);

TypedReference r = TypedReference.MakeTypedReference (p, new[] {addressField, cityField});
var zipCode = (int) zipCodeField.GetValueDirect (r);
</pre>
<p>Dans ce cas précis, les performances mesurées sont environ <strong>4 fois meilleures</strong> en utilisant <code>GetValueDirect</code> à la place de <code>GetValue</code>. Hourra.</p>
<p>Quant à l&#8217;écriture, nous n&#8217;avons même pas le luxe du choix, puisque chainer les <code>SetValue</code> ne peut en aucun cas modifier la personne, cette fonction retournant à chaque fois une <em>copie</em> des valeurs&#8230; Il faut donc nécessairement utiliser <code>SetValueDirect</code> et une <code>TypedReference</code>.</p>
<h3>Conclusion</h3>
<p>La conclusion, que je vous dois brève :</p>
<p><strong>Ce qui n&#8217;est pas documenté ne doit pas être utilisé</strong>. En gros, tout ce qui est lié aux arglists est à oublier. En revanche, la création et la manipulation de <code>TypedReference</code> sans passer par tous les __mots __clés __moches n&#8217;est pas réprouvée. Notez simplement que <code>TypedReference</code> n&#8217;est pas <em>CLS Compliant</em>.</p>
Posted in Articles Tagged: .NET, C#, CIL, Optimisation <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/romainverdier.wordpress.com/535/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/romainverdier.wordpress.com/535/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/romainverdier.wordpress.com/535/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/romainverdier.wordpress.com/535/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/romainverdier.wordpress.com/535/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/romainverdier.wordpress.com/535/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/romainverdier.wordpress.com/535/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/romainverdier.wordpress.com/535/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/romainverdier.wordpress.com/535/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/romainverdier.wordpress.com/535/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=codingly.com&blog=3510695&post=535&subd=romainverdier&ref=&feed=1" /></div><img src="http://feeds.feedburner.com/~r/Codingly/~4/-1ImBKH4ikg" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://codingly.com/2009/01/15/si-les-types-etaient-des-animaux-typedreference-serait-un-ornithorynque/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/cb0ee4bde49708f4be24a02a5d59e52e?s=96&amp;d=http%3A%2F%2F0.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96" medium="image">
			<media:title type="html">Romain</media:title>
		</media:content>
	<feedburner:origLink>http://codingly.com/2009/01/15/si-les-types-etaient-des-animaux-typedreference-serait-un-ornithorynque/</feedburner:origLink></item>
		<item>
		<title>Dégage, sale programmeur !</title>
		<link>http://feedproxy.google.com/~r/Codingly/~3/UawqGs3KAtg/</link>
		<comments>http://codingly.com/2008/12/29/degage-sale-programmeur/#comments</comments>
		<pubDate>Mon, 29 Dec 2008 23:35:29 +0000</pubDate>
		<dc:creator>Romain Verdier</dc:creator>
				<category><![CDATA[Posts]]></category>
		<category><![CDATA[Opinion]]></category>

		<guid isPermaLink="false">http://codingly.com/?p=491</guid>
		<description><![CDATA[Et ouais, être développeur lorsqu&#8217;on a plus de 30 ans en France, c&#8217;est pire que d&#8217;être caissier à 40 ans. La plupart des gens qui passent 90% de leur temps à programmer vont s&#8217;arranger pour qu&#8217;on les voit comme des ingénieurs d&#8217;études, des experts techniques, des chefs de projets, des architectes solution, des consultants, etc. [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=codingly.com&blog=3510695&post=491&subd=romainverdier&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p>Et ouais, être développeur lorsqu&#8217;on a plus de 30 ans en France, c&#8217;est pire que d&#8217;être caissier à 40 ans. La plupart des gens qui passent 90% de leur temps à programmer vont s&#8217;arranger pour qu&#8217;on les voit comme des ingénieurs d&#8217;études, des experts techniques, des chefs de projets, des architectes solution, des consultants, etc. Le top, quand on est un pauvre prestataire d&#8217;une SSII en mission pour une banque, et que l&#8217;on passe ses journées à coder, c&#8217;est de raconter à tout le monde qu&#8217;on est INGENIEUR DANS LA FINANCE. Oui oui.</p>
<p>C&#8217;est assez terrible, mais il semblerait qu&#8217;on n&#8217;y puisse pas grand chose.</p>
<p><span id="more-491"></span></p>
<p>La première observation, c&#8217;est que le phénomène est assez localisé. Ou plutôt : le phénomène n&#8217;est pas généralisé. En France, dès les études, on explique qu&#8217;il y a les développeurs (berk), et les chefs (ouais).</p>
<blockquote><p>Bon, les enfants, si vous avez été admis chez SUPIMAG, c&#8217;est pas pour finir développeur. En sortant de notre établissement, espérez être chef de projet junior (à la tête de 5 développeurs, 52K€, pendant 6 à 12 mois), puis, <em>évidemment</em> directeur de projet (1200 développeurs à vos pieds, 420K€ + iPhone + bonus)</p></blockquote>
<p>Et ensuite, même si on se fout de votre gueule lors des premiers entretiens, c&#8217;est trop tard : vous ne voulez plus, vous ne pouvez plus être développeur. On pourrait vous confondre avec l&#8217;admin réseau (BTS Informatique et Réseaux pour l’Industrie et les Services Techniques, 23K€, Nokia 3310 pour les astreintes). </p>
<p>Aux Etats-Unis, par exemple, et sans doute ailleurs, ça ne fonctionne pas comme ça. Il y a <a href="http://stackoverflow.com/questions/389833/manager-versus-developer-as-a-career">différents métiers</a>. Développeur, c&#8217;est un métier. Manager, c&#8217;est un <em>autre métier</em>. Le développeur programme, et le manager gère. Il est tout à fait possible de rester programmeur lorsqu&#8217;on devient papa. On n&#8217;est pas pris pour un con, juste pour un programmeur senior, payé et reconnu comme tel. Un professionnel ayant fait un choix de carrière plutôt qu&#8217;un autre, en somme. Il n&#8217;y a pas une hiérarchie dans laquelle le programmeur est en bas de l&#8217;échelle, il y a juste différents métiers dont les exercices sont nécessaires à la réalisation des projets informatiques.</p>
<p>Tant qu&#8217;on ne comprendra pas ça ici, on continuera à subir les rires bruyants des gros blaireaux qui parlent de pissage-de-code-lol.</p>
<p>Gens, vous vous trompez.</p>
<p>Le développement, ou l&#8217;ingénierie logicielle si on veut élargir un peu, est une discipline <em>complexe</em>, qui requiert un cerveau. Un développeur digne de ce nom est une personne capable de réfléchir, de conceptualiser, de comprendre. C&#8217;est une personne capable de travailler en équipe, de communiquer efficacement, de s&#8217;organiser. C&#8217;est une personne qui ne peut pas se reposer éternellement sur ses acquis. C&#8217;est aussi une personne qui doit produire, et qui peut difficilement tricher. Programmer est un métier à la fois compliqué et passionnant, dont on peut même penser qu&#8217;il demande du talent. En fait, c&#8217;est probablement l&#8217;un des métiers les plus exigeants et intelligents qui soient.</p>
<p>Il est presque incompréhensible qu&#8217;on en soit arrivé à trouver ça péjoratif, et que la programmation ait été reléguée au rang de tâche honteuse. </p>
<blockquote><p><strong>Programmeur</strong> : n.m. Celui dont le métier est de rédiger des programmes informatiques. Le plus souvent, jeune diplômé, ou chef de projet raté. Syn. <em>looser</em>. Ex. <em>Tu crains comme un programmeur</em>.</p></blockquote>
<p>Première hypothèse : Romain, t&#8217;es un crétin doublé d&#8217;un parano : personne n&#8217;a cette sale image des développeurs. Deuxième hypothèse &#8211; très personnelle et probablement très discutable : tout le monde n&#8217;est pas né pour être programmeur. Et tant mieux, devrais-je ajouter : il serait assez triste de rêver du contraire. Cependant, il y a un besoin de programmeurs, en France comme ailleurs, et donc, on obtient fatalement une armée de développeurs-malgré-eux. Ni particulièrement doués ni particulièrement motivés, il se retrouvent à devoir maintenir des applications plus ou moins monstrueuses, sans vraiment comprendre ce qu&#8217;ils font et sans avoir envie d&#8217;ailleurs d&#8217;en comprendre plus. Développer, pfiou, c&#8217;est finalement un peu relou, hein. Vivement que je puisse moi aussi passer mes journées sur Powerpoint.</p>
<p>Ce que je veux dire, c&#8217;est que dans le fond, il y a peu de personnes qui savent ce qu&#8217;est la programmation. Parmi les programmeurs, les chefs, les recruteurs, les profs, les chats, ma mère. Moi, plus par fausse modestie que pour paraphraser Socrate, j&#8217;ai découvert il n&#8217;y a pas si longtemps que je ne savais pas vraiment ce qu&#8217;était la programmation.</p>
<p>Bon, j&#8217;exagère un peu pour que vous souriez, mais au delà de la simplification volontairement naïve et de la provocation facile, je crois qu&#8217;il y a un peu de vrai. Quand la Masse se met d&#8217;accord sur une définition faussée du métier de programmeur, les choses sont vite réglées. A côté de ça, il y a des développeurs &#8220;qui ont goûté au sang&#8221; (© <a href="http://evain.net/blog/">Jb</a>) et qui ont du mal à revenir aux <a href="http://admin.proxi-business.com/uploads/CHAMPION_GRANDCHAMP/PHOTO1/3033490/281021.jpg">Taillefine &#8220;Pruneau&#8221; 0%</a>. Tant qu&#8217;à faire, ne confondez pas tout le monde et choisissez bien votre audience le jour où vous voulez expliquer que vous aimez programmer, ou pire, que vous êtes capable d&#8217;en tirer une certaine fierté.</p>
<p>Au fait, ça existe les architectes qui écrivent juste les prototypes des méthodes et qui laissent l&#8217;implémentation aux programmeurs ?</p>
Posted in Posts Tagged: Opinion <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/romainverdier.wordpress.com/491/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/romainverdier.wordpress.com/491/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/romainverdier.wordpress.com/491/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/romainverdier.wordpress.com/491/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/romainverdier.wordpress.com/491/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/romainverdier.wordpress.com/491/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/romainverdier.wordpress.com/491/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/romainverdier.wordpress.com/491/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/romainverdier.wordpress.com/491/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/romainverdier.wordpress.com/491/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=codingly.com&blog=3510695&post=491&subd=romainverdier&ref=&feed=1" /></div><img src="http://feeds.feedburner.com/~r/Codingly/~4/UawqGs3KAtg" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://codingly.com/2008/12/29/degage-sale-programmeur/feed/</wfw:commentRss>
		<slash:comments>19</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/cb0ee4bde49708f4be24a02a5d59e52e?s=96&amp;d=http%3A%2F%2F0.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96" medium="image">
			<media:title type="html">Romain</media:title>
		</media:content>
	<feedburner:origLink>http://codingly.com/2008/12/29/degage-sale-programmeur/</feedburner:origLink></item>
		<item>
		<title>Cecil.Decompiler : Un décompilateur .NET OpenSource</title>
		<link>http://feedproxy.google.com/~r/Codingly/~3/ZOGtdt8U7nA/</link>
		<comments>http://codingly.com/2008/12/16/cecildecompiler-un-decompilateur-net-opensource/#comments</comments>
		<pubDate>Tue, 16 Dec 2008 22:23:30 +0000</pubDate>
		<dc:creator>Romain Verdier</dc:creator>
				<category><![CDATA[Posts]]></category>
		<category><![CDATA[.NET]]></category>
		<category><![CDATA[Annonce]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[Cecil.Decompiler]]></category>
		<category><![CDATA[Expression Tree]]></category>

		<guid isPermaLink="false">http://codingly.com/?p=450</guid>
		<description><![CDATA[Jean-Baptiste Evain vient de l&#8217;annoncer sur son blog : il travaille actuellement sur un nouveau projet particulièrement ambitieux appelé Cecil.Decompiler. Comme son nom l&#8217;indique, il s&#8217;agit d&#8217;un décompilateur .NET basé sur Mono.Cecil (du même auteur) qui permettait déjà de manipuler le langage intermédiaire du CLR.
Quelques jours avant l&#8217;annonce officielle, Jb a organisé un Code Camp [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=codingly.com&blog=3510695&post=450&subd=romainverdier&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p>Jean-Baptiste Evain <a href="http://evain.net/blog/articles/2008/12/15/cecil-decompiler">vient de l&#8217;annoncer</a> sur son blog : il travaille actuellement sur un nouveau projet particulièrement ambitieux appelé Cecil.Decompiler. Comme son nom l&#8217;indique, il s&#8217;agit d&#8217;un décompilateur .NET basé sur <a href="http://www.mono-project.com/Cecil">Mono.Cecil</a> (du même auteur) qui permettait déjà de manipuler le langage intermédiaire du CLR.</p>
<p>Quelques jours avant l&#8217;annonce officielle, Jb a organisé un <a href="http://evain.net/blog/articles/2008/12/16/decompiler-codecamp">Code Camp</a> en Ardèche (près de Lyon) en invitant quelques personnes à travailler avec lui sur ce decompiler. L&#8217;idée était avant tout de passer un bon moment, de <strike>faire avancer</strike> découvrir le projet, mais aussi d&#8217;intéresser et d&#8217;encourager d&#8217;éventuels futurs contributeurs à rejoindre l&#8217;initiative.</p>
<p>Comme j&#8217;ai eu la chance de faire partie des petits privilégiés, je vais essayer de vous livrer mes impressions à chaud.<br />
<span id="more-450"></span><br />
Déjà, belle surprise en recevant le mail d&#8217;invitation de Jb&#8230; Nous ne nous étions croisé qu&#8217;une soirée, à Paris, lorsqu&#8217;il était <a href="http://codingly.com/2008/11/05/altnet-en-france-mono-a-paris-pour-la-7eme-rencontre/">venu présenter Mono</a> en novembre pour une de nos réunions ALT.NET. Dans un milieu où le copinage reste bien présent, ce genre de proposition dénote bien une certaine ouverture d&#8217;esprit, et un fort degré de coolitude. Merci. <a href="http://strangelights.com/blog/">Robert Pickering</a> faisait aussi partie des invités mais à part lui (et Jb, donc) je ne connaissais personne. Ce fut l&#8217;occasion de faire la connaissance de <a href="http://patricelamarche.net/">Patrice Lamarche</a>, <a href="http://batswirl.com/">Mathieu Szablowski</a>, <a href="http://evilznet.com/">Vincent Bourdon</a>, et <a href="http://sebastien.lebreton.free.fr/blog/">Sébastien Lebreton</a> (auteur de réflexil). Sept personnes en tout ; soit un petit comité.</p>
<p><img src="http://romainverdier.files.wordpress.com/2008/12/codecamp2.jpg?w=715&#038;h=405" alt="codecamp2" title="codecamp2" width="715" height="405" class="alignnone size-full wp-image-462" /></p>
<p>Je vous avouerai que j&#8217;étais un peu impressionné à l&#8217;idée de devoir rejoindre tout ce beau monde pour travailler sur un projet de cette envergure, dont la complexité moyenne dépasse quand même celle d&#8217;une application de gestion classique&#8230; Mais l&#8217;ambiance était excellente d&#8217;une part, et le sujet carrément intéressant d&#8217;autre part.</p>
<p>Ca ne suffit pas pour faire oublier qu&#8217;on est en train de faire du pair programming avec un mec de l&#8217;équipe Mono, mais ça aide un peu. En tout cas, ça fait vraiment plaisir de participer à un projet aussi motivant, avec des gens dont la simple proximité rend moins con. J&#8217;aurais aimé pouvoir travailler en pair avec tout le monde, mais j&#8217;ai principalement codé avec Jb et Rob. Et tout seul aussi, hein. Je n&#8217;ai pas envie de rentrer dans les détails techniques aujourd&#8217;hui, mais en gros, j&#8217;ai principalement travaillé sur la partie &#8220;décompilation C#&#8221;, et plus particulièrement sur les étapes de transformation de l&#8217;arbre syntaxique visant à faire apparaitre les structures de haut niveau du langage.</p>
<p>Le decompiler lit le code intermédiaire, en infère un <a href="http://en.wikipedia.org/wiki/Control_flow_graph">Control Flow Graph</a>, puis un <a href="http://en.wikipedia.org/wiki/Abstract_syntax_tree">AST</a> assez brut dans lequel, par exemple, toutes les pre/post-tested loops sont modélisées sous la forme de statements while/do-while. Selon le langage, et selon la version du langage, il faudra ensuite exécuter une série d&#8217;analyses et de transformations sur cet arbre afin de reconnaitre les constructions spécifiques. Par exemple, et <em>au hasard</em>, le foreach.</p>
<p>Dans un <a href="http://codingly.com/2008/04/28/le-mot-cle-yield-et-les-iterateurs-en-c/">vieux post</a>, j&#8217;expliquais que le foreach en C# était syntaxiquement équivalent à :</p>
<pre name="code" class="csharp">

IEnumerator&lt;Jambon&gt; enumerator = jambons.GetEnumerator();
try
{
	while( enumerator.MoveNext())
	{
		Jambon jambon = enumerator.Current;
		// Manger le jambon, miam, etc.
	}
}
finally
{
	IDisposable disposableEnumerator = enumerator as IDisposable;
	if(disposableEnumerator != null)
	{
		disposableEnumerator.Dispose();
	}
}
</pre>
<p>C&#8217;est donc le pattern qu&#8217;il faut identifier dans l&#8217;arbre, à quelques subtilités près. Ca m&#8217;a pris 3 bons jours, et c&#8217;est loin d&#8217;être terminé si on veut gérer tous les edge cases, allez donc savoir pourquoi. J&#8217;ai aussi travaillé avec Jb sur une implémentation sympa d&#8217;un &#8220;pattern matching du pauvre&#8221; en C#, joyeusement supprimée depuis&#8230; On cherche quelque chose de mieux. Mais ça permettait d&#8217;écrire des trucs rigolos du genre :</p>
<pre name="code" class="csharp">

// Création du pattern
var matcher = Pattern.Match&lt;Expression&gt;()
					 .Is&lt;MethodInvocationExpression&gt;()
                     .Select(mie =&gt; mie.Method)
                     .Is&lt;MethodReferenceExpression&gt;()
                     .Tag(() =&gt; method_key, mre =&gt; mre.Method)
                     .Tag(() =&gt; target_key, mre =&gt; mre.Target);

// Compilation du pattern matcher pour récupérer un delegate qui pourra être mis en cache
// et invoqué avec de bonnes performances
var methodInvocationMatcher = matcher.Compile&lt;Func&lt;MatchResult, Expression, bool&gt;&gt; ();

// Exécution du pattern matching : on obtient un MatchResult
var result = Pattern.Run (MethodInvocationMatcher, expression);

// On peut maintenant, en cas de succès, travailler avec les valeurs qui ont été tagguée
// lors du pattern matching, si elles ont été trouvées
if (result.Success)
{
	Expression targetExpression;
    if (result.TryGetValue(target_key, out targetExpression))
    {
		// ...
	}

	MethodReference methodReference;
	if (result.TryGetValue(method_key, out methodReference))
	{
		// ...
	}
}
</pre>
<p>Le code du matcher pouvait être généré dynamiquement via <code>System.Reflection.Emit</code>, puis compilé pour obtenir un delegate capable d&#8217;être exécuté sans ruiner les perfs. Ca peut <a href="http://codingly.com/2008/05/06/continuer-loptimisation-avec-la-lightweight-code-generation-lcg/">vous rappeler quelque chose</a>&#8230; mais l&#8217;idée n&#8217;était pas de moi !</p>
<p>J&#8217;ai également eu l&#8217;opportunité de travailler avec Rob pour réaliser une version F# du matcher capable de détecter les foreach à titre d&#8217;essai. Pas vraiment l&#8217;initiation idéale à F# pour un profane comme moi, mais heureusement Rob a gardé le clavier durant la session. Ce fut pour moi l&#8217;occasion d&#8217;avoir un bon aperçu de la puissance du langage en matière de pattern matching et de tester rapidement pour la première fois l&#8217;intérop C#/F#.</p>
<p><img src="http://romainverdier.files.wordpress.com/2008/12/codecamp1.jpg?w=358&#038;h=246" alt="codecamp1" title="codecamp1" width="358" height="246" class="alignright size-full wp-image-463" /><br />
Le projet en lui-même est à mon sens prometteur. Ce n&#8217;est pas juste un Reflector-bis. Il s&#8217;agit d&#8217;un framework de décompilation, libre et open source, qui peut être embarqué n&#8217;importe où. Ca ouvre pas mal de perspectives pour ceux qui travaillent sur des outils d&#8217;analyse statique de code par exemple. Jason Bock, auteur de CIL Programming avec lequel j&#8217;ai été méchant par le passé, va même jusqu&#8217;à trouver <a href="http://www.jasonbock.net/JB/Default.aspx?blog=entry.850a91e9249c4d388f1ca4a3e64dfed4">Cecil.Decompiler et sa licence MIT/X11 rassurants</a> dans la mesure où la visibilité sur le devenir de Reflector est compromise.</p>
<p>Je ne suis pas sûr de vouloir crier hourra pour ça, mais ce dont je suis sûr, c&#8217;est que pouvoir disposer d&#8217;un décompilateur .NET open source, managé, qui repose sur une base solide, c&#8217;est tout bon. Si on considère en plus que Sébastien est déjà lancé à fond sur la réalisation d&#8217;une interface pour exploiter Cecil.Decompiler, dont le modèle d&#8217;extensibilité devrait être plus souple que celui de Reflector, c&#8217;est encore plus alléchant.</p>
<p>Quoi qu&#8217;il en soit, le decompiler en est à ses débuts. Il reste vraiment beaucoup de choses à faire, et ce à plusieurs niveaux :</p>
<ul>
<li>Core</li>
<li>Support des langages : C#, VB, F#, etc.</li>
<li>Interface, plugins</li>
</ul>
<p>Mais au moins, vous savez à présent que le projet existe.</p>
Posted in Posts Tagged: .NET, Annonce, C#, Cecil.Decompiler, Expression Tree <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/romainverdier.wordpress.com/450/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/romainverdier.wordpress.com/450/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/romainverdier.wordpress.com/450/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/romainverdier.wordpress.com/450/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/romainverdier.wordpress.com/450/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/romainverdier.wordpress.com/450/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/romainverdier.wordpress.com/450/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/romainverdier.wordpress.com/450/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/romainverdier.wordpress.com/450/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/romainverdier.wordpress.com/450/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=codingly.com&blog=3510695&post=450&subd=romainverdier&ref=&feed=1" /></div><img src="http://feeds.feedburner.com/~r/Codingly/~4/ZOGtdt8U7nA" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://codingly.com/2008/12/16/cecildecompiler-un-decompilateur-net-opensource/feed/</wfw:commentRss>
		<slash:comments>20</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/cb0ee4bde49708f4be24a02a5d59e52e?s=96&amp;d=http%3A%2F%2F0.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96" medium="image">
			<media:title type="html">Romain</media:title>
		</media:content>

		<media:content url="http://romainverdier.files.wordpress.com/2008/12/codecamp2.jpg" medium="image">
			<media:title type="html">codecamp2</media:title>
		</media:content>

		<media:content url="http://romainverdier.files.wordpress.com/2008/12/codecamp1.jpg" medium="image">
			<media:title type="html">codecamp1</media:title>
		</media:content>
	<feedburner:origLink>http://codingly.com/2008/12/16/cecildecompiler-un-decompilateur-net-opensource/</feedburner:origLink></item>
		<item>
		<title>Le futur de C# ?</title>
		<link>http://feedproxy.google.com/~r/Codingly/~3/NSmbZOEy8NA/</link>
		<comments>http://codingly.com/2008/11/15/le-futur-de-c/#comments</comments>
		<pubDate>Sat, 15 Nov 2008 15:34:03 +0000</pubDate>
		<dc:creator>Romain Verdier</dc:creator>
				<category><![CDATA[Posts]]></category>
		<category><![CDATA[.NET]]></category>
		<category><![CDATA[C#]]></category>

		<guid isPermaLink="false">http://romainverdier.wordpress.com/?p=356</guid>
		<description><![CDATA[Le problème de la PDC, quand on y est pas et qu&#8217;on est curieux, c&#8217;est qu&#8217;il faut attendre les vidéos des sessions pour savoir ce qui s&#8217;est vraiment passé. Symptôme de naïveté : croire qu&#8217;on pourra s&#8217;en sortir grâce à la blogosphère. Sérieusement, et je reste sur l&#8217;exemple spécifique de C# 4.0, 80% des billets [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=codingly.com&blog=3510695&post=356&subd=romainverdier&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p>Le problème de la <a href="http://www.microsoftpdc.com/">PDC</a>, quand on y est pas et qu&#8217;on est curieux, c&#8217;est qu&#8217;il faut attendre les vidéos des sessions pour savoir ce qui s&#8217;est <em>vraiment</em> passé. Symptôme de naïveté : croire qu&#8217;on pourra s&#8217;en sortir grâce à la blogosphère. Sérieusement, et je reste sur l&#8217;exemple spécifique de C# 4.0, 80% des billets qui sont sortis jusqu&#8217;à présent à ce sujet ont simplement contribué à rendre l&#8217;écho plus pénible. Un peu partout on peut tomber sur des réactions constructives du genre :</p>
<blockquote><p>The dynamic keyword is going be abused so much&#8230; C# is on its way to becoming PHP.</p></blockquote>
<p><span id="more-356"></span><br />
J&#8217;aurais carrément ajouté un &#8220;lol&#8221; à la place du point, moi. Difficile dans ces conditions de comprendre de quoi est fait C# 4.0, difficile d&#8217;anticiper à quoi pourront ressembler les prochaines versions. Pourtant, et c&#8217;est où je veux en venir, Anders Hejlsberg a été particulièrement clair dans <a href="http://channel9.msdn.com/pdc2008/TL16/">sa présentation</a>. Il a parlé du <em>langage C#</em>. Il a exposé sa vision, celle de l&#8217;équipe de conception du langage. Je vous invite donc tous à voir sa session si ce n&#8217;est déjà fait, en prenant bien soin de ne pas zapper l&#8217;introduction.</p>
<p>C# est né avec et pour la plateforme .NET. On peut être surpris de se faire rappeler que ça fait 8 ans qu&#8217;il a été annoncé pour la première fois, et presque 10 ans que sa conception a commencé. Pourtant, si on met de côté les spécificités héritées de la plateforme .NET elle-même, c&#8217;est un langage dont le vrai caractère n&#8217;a commencé à s&#8217;affirmer qu&#8217;à partir de la version 3.0, avec laquelle sont apparus, entres autres, les expressions lambda, les arbres syntaxiques, les méthodes d&#8217;extension, ou Linq &#8211; ce dernier reposant d&#8217;ailleurs essentiellement sur les précédentes features.</p>
<p>On a un peu tout vu et entendu à leur sujet : de la critique violente à l&#8217;apologie extatique. Pourtant, on ne parle que d&#8217;un langage de programmation. Il y a souvent plusieurs raisons de critiquer un langage, et bien évidemment, toutes ne se valent pas. Essayer de discuter les choix des concepteurs quant à l&#8217;implémentation de telle ou telle feature, pourquoi pas :</p>
<blockquote><p>Ouais, mais tu vois, ça ils auraient dû le descendre au niveau du CLR au lieu de laisser le compilo interpréter des attributs pourris</p></blockquote>
<p>Quoique déjà, il vaut mieux ne pas s&#8217;appeler Romain Verdier et avoir réfléchi un peu plus de 3 minutes à la pause café. Car remettre en cause aussi légèrement les décisions prises par une équipe qui ne ressemble pas exactement à un groupe de singes, ça revient à parler pour parler.</p>
<p>Attention, tout le monde peut avoir un avis, et l&#8217;équipe d&#8217;Anders n&#8217;est probablement pas infaillible. ce n&#8217;est pas parce qu&#8217;on ne sait pas peindre qu&#8217;on est obligé d&#8217;aimer tous les tableaux, hein. Je suis simplement bien placé pour savoir que les opinions-réflexes sont parfois assez dures à réfréner, et rarement pertinentes.</p>
<p>Bref, ne critiquez plus jamais C#, OK ?</p>
<p><strong>OKAY ?</strong></p>
<p>Hihi. Non, j&#8217;ai surtout envie d&#8217;insister sur un point précis, ou sur une critique particulière, celle qui consiste à regretter ouvertement l&#8217;extension du &#8220;périmètre C#&#8221;, si possible avec condescendance. Critiquer un langage parce qu&#8217;il mêle différents concepts, parce qu&#8217;il s&#8217;enrichit et se diversifie en introduisant des fonctionnalités que l&#8217;on peut difficilement classifier ; ça n&#8217;a pas vraiment de sens pour moi.</p>
<p>Aujourd&#8217;hui, on peut considérer que C#, à l&#8217;instar d&#8217;autres langages, est un <a href="http://en.wikipedia.org/wiki/Multi-paradigm_programming_language">langage multi-paradigmes</a> :</p>
<ul>
<li>Impératif</li>
<li>Orienté objet</li>
<li>Générique</li>
<li>(Fonctionnel)</li>
<li>(Dynamique)</li>
</ul>
<p>Et, à la différence d&#8217;autres langages, il évolue très vite.</p>
<p>Je me permets de citer <a href="http://blogs.msdn.com/ericlippert/">Eric Lippert</a> :</p>
<blockquote><p><strong>The techniques are not good in of themselves, they&#8217;re good because they&#8217;re practical.</strong></p>
<p>Perhaps surprisingly, our goal in making C# is not <strong>to make an object-oriented language. Our goal is to make a compelling and practical language for general-purpose application development on our platforms, and thereby enable our customers to be successful</strong>. Making an object-oriented language called C# is just a means to that end, not an end in of itself.</p></blockquote>
<p>Le paragraphe est tiré de <a href="http://blogs.msdn.com/ericlippert/archive/2008/10/28/the-future-of-c-part-two.aspx">son article en plusieurs parties</a> au sujet du futur de C#. (Je vous invite à le lire, évidemment.) Il y explique assez bien que le but du langage est d&#8217;être un langage pratique, puissant, efficace. Et si les méthodes d&#8217;extension rendent Linq possible, alors, <em>même si elles n&#8217;ont rien à voir avec l&#8217;OOP</em>, il serait peut-être bon de les ajouter au langage. De même, si l&#8217;inclusion du DLR dans .NET 4 et son exploitation à partir de C# via le mot clé <code>dynamic</code> permet de rendre l&#8217;interopérabilité entre C# et les langages dynamiques possible et même <em>facile</em>, alors ce n&#8217;est probablement pas complètement con. Python, Ruby, Javascript, COM, etc. Ce n&#8217;est pas comme si l&#8217;essence même du langage changeait pour que ce dernier supporte nativement, heu, le parsing des fichiers CSV par exemple.</p>
<p><a href="http://www.wiltamuth.com/blog/shipparty/"><img src="http://romainverdier.files.wordpress.com/2008/11/andershasaustinpowers.jpg?w=217&#038;h=320" alt="anders hejlsberg as austin powers" title="andershasaustinpowers" width="217" height="320" class="border-image alignright size-full wp-image-441" /></a>Il y a aussi les alarmistes, qui pensent tout de suite que telle ou telle fonctionnalité, potentiellement <em>dangereuse</em> va être détournée. Les mauvais programmeurs vont en abuser et rendre la vie des bons programmeurs (ceux qui passent leur temps à corriger et maintenir le travail d&#8217;autrui) insupportable. Perso, je préfère reprendre un projet .NET 2.0 de 200K LOC, plutôt qu&#8217;un projet .NET 1.1 de 50K LOC. Et il y a fort à parier pour qu&#8217;en 2010, je préfère maintenir une solution .NET 4.0 plutôt qu&#8217;une solution .NET 2.0. L&#8217;inférence de type et les méthodes d&#8217;extensions faisaient peur en C# 3.0, mais je me demande dans quelle mesure on en a abusé dans les projets-du-monde-réel. Je n&#8217;ai pas assez d&#8217;éléments pour juger &#8211; vos retours d&#8217;expérience m&#8217;intéressent &#8211; mais je vais quand même y aller de mon pronostic : les exagérations doivent être minoritaires. En ce qui concerne le late-binding en C# 4.0, pour prendre un exemple plus récent, je ne vois pas qui serait prêt à perdre le confort de la complétion et du typage statique pour utiliser le mot clé <code>dynamic</code> sans raison. Mais peut-être me trompè-je ; nous verrons bien.</p>
<p>Quoi qu&#8217;il en soit, il est selon moi important de prendre un peu de recul. Le langage est un outil, un moyen. Il fut un temps où la meilleure façon d&#8217;arriver à de se faire tabasser dans la rue consistait à porter un t-shirt &#8220;I love JavaScript&#8221;. De nos jours, c&#8217;est devenu le meilleur moyen de choper. On se demande bien pourquoi&#8230;</p>
<p>Je crois qu&#8217;il faut vraiment voir ça comme un enrichissement du langage. Je ne parle pas des t-shirts, mais de l&#8217;apparition de toutes ces fonctionnalités a priori éloignées du couple OO/Imperative Programming dans un langage à accolades. Que penser alors de la possible promotion accordée à la métaprogrammation pour C# 5.0 ? OK, ce n&#8217;est pas nouveau et dans une certaine mesure il est déjà possible d&#8217;y recourir maintenant, mais exposer le &#8220;compiler as a service&#8221; comme l&#8217;a laissé entendre Anders à la fin de son talk, c&#8217;est un choix non-orthodoxe, et un peu plus ambitieux. Le ton semble avoir été donné : C# va probablement se décomplexer de plus en plus et surprendre encore en offrant ce que d&#8217;autres langages plus rigides s&#8217;interdiraient d&#8217;offrir. C&#8217;est en tout cas mon sentiment.</p>
<p>Jusqu&#8217;à présent, j&#8217;ai eu l&#8217;impression qu&#8217;à chaque nouvelle version du langage les évolutions s&#8217;inscrivaient avec une certaine cohérence dans ce qui semble être une vision pragmatique de C# et de la plateforme .NET. Au risque de paraitre complètement vendu, je n&#8217;ai pour l&#8217;instant pas été sérieusement contrarié ou déçu dans l&#8217;histoire C#.</p>
<p>Parmi ceux qui pouvaient crier au scandale en découvrant les expressions lambda ou Linq lors de la sortie de C# 3.0, j&#8217;aimerais bien avoir les noms de ceux qui ne peuvent plus s&#8217;en passer aujourd&#8217;hui, et qui commencent déjà à crier au scandale en voyant poindre le duck typing&#8230;</p>
Posted in Posts Tagged: .NET, C# <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/romainverdier.wordpress.com/356/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/romainverdier.wordpress.com/356/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/romainverdier.wordpress.com/356/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/romainverdier.wordpress.com/356/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/romainverdier.wordpress.com/356/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/romainverdier.wordpress.com/356/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/romainverdier.wordpress.com/356/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/romainverdier.wordpress.com/356/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/romainverdier.wordpress.com/356/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/romainverdier.wordpress.com/356/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=codingly.com&blog=3510695&post=356&subd=romainverdier&ref=&feed=1" /></div><img src="http://feeds.feedburner.com/~r/Codingly/~4/NSmbZOEy8NA" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://codingly.com/2008/11/15/le-futur-de-c/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/cb0ee4bde49708f4be24a02a5d59e52e?s=96&amp;d=http%3A%2F%2F0.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96" medium="image">
			<media:title type="html">Romain</media:title>
		</media:content>

		<media:content url="http://romainverdier.files.wordpress.com/2008/11/andershasaustinpowers.jpg" medium="image">
			<media:title type="html">andershasaustinpowers</media:title>
		</media:content>
	<feedburner:origLink>http://codingly.com/2008/11/15/le-futur-de-c/</feedburner:origLink></item>
		<item>
		<title>Introduction à Mono.Cecil : Implémenter INotifyPropertyChanged</title>
		<link>http://feedproxy.google.com/~r/Codingly/~3/-EN8I5Dk-kw/</link>
		<comments>http://codingly.com/2008/11/10/introduction-a-monocecil-implementer-inotifypropertychanged/#comments</comments>
		<pubDate>Mon, 10 Nov 2008 19:20:09 +0000</pubDate>
		<dc:creator>Romain Verdier</dc:creator>
				<category><![CDATA[Articles]]></category>
		<category><![CDATA[.NET]]></category>
		<category><![CDATA[AOP]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[Cecil]]></category>
		<category><![CDATA[CIL]]></category>

		<guid isPermaLink="false">http://romainverdier.wordpress.com/?p=379</guid>
		<description><![CDATA[Vous allez probablement m&#8217;en vouloir à force, mais j&#8217;ai décidé de continuer mes expériences autour d&#8217;INotifyPropertyChanged. Cette fois-ci, en utilisant Mono.Cecil pour faire un peu d&#8217;IL rewriting. Où comment tisser un aspect sans utiliser de framework AOP. Comparée à celle basée sur PostSharp.Laos, cette solution a un inconvénient majeur : elle est plus roots.
En revanche, [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=codingly.com&blog=3510695&post=379&subd=romainverdier&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p>Vous allez probablement m&#8217;en vouloir à force, mais j&#8217;ai décidé de continuer mes expériences autour d&#8217;<code>INotifyPropertyChanged</code>. Cette fois-ci, en utilisant <a href="http://www.mono-project.com/Cecil">Mono.Cecil</a> pour faire un peu d&#8217;IL rewriting. Où comment tisser un aspect sans utiliser de framework AOP. Comparée à celle basée sur <a href="http://www.postsharp.org/about/architecture/">PostSharp.Laos</a>, cette solution a un inconvénient majeur : elle est plus roots.</p>
<p>En revanche, aucune autre méthode à ma connaissance ne permet d&#8217;obtenir un tissage aussi fin. Par fin, j&#8217;entends spécifique, propre, non pollué par le code que génèrent les outils d&#8217;AOP classiques pour supporter les mécanismes d&#8217;interception. Donc les performances seront à la clé puisqu&#8217;une fois l&#8217;assembly retravaillé avec Cecil, il ne sera plus possible de faire la différence entre son code IL et celui qui aurait été généré si nous avions implémenté <code>INotifyPropertyChanged</code> à la main. Le développement aura juste été un peu plus cher&#8230;</p>
<p><span id="more-379"></span></p>
<p>Même si la plupart du temps vous préfèrerez sans doute bénéficier de l&#8217;abstraction offerte par les outils d&#8217;AOP classiques, vous trouverez peut-être excitant de jouer avec Cecil pour déveloper des aspects bas niveau en mettant les mains dans le camboui. (Vous pouvez aussi trouver ça naze au point d&#8217;en bailler, hein.)</p>
<p>Bref, ce post va plus ressembler à un article sur Cecil qu&#8217;à un article sur <code>INotifyPropertyChanged</code>. Il y aura probablement deux parties, mais ce n&#8217;est pas une promesse :</p>
<ul>
<li>Part 1 : première version d&#8217;un <em>transformer</em> utilisant Cecil pour implémenter <code>INotifyPropertyChanged</code> (cet article)</li>
<li>Part 2 : version améliorée du <em>transformer</em> lançant l&#8217;évènement de notification uniquement lorsque la valeur affectée à la propriété est différente</li>
</ul>
<p>Eventuellement, je fournirai quelques pistes pour lancer automatiquement ce genre de transformations en post-build dans la seconde partie, si seconde partie il y a.</p>
<p>Mais commençons par le commencement, en prenant pour victime la <code>Person</code> des articles précédents. Le but est de pouvoir écrire :</p>
<pre name="code" class="csharp">

	[NotifyPropertyChanged]
	public class Person
	{
		private string name;

		public string Name
		{
			get { return this.name; }
			set { this.name = value; }
		}
	}
</pre>
<p>et d&#8217;obtenir au final une classe <code>Person</code> implémentant <code>INotifyPropertyChanged</code> et capable donc de notifier par l&#8217;événement <code>PropertyChanged</code> les changements de ses propriétés.</p>
<p>Cecil permet de charger un assembly, de l&#8217;inspecter et de le modifier éventuellement avant de le sauvegarder, de le copier, etc. L&#8217;idée consiste donc à :</p>
<ol>
<li>Compiler le code ci-dessus normalement, afin d&#8217;obtenir un assembly</li>
<li>Lancer un transformer, qui utilise Cecil afin de charger cet assembly</li>
<li>Modifier l&#8217;assembly, toujours avec Cecil, pour y injecter l&#8217;implémentation d&#8217;<code>INotifyPropertyChanged</code> en manipulant le code CIL.</li>
<li>Sauvegarder l&#8217;assembly modifié</li>
</ol>
<h3>Le transformer</h3>
<p>Dans cette première version, imaginons quelque chose de naïf : un programme en ligne de commande, qui prend en argument le chemin de l&#8217;assembly à instrumenter :</p>
<pre name="code" class="csharp">

    private static void Main(string[] args)
    {
        if (args.Length == 0)
        {
            Console.WriteLine(&quot;Usage: transformer &lt;assembly file&gt;&quot;);
            return;
        }
        new Transformer(path).Run();
    }
</pre>
<p>D&#8217;ailleurs, je vais continuer à être naïf en laissant de côté la gestion du logging, des exceptions, etc. Les snippets présentés ici n&#8217;en seront que plus lisibles, à défaut d&#8217;être solides.</p>
<p>Commençons par une vue d&#8217;ensemble des étapes nécessaires à la transformation des assemblies, que nous détaillerons ensuite. (Vous aimez les opcodes ?)</p>
<ol>
<li>Chargement de l&#8217;assembly à instrumenter</li>
<li>Identification des types à modifier : on recherche ceux qui sont taggés par notre attribut <code>[NotifyPropertyChanged]</code></li>
<li>Transformation de chacun de ces types pour leur faire supporter <code>INotifyPropertyChanged</code></li>
<li>Sauvegarde de l&#8217;assembly modifié</li>
</ol>
<p>Le schéma ci-dessous met en avant les différentes étapes de la transformation :<br />
<img src="http://romainverdier.files.wordpress.com/2008/11/transformer.jpg?w=664&#038;h=609" alt="transformer" title="transformer" width="664" height="609" class="alignnone size-full wp-image-393" /></p>
<ul>
<li>[#1] Implémentation proprement dite de l&#8217;interface <code>INotifyPropertyChanged</code></li>
<li>[#2] Ajout d&#8217;une fonction &#8220;helper&#8221; pour le déclenchement de l&#8217;évènement <code>PropertyChanged</code></li>
<li>[#3] Instrumentation des setters, en utilisant la méthode précédente pour lancer les notifications</li>
</ul>
<p>Voyons comment implémenter ça. Rappelez-vous, tout commence par :</p>
<pre name="code" class="csharp">

	new Transformer(path).Run();
</pre>
<p>Le constructeur (qui en fait sans doute un peu trop) :</p>
<pre name="code" class="csharp">

public Transformer(string assemblyPath)
{
    this.assemblyPath = assemblyPath;
    this.assembly = AssemblyFactory.GetAssembly(assemblyPath);
    this.assembly.MainModule.LoadSymbols();
    this.assembly.MainModule.FullLoad();
}
</pre>
<p>Assez trivial : on laisse tout le travail à Cecil. Son <code>AssemblyFactory</code> nous permet de récupérer la définition de l&#8217;assembly à modifier. Afin de conserver les sequence points et permettre de debuguer l&#8217;assembly modifiée, on charge les infos de debug. L&#8217;appel à la méthode <code>FullLoad</code> permet de charger en mémoire toute la représentation du module principal, afin de pouvoir la modifier par la suite.</p>
<p><strong>Petite parenthèse introductive</strong> : Plusieurs fois, dans les méthodes que je vais présenter par la suite, on aura besoin de récupérer une <code>TypeReference</code>, à partir d&#8217;un <code>Type</code>. Lorsque ce sera le cas, on utilisera une des deux méthodes suivantes :</p>
<pre name="code" class="csharp">

private TypeReference GetReference(Type type)
{
    TypeReference typeReference = this.assembly.MainModule.TypeReferences[type.FullName]
                                  ?? this.assembly.MainModule.Import(type);
    return typeReference;
}

private TypeReference GetReference&lt;T&gt;()
{
    return GetReference(typeof (T));
}
</pre>
<p>Leur fonctionnement est simple : si on a déjà chargé le type dans le module principal de l&#8217;assembly en cours de modification, on retourne directement la <code>TypeReference</code> correspondante, sinon on importe le type pour créer la référence. Car Cecil fait bien la distinction (qui existe au niveau CIL) entre les <em>définitions</em> et les <em>références</em> pour les différents éléments du code (types, fields, methods, etc.)</p>
<p>Lorsqu&#8217;on veut modifier une méthode, par exemple, on va travailler sur sa définition. Mais si on désire simplement l&#8217;appeler, il nous faut juste sa référence. Ce modèle, plus juste que celui proposé par l&#8217;API de réflexion de la BCL peut sembler troublant au premier abord, mais s&#8217;avère au final plus puissant puisqu&#8217;il colle directement avec les <a href="http://www.ecma-international.org/publications/standards/Ecma-335.htm">spécifications du langage intermédiaire</a>. <strong>Fin de la parenthèse</strong>.</p>
<p>Bien, on a de quoi commencer l&#8217;autopsie du <code>Transformer</code>, dont le nom est plus que douteux&#8230; La méthode <code>Run</code> semble être un point de départ judicieux pour notre analyse :</p>
<pre name="code" class="csharp">

public void Run()
{
    foreach (TypeDefinition type in GetTypesToWeave())
    {
        MethodReference firePropertyChangedMethod = WeaveINotifyPropertyChanged(type);
        WeaveEventTriggers(type, firePropertyChangedMethod);
    }
    this.assembly.MainModule.SaveSymbols();
    AssemblyFactory.SaveAssembly(this.assembly, this.assemblyPath);
}
</pre>
<p>La méthode <code>GetTypesToWeave</code> permet de retourner tous les types à modifier, c&#8217;est à dire ceux qui sont décorés par notre attribut <code>[NotifyPropertyChanged]</code>. Ce dernier devra donc être défini dans un assembly quelconque, référencé à la fois par le code client &#8211; celui qui contient les types à instrumenter &#8211; et par notre transformer. Chacun des types est ensuite transformé par les appels successifs aux méthodes <code>WeaveINotifyPropertyChanged</code> et <code>WeaveEventTriggers</code>.</p>
<p>La sauvegarde des modifications s&#8217;effectue elle aussi en plusieurs étapes :</p>
<ul>
<li>On indique qu&#8217;on souhaite conserver les symboles de debugging</li>
<li>On sauvegarde notre travail en remplaçant l&#8217;assembly original par celui que l&#8217;on vient d&#8217;instrumenter.
</ul>
<p>Jusqu&#8217;ici, tout va bien, comme qui dirait. Mais creusons un peu plus. Tout d&#8217;abord, le code de la méthode <code>GetTypesToWeave</code> qui nous permet de retourner les types de l&#8217;assembly à modifier. Il s&#8217;agit essentiellement d&#8217;alléger la méthode <code>Run</code> en évitant les imbrications et en isolant la logique de recherche dans une autre méthode :</p>
<pre name="code" class="csharp">

private IEnumerable&lt;TypeDefinition&gt; GetTypesToWeave()
{
    string attributeFullName = typeof (NotifyPropertyChangedAttribute).FullName;
    foreach (TypeDefinition type in this.assembly.MainModule.Types)
    {
        foreach (CustomAttribute attribute in type.CustomAttributes)
        {
            if (attribute.Constructor.DeclaringType.FullName == attributeFullName)
            {
                yield return type;
                break;
            }
        }
    }
}
</pre>
<p>Notez qu&#8217;on utilise pour cela un bloc itérateur. Le reste pourrait se passer de commentaire : on retourne les types marqués par l&#8217;attribut <code>[NotifyPropertyChanged]</code> en basant la recherche sur le fullname des attributs.</p>
<p>Passons maintenant à la modification des types. Rappelez-vous, il y a deux étapes principales :</p>
<ul>
<li>Implémentation de <code>INotifyPropertyChanged</code> (méthode <code>WeaveINotifyPropertyChanged</code>)</li>
<li>Instrumentation des setters (méthode <code>WeaveEventTriggers</code>)</li>
</ul>
<h3>Implémentation de <code>INotifyPropertyChanged</code></h3>
<p>L&#8217;implémentation proprement dite de <code>INotifyPropertyChanged</code> est une tâche que l&#8217;on peut aisément redécomposer. Cette redécomposition est d&#8217;ailleurs assez visible dans la méthode <code>WeaveINotifyPropertyChanged</code> que je propose :</p>
<pre name="code" class="csharp">

private MethodReference WeaveINotifyPropertyChanged(TypeDefinition type)
{
    TypeReference iNotifyPropertyChangedType = GetReference&lt;INotifyPropertyChanged&gt;();
    type.Interfaces.Add(iNotifyPropertyChangedType);
    FieldReference eventField = WeaveEvent(type);

    return WeaveEventFiringHelper(eventField, type);
}
</pre>
<p>La première étape consiste à récupérer une <code>TypeReference</code> correspondant à cette interface pour l&#8217;ajouter à la liste des interfaces du type que l&#8217;on modifie. Simple, mais insuffisant : il faut également <em>implémenter</em> l&#8217;interface. Dans le cas d&#8217;<code>INotifyPropertyChanged</code>, on doit ajouter un évènement public <code>PropertyChanged</code> au type. C&#8217;est la méthode <code>WeaveEvent</code> qui s&#8217;en chargera. (Etape [#1] du schéma)</p>
<p>La méthode <code>WeaveEventFiringHelper</code>, quant à elle, permet d&#8217;ajouter une méthode <code>FirePropertyChanged</code> au type. Quelque chose équivalent à :</p>
<pre name="code" class="csharp">

    private void FirePropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
</pre>
<p>C&#8217;est l&#8217;étape [#2] de la transformation, également signalée dans le schéma précédent. La référence vers cette méthode est retournée pour permettre son appel plus tard à partir des setters des propriétés. </p>
<p>Dès que vous aurez terminé de bailler, nous détaillerons la première étape qui consiste à ajouter l&#8217;évènement <code>PropertyChanged</code> au type. Soit la méthode <code>WeaveEvent</code> :</p>
<pre name="code" class="csharp">

private FieldReference WeaveEvent(TypeDefinition type)
{
    TypeReference eventHandlerTypeRef = GetReference&lt;PropertyChangedEventHandler&gt;();
    MethodReference combineMethodRef = this.assembly.MainModule.Import(combineMethodBase);
    MethodReference removeMethodRef = this.assembly.MainModule.Import(removeMethodBase);
    const string eventName = &quot;PropertyChanged&quot;;

    FieldDefinition eventField = new FieldDefinition(&quot;PropertyChanged&quot;,
                                                     eventHandlerTypeRef,
                                                     FieldAttributes.Private);
    type.Fields.Add(eventField);

    EventDefinition eventDefinition = new EventDefinition(eventName,
                                                          eventHandlerTypeRef,
                                                          0);

    eventDefinition.AddMethod = CreateEventMethod(string.Format(&quot;add_{0}&quot;, eventName),
                                                  combineMethodRef,
                                                  eventField);

    eventDefinition.RemoveMethod = CreateEventMethod(string.Format(&quot;remove_{0}&quot;, eventName),
                                                     removeMethodRef,
                                                     eventField);

    type.Methods.Add(eventDefinition.AddMethod);
    type.Methods.Add(eventDefinition.RemoveMethod);
    type.Events.Add(eventDefinition);

    return eventField;
}
</pre>
<p>Le layout n&#8217;est pas terrible, j&#8217;espère que vous ne m&#8217;en tiendrez pas rigueur.</p>
<p>Petit rappel : Lorsqu&#8217;on est au niveau CIL, on a une bonne visibilité sur ce qu&#8217;un langage de plus haut niveau comme C# peut nous cacher. Les évènements constituent un bon exemple. En C#, la déclaration d&#8217;un event est simple :</p>
<pre name="code" class="csharp">

public event PropertyChangedEventHandler PropertyChanged;
</pre>
<p>Au niveau IL, le compilateur C# va en fait générer un champ privé encapsulé par une propriété un peu spéciale de type <code>event</code> qui possède les méthodes &#8220;<code>add</code>&#8221; et &#8220;<code>remove</code>&#8220;. Note : même si ce n&#8217;est pas souvent utilisé, sachez qu&#8217;à partir de C# il est possible de <a href="http://msdn.microsoft.com/en-us/library/aa664650(VS.71).aspx">faire apparaitre ces méthodes</a> pour éventuellement intercepter les abonnements / désabonnements à l&#8217;évènement. </p>
<p>Pour ajouter l&#8217;évènement <code>PropertyChanged</code> à notre type, nous avons donc :</p>
<ul>
<li>Ajouté un champ d&#8217;instance privé de type <code>NotifyPropertyChangedEventHandler</code></li>
<li>Ajouté l&#8217;évènement (pseudo propriété), qui utilise deux méthodes : <code>add_PropertyChanged</code> et <code>remove_PropertyChanged</code></li>
<li>Créé les deux méthodes précédentes, qui utilisent respectivement les méthodes statiques <code>Delegate.Combine</code> et <code>Delegate.Remove</code> pour ajouter et supprimer les handlers au champ d&#8217;instance</li>
</ul>
<p>Puisque l&#8217;IL n&#8217;est pas très lisible, voici la traduction C# de ces deux méthodes :</p>
<pre name="code" class="csharp">

public void add_PropertyChanged(PropertyChangedEventHandler value)
{
    this.PropertyChanged =
		(PropertyChangedEventHandler) Delegate.Combine(this.PropertyChanged, value);
}

public void remove_PropertyChanged(PropertyChangedEventHandler value)
{
    this.PropertyChanged =
		(PropertyChangedEventHandler) Delegate.Remove(this.PropertyChanged, value);
}
</pre>
<p>Dans notre exemple précédent, on délègue la création de ces deux méthodes à <code>CreateEventMethod</code> dont voici la définition :</p>
<pre name="code" class="csharp">

private MethodDefinition CreateEventMethod(string methodName,
                                           MethodReference delegateMethodReference,
                                           FieldReference eventField)
{
    const MethodAttributes attributes = MethodAttributes.Public |
                                        MethodAttributes.HideBySig |
                                        MethodAttributes.Final |
                                        MethodAttributes.SpecialName |
                                        MethodAttributes.NewSlot |
                                        MethodAttributes.Virtual;

    TypeReference eventHandlerTypeRef = GetReference&lt;PropertyChangedEventHandler&gt;();
    TypeReference voidType = GetReference(typeof (void));

    MethodDefinition methodDef = new MethodDefinition(methodName, attributes, voidType);

    methodDef.Parameters.Add(new ParameterDefinition(eventHandlerTypeRef));
    CilWorker cilWorker = methodDef.Body.CilWorker;
    cilWorker.Emit(OpCodes.Ldarg_0);
    cilWorker.Emit(OpCodes.Ldarg_0);
    cilWorker.Emit(OpCodes.Ldfld, eventField);
    cilWorker.Emit(OpCodes.Ldarg_1);
    cilWorker.Emit(OpCodes.Call, delegateMethodReference);
    cilWorker.Emit(OpCodes.Castclass, eventHandlerTypeRef);
    cilWorker.Emit(OpCodes.Stfld, eventField);
    cilWorker.Emit(OpCodes.Ret);
    return methodDef;
}
</pre>
<p>Notez l&#8217;API intuitive que propose Cecil pour ce genre de choses : on instancie une définition de l&#8217;élément que l&#8217;on cherche à ajouter au type (<code>FieldDefinition</code>, <code>EventDefinition</code>, <code>MethodDefinition</code>, etc.), on la configure si besoin, et on l&#8217;ajoute à la définition parente. Pour ce qui est de l&#8217;émission d&#8217;IL pour le corps des méthodes, il suffit d&#8217;obtenir un <code>CilWorker</code> et de créer séquentiellement les instructions en utilisant les codes d&#8217;opérations du langage intermédiaire.</p>
<p>Voilà pour la création de l&#8217;évènement <code>PropertyChanged</code>. Notre type est à présent une implémentation valide de l&#8217;interface <code>INotifyPropertyChanged</code>, puisque qu&#8217;il respecte le contrat imposé par cette dernière : exposer un évènement <code>PropertyChanged</code>, de type <code>PropertyChangedEventHandler</code>. (Etape [#1] du schéma)</p>
<p>Il ne reste plus qu&#8217;à déclencher cet évènement, et pour cela, il est habituellement préférable de prévoir une méthode spécifique qui sera appellée à partir des setters (Etape [#2]). Nous l&#8217;appellons ici <code>FireNotifyPropertyChanged</code> et c&#8217;est la méthode <code>WeaveEventFiringHelper</code> de notre transformer qui se charge de l&#8217;ajouter au type instrumenté :</p>
<pre name="code" class="csharp">

private MethodReference WeaveEventFiringHelper(FieldReference eventField, TypeDefinition type)
{
    MethodReference invokeMethodRef = this.assembly.MainModule.Import(invokeMethodBase);
    MethodReference argsCtorMethodRef = this.assembly.MainModule.Import(constructorMethodBase);
    TypeReference stringTypeRef = GetReference&lt;string&gt;();
    TypeReference voidTypeRef = GetReference(typeof (void));

    MethodDefinition firePropertyChanged =
        new MethodDefinition(&quot;FirePropertyChanged&quot;, MethodAttributes.Private, type);
    firePropertyChanged.ReturnType = new MethodReturnType(voidTypeRef);
    ParameterDefinition propertyNameParameter =
        new ParameterDefinition(&quot;propertyName&quot;, 0, ParameterAttributes.None, stringTypeRef);
    firePropertyChanged.Parameters.Add(propertyNameParameter);

    CilWorker cilWorker = firePropertyChanged.Body.CilWorker;

    Instruction returnInstruction = cilWorker.Create(OpCodes.Ret);
    cilWorker.Emit(OpCodes.Ldarg_0);
    cilWorker.Emit(OpCodes.Ldfld, eventField);
    cilWorker.Emit(OpCodes.Brfalse_S, returnInstruction);
    cilWorker.Emit(OpCodes.Ldarg_0);
    cilWorker.Emit(OpCodes.Ldfld, eventField);
    cilWorker.Emit(OpCodes.Ldarg_0);
    cilWorker.Emit(OpCodes.Ldarg_1);
    cilWorker.Emit(OpCodes.Newobj, argsCtorMethodRef);
    cilWorker.Emit(OpCodes.Callvirt, invokeMethodRef);
    cilWorker.Append(returnInstruction);
    type.Methods.Add(firePropertyChanged);

    return firePropertyChanged;
}
</pre>
<p>La <code>FieldReference</code> récupérée en argument est celle retournée par la méthode précédente, <code>WeaveEvent</code>, qui a ajouté l&#8217;évènement au type. Elle représente d&#8217;ailleurs le champ de l&#8217;évènement, qui doit être utilisé pour l&#8217;invocation. La traduction C# de la méthode générée dynamiquement correspond à :</p>
<pre name="code" class="csharp">

    private void FirePropertyChanged(string propertyName)
    {
        if (this.PropertyChanged != null)
        {
            this.PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }
</pre>
<p>C&#8217;est complètement équivalent au code de l&#8217;étape [#2] dans le premier schéma.</p>
<h3>Instrumentation des setters</h3>
<p>A ce stade, pour résumer, nous avons :</p>
<ul>
<li>[#1] Implémenté <code>INotifyPropertyChanged</code> en ajoutant un évènement <code>PropertyChanged</code> au type</li>
<li>[#2] Créé une méthode &#8220;helper&#8221; pour déclencher l&#8217;évènement</li>
</ul>
<p>Très logiquement, il ne reste plus qu&#8217;à appeller cette dernière à partir de tous les setters des propriétés du type que l&#8217;on modifie (étape [#3]). Cette fois-ci, on ne va pas créer un nouveau champ, un nouvel évènement ou une nouvelle méthode, on va <em>modifier</em> le code CIL du corps de méthodes existantes. Car un setter de propriété est une méthode traditionnelle.</p>
<p>Examinons la méthode <code>WeaveEventTriggers</code> du transformer, qui est responsable de cette tache :</p>
<pre name="code" class="csharp">

private static void WeaveEventTriggers(TypeDefinition type, MethodReference firePropertyChanged)
{
    foreach (PropertyDefinition property in type.Properties)
    {
        MethodDefinition method = property.SetMethod;
        if (method == null)
        {
            continue;
        }

        Instruction retInstruction = method.Body.Instructions[method.Body.Instructions.Count - 1];

        CilWorker cilWorker = method.Body.CilWorker;
        cilWorker.InsertBefore(retInstruction, cilWorker.Create(OpCodes.Ldarg_0));
        cilWorker.InsertBefore(retInstruction, cilWorker.Create(OpCodes.Ldstr, property.Name));
        cilWorker.InsertBefore(retInstruction, cilWorker.Create(OpCodes.Call, firePropertyChanged));
    }
}
</pre>
<p>Encore une fois, l&#8217;implémentation est naïve et nous verrons s&#8217;il est possible de l&#8217;améliorer plus tard. La logique est simple :</p>
<ul>
<li>On itère sur <em>toutes</em> les propriétés du type. (Pas très malin&#8230;)</li>
<li>On récupère la définition de la méthode du setter.</li>
<li>On récupère une référence vers la dernière instruction du corps du setter</li>
<li>On injecte le code CIL correspondant à l&#8217;appel de la méthode <code>FirePropertyChanged</code> avant la dernière instruction pour que la notification soit lançée à la fin de chaque modification.</li>
</ul>
<p>En gros, si le setter en C# est du genre :</p>
<pre name="code" class="csharp">

	public void set_Name(string value)
	{
		this.name = value;
	}
</pre>
<p>On le transforme en :</p>
<pre name="code" class="csharp">

	public void set_Name(string value)
	{
		this.name = value;
		FirePropertyChanged(&quot;Name&quot;);
	}
</pre>
<p>Note : <code>combineMethodBase</code>, <code>invokeMethodBase</code>, <code>constructorMethodBase</code> et <code>removeMethodBase</code>, référencés dans les méthodes du <code>Transformer</code>, sont des membres statiques initialisés de la façon suivante :</p>
<pre name="code" class="csharp">

private static readonly MethodBase combineMethodBase;
private static readonly MethodBase invokeMethodBase;
private static readonly MethodBase constructorMethodBase;
private static readonly MethodBase removeMethodBase;

static Transformer()
{
    var type = typeof (Delegate);
    combineMethodBase = type.GetMethod(&quot;Combine&quot;, new[] {type, type});
    removeMethodBase = type.GetMethod(&quot;Remove&quot;);
    type = typeof (PropertyChangedEventHandler);
    invokeMethodBase = type.GetMethod(&quot;Invoke&quot;);
    type = typeof (PropertyChangedEventArgs);
    constructorMethodBase = type.GetConstructor(new[] {typeof (string)});
}
</pre>
<p>Les <code>MethodBase</code> sont des types de l&#8217;API d&#8217;introspection de <code>System.Reflection</code>. Il est facile de récupérer les <code>MethodReference</code> correspondantes (API Cecil) en utilisant la méthode <code>Import</code> d&#8217;une <code>ModuleDefinition</code>.</p>
<h3>Conclusion intermédiaire</h3>
<p>Voilà une première version du &#8220;transformer&#8221; capable d&#8217;instrumenter un assembly existant pour faire implémenter <code>INotifyPropertyChanged</code> à certains de ses types automatiquement. Les améliorations possibles sont nombreuses, et je ne vais en citer que quelques unes :</p>
<ul>
<li>Meilleure utilisation de Cecil : après tout, je découvre et suis donc loin d&#8217;être un expert</li>
<li>Meilleure intégration au process de build, en utilisant une custom task MSBuild par exemple</li>
<li>Version complète de l&#8217;instrumentation : l&#8217;évènement <code>PropertyChanged</code> ne doit être déclenché que lorsque la valeur affectée à la propriété est différente</li>
<li>Gestion des exceptions et du logging (évidemment)</li>
<li>Etc.</li>
</ul>
<p>Cecil est un outil extrêmement puissant et facile d&#8217;utilisation. Pour info, la mise en place de cette version du <code>Transformer</code> n&#8217;a pas dû me prendre 2 heures, alors que <strike>la femme de ma vie me parlait</strike> je faisais autre chose en même temps, et que je découvrais complètement l&#8217;API non documentée. Il est préférable par contre de connaître le CIL, même si ILdasm ou Reflector peuvent vous assister efficacement. Enfin, et presque paradoxalement, la prise en main de Cecil vous paraitra déroutante si vous avez l&#8217;habitude d&#8217;utiliser <code>System.Reflection</code> et <code>System.Reflection.Emit</code>.</p>
<p>Au final ma première expérience est définitivement positive, et je n&#8217;hésiterai pas dans le futur à recourir à Cecil au besoin. Je pense d&#8217;ailleurs qu&#8217;en collaboration avec une couche facilitant son utilisation dans un context post-build, on aurait quelque chose d&#8217;assez terrible, probablement plus simple à utiliser que PostSharp.Core par exemple pour des tâches bien spécifiques.</p>
<p>Notez tout de même que l&#8217;exemple d&#8217;utilisation de Cecil présenté ici est un peu tordu, et qu&#8217;il y a bien d&#8217;autres (meilleurs) <a href="http://www.mono-project.com/Cecil#Projects">moyens d&#8217;exploiter ses capacités</a>.</p>
Posted in Articles Tagged: .NET, AOP, C#, Cecil, CIL <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/romainverdier.wordpress.com/379/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/romainverdier.wordpress.com/379/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/romainverdier.wordpress.com/379/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/romainverdier.wordpress.com/379/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/romainverdier.wordpress.com/379/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/romainverdier.wordpress.com/379/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/romainverdier.wordpress.com/379/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/romainverdier.wordpress.com/379/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/romainverdier.wordpress.com/379/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/romainverdier.wordpress.com/379/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=codingly.com&blog=3510695&post=379&subd=romainverdier&ref=&feed=1" /></div><img src="http://feeds.feedburner.com/~r/Codingly/~4/-EN8I5Dk-kw" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://codingly.com/2008/11/10/introduction-a-monocecil-implementer-inotifypropertychanged/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/cb0ee4bde49708f4be24a02a5d59e52e?s=96&amp;d=http%3A%2F%2F0.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96" medium="image">
			<media:title type="html">Romain</media:title>
		</media:content>

		<media:content url="http://romainverdier.files.wordpress.com/2008/11/transformer.jpg" medium="image">
			<media:title type="html">transformer</media:title>
		</media:content>
	<feedburner:origLink>http://codingly.com/2008/11/10/introduction-a-monocecil-implementer-inotifypropertychanged/</feedburner:origLink></item>
		<item>
		<title>ALT.NET en France : Mono à Paris pour la 7ème rencontre</title>
		<link>http://feedproxy.google.com/~r/Codingly/~3/hjbWbLCFFbQ/</link>
		<comments>http://codingly.com/2008/11/05/altnet-en-france-mono-a-paris-pour-la-7eme-rencontre/#comments</comments>
		<pubDate>Wed, 05 Nov 2008 23:19:51 +0000</pubDate>
		<dc:creator>Romain Verdier</dc:creator>
				<category><![CDATA[Posts]]></category>
		<category><![CDATA[.NET]]></category>
		<category><![CDATA[ALT.NET]]></category>
		<category><![CDATA[Mono]]></category>

		<guid isPermaLink="false">http://romainverdier.wordpress.com/?p=358</guid>
		<description><![CDATA[Mardi dernier a eu lieu la réunion ALT.NET parisienne du mois de novembre. Généralement, on s&#8217;arrange pour que cela tombe le premier mercredi de chaque mois mais cette fois ci nous avons préféré supporter une exception pour bénéficier de la présence de Jean-Baptiste Evain, de passage à Paris. Ce dernier travaille à plein temps pour [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=codingly.com&blog=3510695&post=358&subd=romainverdier&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p>Mardi dernier a eu lieu la réunion ALT.NET parisienne du mois de novembre. Généralement, on s&#8217;arrange pour que cela tombe le premier mercredi de chaque mois mais cette fois ci nous avons préféré supporter une exception pour bénéficier de la présence de <a href="http://evain.net/blog/">Jean-Baptiste Evain</a>, de passage à Paris. Ce dernier travaille à plein temps pour <a href="http://www.novell.com/">Novell</a>, en tant que contributeur sur le projet <a href="http://www.mono-project.com/">Mono</a>. Oui, vous avez le droit d&#8217;être jaloux, en comptant le QA ils doivent être une trentaine. Dans le monde.<br />
<span id="more-358"></span></p>
<p><img src="http://romainverdier.files.wordpress.com/2008/11/altnetmono1.jpg?w=664&#038;h=289" alt="altnetmono1" title="altnetmono1" width="664" height="289" class="aligncenter size-full wp-image-365" /></p>
<p>Pour la première fois &#8211; c&#8217;est à noter également &#8211; la réunion à été sponsorisée. Cela nous a permis de rassembler la vingtaine de participants dans une jolie salle de meeting gracieusement mise à disposition par <a href="http://www.valtech.fr/fr/index.html">Valtech</a>, pour discuter de Mono en mangeant des pizzas. En fait, cette foule a commencé à se rassembler vers 19h dans un bar, avant de migrer chez Valtech à 20h pour la &#8220;présentation interactive&#8221; de Mono par Jb. Comprendre : 4 slides, <a href="http://www.williamandnadia.com/media/photos/scaredkitty_large.jpg">lolcatz</a> inclu. Nous avons appris pas mal de choses sur Mono. En vrac, comme toujours : vision et motivations des contributeurs du projet, vision et motivation de Novell, origines de Mono, Novell &amp; Microsoft, les utilisateurs de Mono, <a href="http://www.mono-project.com/Moonlight">Moonlight</a>, <a href="http://www.mono-project.com/Cecil">Mono.Cecil</a>, <a href="http://www.mono-project.com/Linker">Mono Linker</a>, Compiler as a Service, le JIT de Mono et <a href="http://tirania.org/blog/archive/2008/Nov-03.html">SIMD</a>, l&#8217;ouverture de Microsoft, MonoDevelop, le debugger Mono, ASP.NET MVC et Mono, le futur de Mono, Mono et les Picaros, etc.</p>
<p>Nous avons épuisé notre stock de questions Mono vers 22h je pense, et sommes restés sur place un moment pour discuter de diverses choses. Pour ma part, ce fût principalement C# et les nouveautés du langage annoncées à la <a href="http://www.microsoftpdc.com/">PDC</a>. Malheureusement, je n&#8217;ai pas eu l&#8217;occasion de parler à tout le monde, et j&#8217;imagine que les sujets furent plus variés que ça. J&#8217;ai entendu &#8220;F#&#8221;, &#8220;MVC&#8221;, &#8220;j&#8217;ai soif&#8221;, etc.</p>
<p>Finalement, la soirée s&#8217;est terminée au Comptoir de l&#8217;Arc, où elle avait commencée, mais une fois de plus nous n&#8217;avons pu discuter qu&#8217;en petits groupes. Dans ceux auxquels je me suis intégré, il était question d&#8217;AOP, de Cecil, de <a href="http://www.postsharp.org/">PostSharp</a>, de <a href="http://www.castleproject.org/dynamicproxy/index.html">DynamicProxy</a>, de <a href="http://msdn.microsoft.com/en-us/library/system.reflection.emit.aspx">SRE</a>, de CIL, de l&#8217;API de profiling native ou de TypeMock. Nous avons également abordé le sujet des grosses solutions Microsoft, de leur pertinence et de leur avenir probable : TFS, Rosario, BizTalk, Entity Framework, Astoria, Azure, etc. Il était intéressant de constater que nous avions tous à peu près pris le temps de visionner les mêmes vidéos de la PDC : </p>
<ul>
<li><a href="http://channel9.msdn.com/pdc2008/TL16/">The future of C#</a></li>
<li><a href="http://channel9.msdn.com/pdc2008/TL26/">Parallel programming</a></li>
<li><a href="http://channel9.msdn.com/pdc2008/PC54/">Mono et .NET</a></li>
<li><a href="http://channel9.msdn.com/pdc2008/TL02/">Advances in the .NET Type System</a></li>
<li><a href="http://channel9.msdn.com/pdc2008/PC49/">CLR Futures</a></li>
<li><a href="https://sessions.microsoftpdc.com/timeline.aspx">Etc.</a></li>
</ul>
<p>En résumé, l&#8217;organisation était différente : nous avions une salle dédiée, nous étions plus nombreux et il y avait un thème. J&#8217;ai trouvé ça assez sympa, même s&#8217;il va falloir que je m&#8217;habitue à la frustration de ne pas pouvoir échanger avec tout le monde.</p>
<p>Et ici vous vous dites, c&#8217;est cool, mais des comptes-rendu de ce genre, ça sert à rien. Et moi de répondre : c&#8217;est pas faux, mais c&#8217;est pas terminé non plus.</p>
<p>Il m&#8217;a semblé qu&#8217;un point important avait été soulevé durant la discussion au sujet de Mono.</p>
<p>Lorsqu&#8217;on comprend un peu mieux ce qu&#8217;est le projet, qu&#8217;on commence à en apercevoir les contours, certaines interrogations plus précises peuvent survenir. On peut, par exemple, chercher à comprendre ce qui a pu pousser quelques pionniers de l&#8217;open source et du monde libre à lancer cette initiative pour le moins <em>ambitieuse</em>. On veut savoir s&#8217;il s&#8217;agit d&#8217;un <strike> simple</strike> délire de geek, ou d&#8217;autre chose. Apparemment, et au risque de vous surprendre, il s&#8217;agirait bien d&#8217;autre chose. Si vous me permettez de résumer très grossièrement la raison qui semble être la principale motivation des contributeurs du projet Mono : <em>la plateforme .NET a des qualités, il serait bien de pouvoir en profiter sous Linux.</em></p>
<p>Cependant, même si on trouve le postulat de base légitime, on est en droit de s&#8217;interroger sur la faisabilité, le devenir de Mono, la pertinence de l&#8217;effort, etc. Et c&#8217;est où je veux en venir. La question qui revient souvent (elle est revenue mardi soir) est la suivante :</p>
<blockquote><p>Ouais, mais vous ne pensez pas, quand même, que c&#8217;est un peu dommage d&#8217;être à la traine derrière Microsoft ? De travailler comme des bourrins pour coller avec un train de retard à une partie des fonctionnalités de l&#8217;implémentation officielle ? Et par dessus tout, vous ne trouvez pas déprimant de ne pas pouvoir innover ou décider de la direction à suivre ?</p></blockquote>
<p><img src="http://romainverdier.files.wordpress.com/2008/11/altnetmono2.jpg?w=222&#038;h=284" alt="altnetmono2" title="altnetmono2" width="222" height="284" class="alignright size-full wp-image-364" /></p>
<p>Bon, OK, il y a plusieurs questions et je me les ai suis posées. M. Evain a assez bien répondu selon moi. En tout cas, suffisamment pour que j&#8217;aie l&#8217;impression aujourd&#8217;hui de percevoir le projet différemment. D&#8217;où ma volonté d&#8217;insister dans ce billet : L&#8217;innovation, ce n&#8217;est pas simplement écrire les spécifications de C# 5.0. Décider, ça ne passe pas forcément par la définition de C# 5.0, ou l&#8217;architecture de WCF.</p>
<p>Il y a beaucoup d&#8217;autres moyens d&#8217;innover et de décider. D&#8217;une part, le fait de proposer une implémentation de .NET sur un environnement complètement différent, où les contraintes sont autres, ça offre un bon lot d&#8217;occasions et de challenges. Par exemple : développer le premier compilateur C# en code managé ou écrire un JIT dont les optimisations rendent envisageable l&#8217;utilisation de .NET dans des domaines qui semblaient auparavant inaccessibles. N&#8217;importe quel geek peut trouver ça suffisant pour étouffer l&#8217;éventuelle frustration dont nous parlions plus tôt. D&#8217;autre part, au delà de la course à l&#8217;implémentation, le projet Mono permet à de nombreux outils et librairies n&#8217;existant pas sous Windows, par exemple, de voir le jour, et d&#8217;être utilisés par la communauté toute entière. Au hasard : Cecil. C&#8217;est également un vecteur d&#8217;innovation.</p>
<p>Accessoirement, je suis curieux de savoir ce que vous avez pensé de la réunion. J&#8217;ai vu que certains prenaient des notes donc je garde un oeil sur google reader, mais comme d&#8217;hab, au cas où vous en doutiez, sachez que vos commentaires ici sont appréciés.</p>
Posted in Posts Tagged: .NET, ALT.NET, Mono <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/romainverdier.wordpress.com/358/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/romainverdier.wordpress.com/358/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/romainverdier.wordpress.com/358/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/romainverdier.wordpress.com/358/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/romainverdier.wordpress.com/358/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/romainverdier.wordpress.com/358/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/romainverdier.wordpress.com/358/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/romainverdier.wordpress.com/358/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/romainverdier.wordpress.com/358/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/romainverdier.wordpress.com/358/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=codingly.com&blog=3510695&post=358&subd=romainverdier&ref=&feed=1" /></div><img src="http://feeds.feedburner.com/~r/Codingly/~4/hjbWbLCFFbQ" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://codingly.com/2008/11/05/altnet-en-france-mono-a-paris-pour-la-7eme-rencontre/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/cb0ee4bde49708f4be24a02a5d59e52e?s=96&amp;d=http%3A%2F%2F0.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96" medium="image">
			<media:title type="html">Romain</media:title>
		</media:content>

		<media:content url="http://romainverdier.files.wordpress.com/2008/11/altnetmono1.jpg" medium="image">
			<media:title type="html">altnetmono1</media:title>
		</media:content>

		<media:content url="http://romainverdier.files.wordpress.com/2008/11/altnetmono2.jpg" medium="image">
			<media:title type="html">altnetmono2</media:title>
		</media:content>
	<feedburner:origLink>http://codingly.com/2008/11/05/altnet-en-france-mono-a-paris-pour-la-7eme-rencontre/</feedburner:origLink></item>
	</channel>
</rss>
