<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-148524916779753368</id><updated>2012-02-16T06:41:30.694-03:00</updated><category term='application block'/><category term='logging'/><category term='agiles2008'/><category term='Visual Studio'/><category term='Vale'/><category term='conversiones'/><category term='MVC'/><category term='javascript'/><category term='delegados'/><category term='AssemblyInfo Task'/><category term='CAB'/><category term='AJAX'/><category term='mock'/><category term='convert.toint32'/><category term='extension methods'/><category term='ASP.NET'/><category term='c#'/><category term='desbordamiento'/><category term='JQuery'/><category term='sharepoint'/><category term='moq'/><category term='int32.parse'/><category term='unit test'/><category term='desarrollo ágil'/><category term='VAN'/><category term='dirigencia'/><category term='colecciones'/><category term='salarios'/><category term='tracelistener'/><category term='herencia'/><category term='EntLib'/><category term='validation application block'/><category term='predicados'/><category term='humor'/><category term='métodos anónimos'/><category term='fsx'/><category term='LINQ'/><category term='xml'/><category term='alt.net'/><category term='enum'/><category term='double'/><category term='inferencia'/><category term='IoC'/><category term='silverlight'/><category term='refactor'/><category term='REST'/><category term='precisión'/><category term='versiones'/><category term='objects'/><category term='teoria de objetos'/><category term='VAP'/><category term='dilbert'/><category term='tipos anónimos'/><category term='MSBuild'/><category term='Generics'/><category term='agiles2009'/><category term='checked'/><category term='PIAB'/><category term='VS2008'/><category term='C# 3.0'/><category term='sql'/><category term='WCF'/><category term='MUG'/><category term='unchecked'/><category term='twitter'/><category term='orcas'/><category term='log4net'/><category term='eventos'/><category term='NHibernate'/><category term='patrones'/><category term='programadores'/><category term='enteros'/><category term='decimal'/><category term='rhino'/><category term='expresiones lambda'/><category term='dce'/><category term='smart client'/><category term='excepciones'/><category term='json'/><category term='trabajo'/><title type='text'>Una sinfonía en C#</title><subtitle type='html'>Un humilde aporte a la comunidad C# de habla hispana.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://leomicheloni.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://leomicheloni.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><link rel='next' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default?start-index=101&amp;max-results=100'/><author><name>Leonardo Micheloni</name><uri>http://www.blogger.com/profile/12085246040181097881</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='30' src='http://3.bp.blogspot.com/_t9Bh42Thfqo/S6TVOJqYWcI/AAAAAAAAANU/MlZc6HpYZis/S220/yo+laguito+en+col%C3%B3n.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>123</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-148524916779753368.post-171038430293824869</id><published>2011-08-10T23:05:00.001-03:00</published><updated>2011-08-10T23:05:57.537-03:00</updated><title type='text'>Nueva casa</title><content type='html'>&lt;p&gt;Este es el último post en este lugar, a partir de ahora me mudo a un hosting propio sobre una plataforma .net, &lt;a href="http://leomicheloni.com/"&gt;la nueva dirección del blog es esta&lt;/a&gt;.&lt;/p&gt; &lt;p&gt;Todo lo que está acá quedará y lo iré llevando a la nueva casa, gracias Blogger por estos años de darme espacio y gracias a todos los que siguen este blog. Nos vemos en la nueva casa.&lt;/p&gt; &lt;p&gt;Saludos, Leonardo.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;Leonardo Micheloni&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/148524916779753368-171038430293824869?l=leomicheloni.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://leomicheloni.blogspot.com/feeds/171038430293824869/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=148524916779753368&amp;postID=171038430293824869' title='1 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default/171038430293824869'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default/171038430293824869'/><link rel='alternate' type='text/html' href='http://leomicheloni.blogspot.com/2011/08/nueva-casa.html' title='Nueva casa'/><author><name>Leonardo Micheloni</name><uri>http://www.blogger.com/profile/12085246040181097881</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='30' src='http://3.bp.blogspot.com/_t9Bh42Thfqo/S6TVOJqYWcI/AAAAAAAAANU/MlZc6HpYZis/S220/yo+laguito+en+col%C3%B3n.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-148524916779753368.post-2099807117764591095</id><published>2011-07-24T23:01:00.004-03:00</published><updated>2011-07-25T09:21:59.018-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='VAN'/><category scheme='http://www.blogger.com/atom/ns#' term='alt.net'/><title type='text'>VAN sobre conceptos HTTP y Fiddler web debugger</title><content type='html'>&lt;p&gt;&lt;/p&gt;
&lt;p&gt;El pasado sábado 23 de Julio tuve nuevamente el gusto de dar una &lt;a href="http://virtualaltnet.com/"&gt;VAN&lt;/a&gt; para la comunidad de &lt;a href="http://altnethispano.org/Inicio.aspx"&gt;Alt.Net hispano&lt;/a&gt;, la misma se trató sobre HTTP y &lt;a href="http://www.fiddler2.com/fiddler2/"&gt;Fiddler&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;Conceptos básicos de HTTP&lt;/h3&gt;
&lt;p&gt;En la VAN hablé las cosas que yo creo indispensables que hay que conocer sobre HTTP si nos dedicamos al desarrollo web, su naturaleza, su principales características y limitaciones.&lt;/p&gt;
&lt;p&gt;Paralelamante al desarrollo de los temas fui mostrando Fiddler y cómo se puede usar como herramienta para visualizar HTTP, manipularlo y demás.&lt;/p&gt;
&lt;h3&gt;Fiddler&lt;/h3&gt;
&lt;p&gt;Finalmente fui mostrando las bondades de esta herramienta y cómo nos puede ayudar de inspeccionar y simular situaciones, cambiar datos, filtrar, hicimos scripts y hasta un plug-in con C#.&lt;/p&gt;
&lt;h3&gt;Muchas gracias&lt;/h3&gt;
&lt;p&gt;No tengo más que agradecer a los patrocinadores por los proveer todo lo necesario para la realización de las reuniones y por los regalos que siempre se sortean al final, no quiero dejar de nombrar a &lt;a href="http://twitter.com/jorgegamba"&gt;Jorge Gamba&lt;/a&gt;, el motor de esta comunidad, la pasé muy bien dando la VAN a pesar que siempre algún ejemplo no funciona :-)&lt;/p&gt;
&lt;h3&gt;El material&lt;/h3&gt;
&lt;p&gt;Dejo la presentación que utilicé durante la VAN &lt;a href="https://skydrive.live.com/?cid=c9e9afda80ba37c1&amp;amp;id=C9E9AFDA80BA37C1%21242"&gt;“HTTP las ruedas de la web”&lt;/a&gt;, pronto estará la grabación disponible en el &lt;a href="http://altnethispano.org/reuniones/historico.aspx"&gt;sitio de Alt.Net hispano&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;El video&lt;/h3&gt;
&lt;p&gt;Ya está el video disponible&lt;/p&gt;
&lt;p&gt;
&lt;object id="scPlayer"  width="640" height="369" type="application/x-shockwave-flash" data="http://content.screencast.com/users/AltNetHispano/folders/VAN/media/7c12da0d-3623-43ea-8a11-ba4544717314/flvplayer.swf" &gt; &lt;param name="movie" value="http://content.screencast.com/users/AltNetHispano/folders/VAN/media/7c12da0d-3623-43ea-8a11-ba4544717314/flvplayer.swf" /&gt; &lt;param name="quality" value="high" /&gt; &lt;param name="bgcolor" value="#FFFFFF" /&gt; &lt;param name="flashVars" value="thumb=http://content.screencast.com/users/AltNetHispano/folders/VAN/media/7c12da0d-3623-43ea-8a11-ba4544717314/FirstFrame.jpg&amp;containerwidth=1280&amp;containerheight=738&amp;analytics=UA-21341284-1&amp;content=http://content.screencast.com/users/AltNetHispano/folders/VAN/media/7c12da0d-3623-43ea-8a11-ba4544717314/van-2011-07-23.flv&amp;blurover=false" /&gt; &lt;param name="allowFullScreen" value="true" /&gt; &lt;param name="scale" value="showall" /&gt; &lt;param name="allowScriptAccess" value="always" /&gt; &lt;param name="base" value="http://content.screencast.com/users/AltNetHispano/folders/VAN/media/7c12da0d-3623-43ea-8a11-ba4544717314/" /&gt; Unable to display content. Adobe Flash is required.&lt;/object&gt;&lt;/p&gt;
&lt;p&gt;Hasta la próxima, Leonardo.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;Leonardo Micheloni&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/148524916779753368-2099807117764591095?l=leomicheloni.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://leomicheloni.blogspot.com/feeds/2099807117764591095/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=148524916779753368&amp;postID=2099807117764591095' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default/2099807117764591095'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default/2099807117764591095'/><link rel='alternate' type='text/html' href='http://leomicheloni.blogspot.com/2011/07/van-sobre-conceptos-http-y-fiddler-web.html' title='VAN sobre conceptos HTTP y Fiddler web debugger'/><author><name>Leonardo Micheloni</name><uri>http://www.blogger.com/profile/12085246040181097881</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='30' src='http://3.bp.blogspot.com/_t9Bh42Thfqo/S6TVOJqYWcI/AAAAAAAAANU/MlZc6HpYZis/S220/yo+laguito+en+col%C3%B3n.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-148524916779753368.post-5067660830836649174</id><published>2011-04-23T21:28:00.002-03:00</published><updated>2011-05-02T10:59:25.362-03:00</updated><title type='text'>HTTP un estado aparente, cookies y caché</title><content type='html'>&lt;p&gt; &lt;/p&gt; &lt;p&gt;En el post anterior dije medio al pasar que HTTP no tiene estado, esto quiere decir que cada transacción es única, no sigue una secuencia y no hay relación entre ellas, esto es a nivel protocolo, o sea que HTTP no provee mecanismos para mantener la sesión “out-of-the-box”, si bien en la web que conocemos podemos entrar a Facebook, ingresar nuestros datos y seguir “logeados”, una clara demostración de que Facebook mantiene el “estado” porque recuerda que ya nos “loegamos” (estoy muy comillero).&lt;/p&gt; &lt;h3&gt;Qué son las cookies o sea las galletitas&lt;/h3&gt; &lt;p&gt;Técnicamente una cookie es un fragmento de información que se almacena del lado del cliente. Dentro de los muchos headers (encabezados) que podemos ver en una respuesta HTTP hay uno de ellos que sirven para controlar las cookies, la cosa es asi:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;Escenario A:  &lt;ul&gt; &lt;li&gt;El servidor indica el cliente que debe guardar una cookie con un nombre y valor determinado.  &lt;/li&gt;&lt;li&gt;El cliente la guarda localmente (de manera segura).  &lt;/li&gt;&lt;li&gt;Con cada nueva petición HTTP el mismo host el cliente envía esa cookie ignorando para qué la necesita el servidor.&lt;/li&gt;&lt;/ul&gt; &lt;/li&gt;&lt;li&gt;Escenario B:  &lt;ul&gt; &lt;li&gt;Desde javascript se genera un cookie (lado del cliente).  &lt;/li&gt;&lt;li&gt;La información se guarda localmente.  &lt;/li&gt;&lt;li&gt;Sólamante es visible desde el ámbito que se creó la cookie (idealmente).  &lt;/li&gt;&lt;li&gt;El servidor desconoce todo esto.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt; &lt;h3&gt; &lt;/h3&gt; &lt;h3&gt;Para mantener el estado usamos cookies&lt;/h3&gt; &lt;p&gt;Vamos a concentarnos en el escenario A que es el que permite el funcionamiento del estado sobre HTTP, para eso un dibujito:&lt;/p&gt; &lt;p&gt;&lt;a href="http://lh5.ggpht.com/_t9Bh42Thfqo/Tb3AR1EYZRI/AAAAAAAAAUQ/gAOrgQikjY8/s1600-h/image%5B3%5D.png"&gt;&lt;img style="border-width: 0px; display: inline;" title="image" alt="image" src="http://lh3.ggpht.com/_t9Bh42Thfqo/Tb3ASutrPmI/AAAAAAAAAUU/QZ0prrvj4Zs/image_thumb%5B1%5D.png?imgmax=800" border="0" width="476" height="285" /&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;Sencillo, en cierto momento que hacemos una petición HTTP al servidor nos response con el header set-cookie, el navegador guarda localmente el nombre y valor de esa cookie y lo envía simpre en cada nueva petición al servidor.&lt;/p&gt; &lt;h3&gt;Ejemplo real&lt;/h3&gt; &lt;p&gt;Vamos a ver con Fiddler qué pasa con las cookies cuando entramos a un sitio cualquiera. Vamor a &lt;a href="http://www.bing.com/"&gt;www.bing.com&lt;/a&gt;&lt;/p&gt; &lt;p&gt;&lt;a href="http://lh5.ggpht.com/_t9Bh42Thfqo/Tb3bsgjhBnI/AAAAAAAAAUY/KSuzkuR-3d0/s1600-h/image%5B8%5D.png"&gt;&lt;img style="border-width: 0px; display: inline;" title="image" alt="image" src="http://lh5.ggpht.com/_t9Bh42Thfqo/Tb3buGALJII/AAAAAAAAAUc/ipeAfBk3HCw/image_thumb%5B4%5D.png?imgmax=800" border="0" width="663" height="299" /&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;simplemente escribimos la dirección en la barra del navegador (Firefox en este caso) y vemos que se generan 15 peticiones….vamos a analizarlo.&lt;/p&gt; &lt;p&gt;En la primera petición nos responde 200 OK y ocho headers set-cookie, quién sabe para qué, pero Bing los usa para algo, en el contenido del primer mensaje está el HTML de la página solicitada. Nuestro navegador va a recordar todas estas cookies y enviarlas con cada petición nueva al host.&lt;/p&gt; &lt;p&gt;Vamos a analizar la segunda petición:&lt;/p&gt; &lt;p&gt;&lt;a href="http://lh5.ggpht.com/_t9Bh42Thfqo/Tb3hZZHaMRI/AAAAAAAAAUg/Ma9NyktqvwQ/s1600-h/image%5B12%5D.png"&gt;&lt;img style="border-width: 0px; display: inline;" title="image" alt="image" src="http://lh4.ggpht.com/_t9Bh42Thfqo/Tb3haSwt9bI/AAAAAAAAAUk/RJwyc3eGW04/image_thumb%5B6%5D.png?imgmax=800" border="0" width="672" height="208" /&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;&lt;/p&gt; &lt;p&gt;Y como era de esperar el navegador envía todas las mismas ocho cookies que le indicó el servidor en la respuesta anterior.&lt;/p&gt; &lt;h3&gt;Por qué se generaron quince peticiones si hicimos nada más que una?&lt;/h3&gt; &lt;p&gt;La respuesta es simple, el HTML de Bing hace referencia a muchos otros recursos también localizados en internet, por ejemplo las imágenes, los archivos de script, las hojas de estilo, etc. el navegador genera todas estas peticiones a medida que analiza el HTML y determina que necesitas los recursos.&lt;/p&gt; &lt;h3&gt;Cuando las cosas se “Cachean”&lt;/h3&gt; &lt;p&gt;Vamos a ver qué pasa si repetimos la petición original:&lt;/p&gt; &lt;p&gt;&lt;a href="http://lh3.ggpht.com/_t9Bh42Thfqo/Tb3hbHMBIZI/AAAAAAAAAUo/3OHe5ESg3VQ/s1600-h/image%5B16%5D.png"&gt;&lt;img style="border-width: 0px; display: inline;" title="image" alt="image" src="http://lh3.ggpht.com/_t9Bh42Thfqo/Tb3hcOfd99I/AAAAAAAAAUs/lFVTO5utvcM/image_thumb%5B8%5D.png?imgmax=800" border="0" width="690" height="316" /&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;Si presionamos F5 y recargamos la misma págna vemos en Fiddler que muchos recursos tiene un ícono con forma de disco, esto quiere decir que el navegador los recuperó del disco local y no los volvió a pedir para optimizar tiempos de respuesta, a esto se le llama caché. O sea el navegador recuerda que ya pedimos ese recurso (por la URL) y lo trae del disco para que sea más rápido, esto pasa mucho con imágenes pero puede pasar con todo, si hacemos Ctrl + F5 obligamos a Firefox a que pida todo de nuevo ignorando el caché.&lt;/p&gt; &lt;h3&gt;Podemos desde el servidor obligar a que siempre se pida el recurso sin usar el cache?&lt;/h3&gt; &lt;p&gt;Sí, podemos, desde el servidor agregamos el header &lt;a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html"&gt;Cache-Control&lt;/a&gt;, por ejemplo con el modificador max-age podemos indicar cuál es el máximo tiempo en segundos que el navegador debe mantener un recurso, en el caso de Bing este header estaba presente en la página por defecto, es por ese que el navegador volvió a pedir el recurso y no lo trajo del cache como los siguientes.&lt;/p&gt; &lt;p&gt;&lt;a href="http://lh5.ggpht.com/_t9Bh42Thfqo/Tb3hc3RgHdI/AAAAAAAAAUw/rdkjqaEhLeI/s1600-h/image%5B20%5D.png"&gt;&lt;img style="border-width: 0px; display: inline;" title="image" alt="image" src="http://lh6.ggpht.com/_t9Bh42Thfqo/Tb3hd-85cmI/AAAAAAAAAU0/XJmp2ziU1ko/image_thumb%5B10%5D.png?imgmax=800" border="0" width="673" height="139" /&gt;&lt;/a&gt; &lt;/p&gt; &lt;h3&gt;El estado y las cookies&lt;/h3&gt; &lt;p&gt;Todo esto era para explicar cómo se puede mantener el estado sobre HTTP, el funcionamiento más simple es utilizar una cookies para que el navegador la envíe siempre y entonces identificamos que se trata del mismo cliente, sería así:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;El cliente se conecta  &lt;/li&gt;&lt;li&gt;El cliente se logea correctamente  &lt;/li&gt;&lt;li&gt;El servidor le dice que guarde la cookie “session_id” con un valor generado único para ese cliente  &lt;/li&gt;&lt;li&gt;El navegador guarda la cookie con dicho valor y la envía con cada petición  &lt;/li&gt;&lt;li&gt;El servidor revisa siempre el valor de esa cookie e identifica el cliente que se acaba de logear &lt;/li&gt;&lt;/ul&gt; &lt;p&gt;Es un mecanismo sencillo, pero efectivo, vamos a verlo en funcionamiento.&lt;/p&gt; &lt;p&gt;Un ejemplo sencillo de ver es el modo en que ASP.NET mantiene la sesión, la cookie que usa se llama….asp.net_session y se ve más o menos así:&lt;/p&gt; &lt;p&gt;&lt;a href="http://lh6.ggpht.com/_t9Bh42Thfqo/Tb3nna1HBrI/AAAAAAAAAU4/6llCLAyNK8U/s1600-h/image%5B24%5D.png"&gt;&lt;img style="border-width: 0px; display: inline;" title="image" alt="image" src="http://lh4.ggpht.com/_t9Bh42Thfqo/Tb3noUytvFI/AAAAAAAAAU8/ZdXPSmXxi1M/image_thumb%5B12%5D.png?imgmax=800" border="0" width="675" height="204" /&gt;&lt;/a&gt; &lt;/p&gt; &lt;h3&gt;Si las cookies son tan importantes para la sesión, cómo las borro?&lt;/h3&gt; &lt;p&gt;No se borran, se hacen expirar, se agrega detrás de la información de la cookie la expiración, la forma más simple es poner una fecha en el pasado para que el navegador detecte que le llegó la hora y la borre. Esto se logra agregando detrás del nombre y valor de la cookies el atributo expires, por ejemplo:&lt;/p&gt; &lt;p&gt;Set-Cookie: lastlogin=1254773024; expires=Mon, 02-Nov-2009 20:12:04 GMT&lt;/p&gt; &lt;p&gt;Entonces cuando un sitio nos da la opción de mantenernos logeados para siempre en parte hace que esa (o esas) cookies que nos identifican no expiren nunca.&lt;/p&gt; &lt;p&gt;Modificando el web server para comprobar el uso de las cookies&lt;/p&gt; &lt;p&gt;Vamos a agregar una pequeña lógica para probar que el navegador va a recibir la orden de guardar una cookies y después va a enviarla siempre, finalmente vamos a forzarlo a hacerla expirar y no enviarla más, el código modificado queda así:&lt;/p&gt; &lt;p&gt;&lt;a href="http://lh3.ggpht.com/_t9Bh42Thfqo/Tb4cunvS53I/AAAAAAAAAVA/PmyrxV7xjyI/s1600-h/image%5B42%5D.png"&gt;&lt;img style="border: 0px none; display: inline;" title="image" alt="image" src="http://lh6.ggpht.com/_t9Bh42Thfqo/Tb4cvfYS8jI/AAAAAAAAAVE/M5JG_8lxjGg/image_thumb%5B22%5D.png?imgmax=800" border="0" width="694" height="461" /&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;Simple, en la primera petición se hace set-cookie (con la instrucción de ASP.NET Cookies.Add) y en la tercera obligamos a que la borre, indicando para esa cookie una fecha de expiración en el pasado. Probemos la primera petición y vemos qué dice Fiddler.&lt;/p&gt; &lt;p&gt;&lt;a href="http://lh4.ggpht.com/_t9Bh42Thfqo/Tb4cwQb01FI/AAAAAAAAAVI/lSs7ZPWp_gQ/s1600-h/image%5B41%5D.png"&gt;&lt;img style="border: 0px none; display: inline;" title="image" alt="image" src="http://lh5.ggpht.com/_t9Bh42Thfqo/Tb4cxJAWYjI/AAAAAAAAAVM/9sbFrN8RpvU/image_thumb%5B21%5D.png?imgmax=800" border="0" width="699" height="284" /&gt;&lt;/a&gt;  &lt;/p&gt; &lt;p&gt;Joya, vemos que nuestro servidor envía el header esperado, vamos a hacer una petición a otra página en el mismo sitio para comprobar si el navegador envía la cookie.&lt;/p&gt; &lt;p&gt;&lt;a href="http://lh4.ggpht.com/_t9Bh42Thfqo/Tb4cyGi1ayI/AAAAAAAAAVQ/xIBXz9JOvlU/s1600-h/image%5B36%5D.png"&gt;&lt;img style="border: 0px none; display: inline;" title="image" alt="image" src="http://lh4.ggpht.com/_t9Bh42Thfqo/Tb4cztDn_jI/AAAAAAAAAVU/kF13lu4k_pM/image_thumb%5B18%5D.png?imgmax=800" border="0" width="704" height="259" /&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;Adicionalmente envíamos la indicación para que expire la cookie, entonces en la siguiente petición no debería ser envíada, vamos a ver….&lt;/p&gt; &lt;p&gt;&lt;a href="http://lh6.ggpht.com/_t9Bh42Thfqo/Tb4c0YQ-RbI/AAAAAAAAAVY/MRkLp6LQJdE/s1600-h/image%5B40%5D.png"&gt;&lt;img style="border: 0px none; display: inline;" title="image" alt="image" src="http://lh3.ggpht.com/_t9Bh42Thfqo/Tb4c1OHYqiI/AAAAAAAAAVc/NG_Jdu4Zwec/image_thumb%5B20%5D.png?imgmax=800" border="0" width="710" height="313" /&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;Notable, funcionó, con esto comprobamos el funcionamiento de las cookies y el comportamiento del navegador.&lt;/p&gt; &lt;p&gt;Hasta la próxima.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;Leonardo Micheloni&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/148524916779753368-5067660830836649174?l=leomicheloni.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://leomicheloni.blogspot.com/feeds/5067660830836649174/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=148524916779753368&amp;postID=5067660830836649174' title='1 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default/5067660830836649174'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default/5067660830836649174'/><link rel='alternate' type='text/html' href='http://leomicheloni.blogspot.com/2011/04/http-un-estado-aparente-cookies-y-cache.html' title='HTTP un estado aparente, cookies y caché'/><author><name>Leonardo Micheloni</name><uri>http://www.blogger.com/profile/12085246040181097881</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='30' src='http://3.bp.blogspot.com/_t9Bh42Thfqo/S6TVOJqYWcI/AAAAAAAAANU/MlZc6HpYZis/S220/yo+laguito+en+col%C3%B3n.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh3.ggpht.com/_t9Bh42Thfqo/Tb3ASutrPmI/AAAAAAAAAUU/QZ0prrvj4Zs/s72-c/image_thumb%5B1%5D.png?imgmax=800' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-148524916779753368.post-114900741835380847</id><published>2011-04-16T10:23:00.001-03:00</published><updated>2011-04-17T20:30:40.171-03:00</updated><title type='text'>Introducción a HTTP, las ruedas de la web</title><content type='html'>&lt;p&gt;Voy a contar un poco de qué se trata HTTP, el protocolo que da vida a la web.  &lt;p&gt;HTTP es un protocolo. Técnicamente es un protocolo de aplicación (&lt;a href="http://es.wikipedia.org/wiki/Modelo_OSI"&gt;según el modelo OSI&lt;/a&gt;) pero en web se utiliza como transporte, es decir para transportar lo que realmente nos importa: el contenido, el HTML, XML, PDF, Zip, etc.  &lt;h3&gt;&amp;nbsp;&lt;/h3&gt; &lt;h3&gt;Algunas características de HTTP &lt;/h3&gt; &lt;ul&gt; &lt;li&gt;A cada comunicación se la llama transacción HTTP.  &lt;li&gt;Todas las transacciones comienzan del lado del cliente (en nuestro caso un navegador WEB).  &lt;li&gt;Es, básicamente, texto.  &lt;li&gt;Tiene dos secciones: una encabezado y un cuerpo.  &lt;li&gt;Se basa en verbos, que indican qué tipo de operación se desea realizar con la petición.  &lt;li&gt;Los verbos más comunes son: GET, POST, DELETE, HEAD, PUT.  &lt;li&gt;Las repuestas tiene un código de estado (STATUS CODE) qué nos indica qué pasó con nuestro request.  &lt;li&gt;Es un protocolo sin estado, es decir, no existe secuencialidad entre transacciones.&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;&amp;nbsp; &lt;h3&gt;Anatomía de una petición HTTP &lt;/h3&gt; &lt;p&gt;GET &lt;a href="http://www.bing.com"&gt;http://www.bing.com&lt;/a&gt; HTTP/1.1  &lt;p&gt;Esta es la petición más básica que podemos hacer para solicitar un recurso (digo recurso porque no sólo pedimos páginas sino imágenes, script, fuentes, etc), vamos a analizarla.  &lt;ul&gt; &lt;li&gt;Utiliza el verbo GET, es que vamos a utilizar en general para solicitar un recurso.  &lt;li&gt;&lt;a href="http://www.bing.com"&gt;http://www.bing.com&lt;/a&gt; es el nombre del recurso que queremos recuperar, se utiliza el protocolo URL para esto, el nombre del recuros tiene que ser único.  &lt;li&gt;Por último la versión del protocolo &lt;/li&gt;&lt;/ul&gt; &lt;p&gt;ok, esto está muy bien, pero no nos quedemos con mis dichos, vamos a verificarlo.  &lt;p&gt;&amp;nbsp; &lt;h3&gt;Armando nuestra primer petición HTTP a mano &lt;/h3&gt; &lt;p&gt;Vamos a hacer el papel de navegador Web, para eso vamos a ejecutar el &lt;a href="http://www.fiddler2.com/fiddler2/"&gt;Fiddler&lt;/a&gt; e ir a la ventana que dice "Request Builder", dentro de ella a la opción "Raw" (que quiere decir "a lo macho") y escribimos exáctamente el request que acabamos a analizar, pero no nos olvidemos de hacer dos veces ENTER o sea, dejar una línea en blanco (por definición antes del cuerpo hay que dejarla) .  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/_t9Bh42Thfqo/TamYOBTlLqI/AAAAAAAAASg/XUST07q1C5E/s1600-h/image%5B4%5D.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://lh3.ggpht.com/_t9Bh42Thfqo/TamYPEzVvfI/AAAAAAAAASk/ZV_89vZY3OM/image_thumb%5B2%5D.png?imgmax=800" width="653" height="288"&gt;&lt;/a&gt;  &lt;p&gt;Hacemos "execute" y..mágia (ignoremos el cartel que pone Fiddler sobre violación de protocolo por falta del header “host” por el momento). Bing nos responde!  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/_t9Bh42Thfqo/TamYQLS9FII/AAAAAAAAASo/Dpw9j1gcoQA/s1600-h/image%5B8%5D.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://lh3.ggpht.com/_t9Bh42Thfqo/TamYRV7IvfI/AAAAAAAAASs/QuzsvQzI3r0/image_thumb%5B4%5D.png?imgmax=800" width="654" height="278"&gt;&lt;/a&gt;  &lt;p&gt;En la columna de la derecha vemos las transacciones y en la izquierda seleccionado “Insepections” y luego “Raw” podemos ver arriba el requerimiento que armamos y debajo la respuesta, vamos a analizar lo más importante (por ahora) de la respuesta.  &lt;p&gt;&amp;nbsp; &lt;h4&gt;Analizando la respuesta &lt;/h4&gt; &lt;p&gt;De todo lo que vamos a ver en la respuesta en este caso nos vamos a concentrar en lo que nos dicen los siguientes datos:  &lt;p&gt;&lt;strong&gt;HTTP /1.1 200 OK&lt;br&gt;Content-Type: text/html &lt;/strong&gt; &lt;p&gt;estos son los datos más importantes (de momento) dentro de una respuesta.  &lt;p&gt;&lt;strong&gt;HTTP /1.1&lt;/strong&gt; la versión del protocolo  &lt;p&gt;&lt;strong&gt;200 OK&lt;/strong&gt; el código de estado y la descripción, en este caso 200 significa que la petición fue exitosa  &lt;p&gt;&lt;strong&gt;Content-Type: text/html&lt;/strong&gt; el tipo de contenido, ya que HTTP transporta texto necesitamos sabes la naturaleza de los datos para saber cómo interpretarlos, por ejemplo si el contenido fuese una imagen JPG el encabezado sería  &lt;p&gt;&lt;strong&gt;Content-Type: image/jpg&lt;/strong&gt;  &lt;p&gt;a la codificación que se utiliza en el encabezado Content-Type se la conoce como &lt;a href="http://en.wikipedia.org/wiki/MIME"&gt;MIME type&lt;/a&gt;, hay uno para cada tipo de contenido, notemos que el navegador se va a basar en él para saber qué hacer con el contenido (la extensión del recurso se ignora), en caso de ser un contenido que puede manipular (por ejemplo text/html) lo hará, sino buscará un programa relacionado para hacerlo, por ejemplo con el MIME Type application/ms-word el navegador sabe que tiene tiene que llamar al MSWord.  &lt;p&gt;Lo que viene después de todos los encabezados y luego de una linea en blanco es la página de Bing, o sea el contenido, en definitiva el recurso que estámos pidiendo.  &lt;p&gt;&amp;nbsp; &lt;h3&gt;Armando nuestro propio Web server&lt;/h3&gt; &lt;p&gt;Vamos a demostar lo mismo que antes pero jugando el papel de Web server, es decir, desde el navegador vamos a pedir un recurso a un web server hecho por nosotros, manos a la obra.  &lt;p&gt;&lt;a href="http://lh6.ggpht.com/_t9Bh42Thfqo/TaoudcEy_UI/AAAAAAAAASw/MtOG3dbnIaA/s1600-h/image%5B12%5D.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://lh3.ggpht.com/_t9Bh42Thfqo/TaoueZXLf9I/AAAAAAAAAS0/UBc6EbCP8rk/image_thumb%5B6%5D.png?imgmax=800" width="640" height="574"&gt;&lt;/a&gt;  &lt;p&gt;Haciendo abuso de mis conocimiento de programación hice un web server en 30 líneas que además de despachar archivos nos indica un error 404 si no encuentra algo, vamos a probarlo.  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/_t9Bh42Thfqo/TaoufYaQ7uI/AAAAAAAAAS4/HacBjs7idsk/s1600-h/image%5B16%5D.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://lh4.ggpht.com/_t9Bh42Thfqo/TaougNtxaGI/AAAAAAAAAS8/Wv__RKB0jqA/image_thumb%5B8%5D.png?imgmax=800" width="651" height="287"&gt;&lt;/a&gt;  &lt;p&gt;Mágia, de más está decir que tengo un archivo “default.htm” en el directorio “C:\temp\pruebasVS2010\minweb\minweb\files” con ese increíble contenido, pero no seamos confiados, vamos a ver si funciona cuando no existe el recurso  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/_t9Bh42Thfqo/Taoug7CnPFI/AAAAAAAAATA/GoEtgIgFOow/s1600-h/image%5B20%5D.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://lh5.ggpht.com/_t9Bh42Thfqo/TaouiI4Cw3I/AAAAAAAAATE/WcXI5U5LdO0/image_thumb%5B10%5D.png?imgmax=800" width="663" height="445"&gt;&lt;/a&gt;  &lt;p&gt;Increíble no? no nos muestra el mensaje que pusimos porque por defecto IE muestra una mensaje “amigable”, probemos con Firefox  &lt;p&gt;&lt;a href="http://lh6.ggpht.com/_t9Bh42Thfqo/Taoui9rQMxI/AAAAAAAAATI/RTwdiNz2tT8/s1600-h/image%5B24%5D.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://lh4.ggpht.com/_t9Bh42Thfqo/Taoujlm3UbI/AAAAAAAAATM/fZxbZ_RHDZQ/image_thumb%5B12%5D.png?imgmax=800" width="672" height="324"&gt;&lt;/a&gt;  &lt;p&gt;Notable, ahora vamos a demostrar que no importa la extension sino que estos navegadores al no enviar nosotros el encabezado “Content-Type” por defecto interpretan HTML, vamos a forzarlos a que llame al lector de PDF configurado en nuestro sistema.  &lt;p&gt;&amp;nbsp; &lt;h3&gt;Forzando al navegador a llamar al lectro de PDF&lt;/h3&gt; &lt;p&gt;El Content-Type lo vamos a ponder como “application/octet-stream” para indicar que es un archivos binario, y vamos a agregar un header con el nombre del archivo destino para que el sistema operativo llame al lector de PDF configurado.  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/_t9Bh42Thfqo/TasypeuIa9I/AAAAAAAAATQ/N6b5zZtQ_jE/s1600-h/image%5B32%5D.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://lh3.ggpht.com/_t9Bh42Thfqo/TasyqmG5vgI/AAAAAAAAATU/jsCBJtha5vU/image_thumb%5B16%5D.png?imgmax=800" width="675" height="367"&gt;&lt;/a&gt;  &lt;p&gt;Hecho esto, no queda más que probarlo, y….  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/_t9Bh42Thfqo/Tasyr-L-PoI/AAAAAAAAATY/1sHdHvoh7U0/s1600-h/image%5B28%5D.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://lh5.ggpht.com/_t9Bh42Thfqo/TasytUoswvI/AAAAAAAAATc/WpJOWQQNmHQ/image_thumb%5B14%5D.png?imgmax=800" width="682" height="295"&gt;&lt;/a&gt;  &lt;h3&gt;&amp;nbsp;&lt;/h3&gt; &lt;h3&gt;El POST y el GET&lt;/h3&gt; &lt;p&gt;Ok, hasta ahora usamos el verbo GET para recuperar contenido, esto está muy bien, pero qué pasa si necesitamos pasar parámetros al servidor para recuperar el contenido, por ejemplo queremos recuperar información de un usuario pero necesitamos indicar de qué usuario, entonces usamos lo que se conoce como “Query String” que no es más que agregar los parámetros al final de la dirección URL y es parte del estándar, sería algo así:  &lt;p&gt;&lt;a href="http://localhost/detalleUsuario.aspx?id=1"&gt;http://localhost/detalleUsuario.aspx?id=1&lt;/a&gt;  &lt;p&gt;Donde el “Query string” es todo lo que está después del signo de interrogación, y tiene la forma “nombre=valor” en este caso “id=1”.  &lt;p&gt;Esto está muy bien, entonces por qué si queremos ingresar nuestro usuarios y contraseña por qué no enviarlos como parte del query string? hay varias respuestas para esta pregunta  &lt;ul&gt; &lt;li&gt;El largo máximo de la URL total, si bien HTTP no especifica un largo máximo hay varios límites, tal vez lo más importante sea que &lt;a href="http://support.microsoft.com/kb/208427"&gt;IE6 limita a 2086 el largo&lt;/a&gt;, algunos servidores a 256…en definitiva no vale la pena arriesgarse a superar 256.  &lt;li&gt;Hacerlo por GET implica que la URL + los parámetros van a ser visibles en la barra de navegador.  &lt;li&gt;Se puede guardar en favoritos si es una dirección.  &lt;li&gt;Sintácticamente para enviar datos se tiene que usar POST y no GET&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;Si bien alguna de estas desventajas pueden ser ventajas dependiendo de lo que querramos hacer, por ejemplo si tenemos un sitio de ventas por internet es interesante que una búsqueda se pueda ver en la barra de naveagación para poder compartirla, por ejemplo los buscadores usan formularios con el verbo GET para que podamos guardar la búsqueda. &lt;p&gt;&lt;a href="http://lh6.ggpht.com/_t9Bh42Thfqo/Tat4Geht64I/AAAAAAAAAUI/tEgmicwB_mk/s1600-h/image%5B65%5D.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://lh6.ggpht.com/_t9Bh42Thfqo/Tat4HrTMloI/AAAAAAAAAUM/GnCRUgvEiJ8/image_thumb%5B33%5D.png?imgmax=800" width="509" height="238"&gt;&lt;/a&gt;  &lt;p&gt;Hay un lugar en donde podemos enviar toda la información que querramos y además no es visible para el usuario (no se ve en la barra de navegación) y es mediante el verbo POST ya que los datos los podemos poner en el cuerpo del mensaje (si ponemos información en el cuerpo y usamos GET el servidor lo va a ignorar).  &lt;p&gt;&amp;nbsp; &lt;h3&gt;“Posteando” datos&lt;/h3&gt; &lt;p&gt;Sí, la expresión “voy a postear” viene del verbo POST de HTTP, para postear simplemente hay que cambiar el verbo a POST en el paquete HTTP, el resto es igual, incluso podemos seguir usando query string, desde HTML es necesario utilizar un elemento Form (formulario) para hacer POST, si bien, podemos cambiarlo para que el formulario envíe usando GET (que es el método por defecto de los formularios).  &lt;p&gt;Vamos a hacer un formulario HTML y ver con Fiddler por dónde van los datos  &lt;p&gt;&lt;a href="http://lh6.ggpht.com/_t9Bh42Thfqo/TatvO72zZcI/AAAAAAAAATg/mEC0RhsThcY/s1600-h/image%5B36%5D.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://lh3.ggpht.com/_t9Bh42Thfqo/TatvPsEpYyI/AAAAAAAAATk/WtAIlE_8l74/image_thumb%5B18%5D.png?imgmax=800" width="526" height="259"&gt;&lt;/a&gt;  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/_t9Bh42Thfqo/TatvQElvDpI/AAAAAAAAATo/LJ8vWBpzsPs/s1600-h/image%5B40%5D.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://lh6.ggpht.com/_t9Bh42Thfqo/TatvRHIuhdI/AAAAAAAAATs/UxmyvV0cGUo/image_thumb%5B20%5D.png?imgmax=800" width="501" height="326"&gt;&lt;/a&gt;  &lt;p&gt;Presionamos “enviar datos” vamos al Fiddler y vemos que los datos del formulario están en el cuerpo del mensaje, los nombres de los elementos se toman de cada atributo “name” de cada elemento dentro del formulario.  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/_t9Bh42Thfqo/TatvSEifQzI/AAAAAAAAATw/7C46Mh9q9fI/s1600-h/image%5B48%5D.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://lh3.ggpht.com/_t9Bh42Thfqo/TatvTNf3x9I/AAAAAAAAAT0/jlABICGL3_s/image_thumb%5B24%5D.png?imgmax=800" width="568" height="351"&gt;&lt;/a&gt;  &lt;p&gt;Por supuesto que nuestro web server devuelve error 404 porque no existe el recurso “destino.htm” &lt;/p&gt; &lt;h3&gt;Leyendo datos de POST desde el web server&lt;/h3&gt; &lt;p&gt;Modificamos levemente el código de nuestro web server para leer datos del POST&lt;/p&gt; &lt;p&gt;&lt;a href="http://lh3.ggpht.com/_t9Bh42Thfqo/TatvUIEbuoI/AAAAAAAAAT4/JPwDZ1NsDhk/s1600-h/image%5B53%5D.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://lh4.ggpht.com/_t9Bh42Thfqo/TatvVNoENFI/AAAAAAAAAT8/zL5eV0dwzQ8/image_thumb%5B27%5D.png?imgmax=800" width="594" height="416"&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;ejecutamos otra vez default.htm con el formulario y listo, tenemos los datos en la consola!&lt;/p&gt; &lt;p&gt;&lt;a href="http://lh5.ggpht.com/_t9Bh42Thfqo/TatvVyFavtI/AAAAAAAAAUA/KKGhCHjcUW0/s1600-h/image%5B57%5D.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://lh3.ggpht.com/_t9Bh42Thfqo/TatvWgRVwyI/AAAAAAAAAUE/OQ1U-AJfjnw/image_thumb%5B29%5D.png?imgmax=800" width="601" height="364"&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;De esta manera verificamos que los datos vienen en el cuerpo del mensaje cuando usamos el verbo HTTP POST.&lt;/p&gt; &lt;p&gt;Es todo por esta vez. En la próximos post vamos a ver cómo se hace para mantener el estado sobre un protocolo sin estado, qué podemos hacer con los códigos de estado y otras cosas locas, nos leemos.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;Leonardo Micheloni&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/148524916779753368-114900741835380847?l=leomicheloni.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://leomicheloni.blogspot.com/feeds/114900741835380847/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=148524916779753368&amp;postID=114900741835380847' title='1 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default/114900741835380847'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default/114900741835380847'/><link rel='alternate' type='text/html' href='http://leomicheloni.blogspot.com/2011/04/introduccion-http-las-ruedas-de-la-web.html' title='Introducción a HTTP, las ruedas de la web'/><author><name>Leonardo Micheloni</name><uri>http://www.blogger.com/profile/12085246040181097881</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='30' src='http://3.bp.blogspot.com/_t9Bh42Thfqo/S6TVOJqYWcI/AAAAAAAAANU/MlZc6HpYZis/S220/yo+laguito+en+col%C3%B3n.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh3.ggpht.com/_t9Bh42Thfqo/TamYPEzVvfI/AAAAAAAAASk/ZV_89vZY3OM/s72-c/image_thumb%5B2%5D.png?imgmax=800' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-148524916779753368.post-6802648982005012649</id><published>2011-04-05T23:29:00.001-03:00</published><updated>2011-04-05T23:29:16.988-03:00</updated><title type='text'>SharpTestEx extensiones para hacer las pruebas unitarias más alegres</title><content type='html'>&lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;Cuando hacemos mucha prueba unitaria (Unit Test) nos encontramos a menudo con tareas similares como evaluar si un número está dentro de un rango, si una colección contiene cierta cantidad de ítems, y cosas así para las cuales nuestro amado .NET Framework no está dotado de funciones ya listas para usar “out of the box” sino más bien tenemos que hacer algunos “Helpers” y cosas así para poder probar más felizmente.&lt;/p&gt; &lt;h3&gt;SharpTestEx&lt;/h3&gt; &lt;p&gt;El amigo &lt;a href="http://fabiomaulo.blogspot.com/"&gt;Fabio Maulo&lt;/a&gt; en el tiempo que le queda siendo el project leader de NHibernate, manteniendo su propio framework para mapeos de &lt;a href="http://nhforge.org/"&gt;NHibernate&lt;/a&gt;, &lt;a href="http://code.google.com/p/codeconform/"&gt;ConfORM&lt;/a&gt;, trabajar y otras cosas, se hizo un rato y se escribió un conjunto de métodos de extensión para ampliar las funcionalidades del Framework. :)&lt;/p&gt; &lt;p&gt;Básicamente son métodos de extensión que extienden la clase object, con lo cual con agregar la referencia a la única DLL de &lt;a href="http://sharptestex.codeplex.com/"&gt;SharpTestEx&lt;/a&gt; ya contamos con toda su potencia, que nos pemite hacer cosas como esta:&lt;/p&gt; &lt;h3&gt;Sintáxis fluyente y auto-descriptiva&lt;/h3&gt; &lt;p&gt;[TestMethod]&lt;br&gt;public void TestMethod1()&lt;br&gt;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; var texto = "mi vieja mula ya no es lo que era";  &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; texto.Should().Contain("mula");&lt;br&gt;} &lt;p&gt;Notemos que el objeto texto (que no es más que un string) ahora tiene un método Should() que indica que debería cumplir concierta condición, en este caso se leería&lt;/p&gt; &lt;p&gt;&lt;em&gt;texto debería contener “mula”&lt;/em&gt;&lt;/p&gt; &lt;p&gt;bien descriptivo, con esta sintáxis ya está listo el test, si la condición no se cumple SharpTestEx lanza una bonita excepción que además nos dice exáctamente qué pasó, mágico.&lt;/p&gt; &lt;h3&gt;Potencia por todos lados&lt;/h3&gt; &lt;p&gt;SharpTestEx tiene un arsenal de métodos que nos facilitan la vida cada día, Fabio es un tipo que programa mucho y sabe mucho qué necesita un programador a la hora de probar. Sino miren las &lt;a href="http://www.ohloh.net/accounts/fabiomaulo"&gt;estadísticas de Fabio en Ohloh.&lt;/a&gt;&lt;/p&gt; &lt;p&gt;public void TestMethod2()&lt;br&gt;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; var valorBoleano = false;  &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; valorBoleano.Should().Be.False();&lt;br&gt;} &lt;p&gt;Otro ejemplo de la rica sintáxis, lo interesante de que el código sea quien describe lo que va a pasar en lugar de agregar un pila de comentarios es que cuando cambiemos el código para que se comporte de otra manera ya tenemos la auto-documentación actualizada, por lo menos en mi experiencia los comentarios si son muchos suelen quedar obsoletos, pero es una opinión personal.&lt;/p&gt; &lt;p&gt;public void TestMethod()&lt;br&gt;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; var valorNumerico = 110;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; valorNumerico.Should().Be.GreaterThanOrEqualTo(100);&lt;br&gt;} &lt;p&gt;Otro ejemplo muy claro, el método GreaterThanOrEqualTo nos soluciona unos cuantos problemas si&amp;nbsp; quisiéramos hacerlo a mano.&lt;/p&gt; &lt;p&gt;public void TestMethod()&lt;br&gt;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; var listaEnteros = new[] { 1, 2, 3 };  &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; listaEnteros.Should()&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; .Not.Be.Null()&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; .And.Not.Be.Empty()&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; .And.Not.Have.SameSequenceAs(new[] { 3, 2, 1 })&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; .And.Have.UniqueValues();  &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; listaEnteros.Should().Contain(2).And.Not.Contain(4);  &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; listaEnteros.Should().Contain(3).And.Not.Have.Count.LessThan(2);&lt;br&gt;} &lt;p&gt;Este ejemplo copiado del &lt;a href="http://sharptestex.codeplex.com/wikipage?title=AssertionIEnumerable&amp;amp;referringTitle=Documentation"&gt;sitio de Codeplex&lt;/a&gt; nos muestra la versatilidad para verificar IEnumerables&amp;lt;T&amp;gt; (colecciones) y que además podemos encadenar validaciones, más que mágico!&lt;/p&gt; &lt;h3&gt;Detalles finales&lt;/h3&gt; &lt;p&gt;Lo único que me queda decir es que sin duda SharpTestEx es una herramienta que siempre nos va a facilitar las cosas, un detalle es que hay un assembly (DLL) según el framework de Unit Testing que usemos, por ejemplo yo usé MSTest el que viene integrado dentro de Visual Studio y agregué el using al principio de los test para “ver” los métodos de extensión.&lt;/p&gt; &lt;p&gt;using SharpTestsEx;&lt;/p&gt; &lt;p&gt;Nada más, nos vemos la próxima.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;Leonardo Micheloni&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/148524916779753368-6802648982005012649?l=leomicheloni.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://leomicheloni.blogspot.com/feeds/6802648982005012649/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=148524916779753368&amp;postID=6802648982005012649' title='2 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default/6802648982005012649'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default/6802648982005012649'/><link rel='alternate' type='text/html' href='http://leomicheloni.blogspot.com/2011/04/sharptestex-extensiones-para-hacer-las.html' title='SharpTestEx extensiones para hacer las pruebas unitarias más alegres'/><author><name>Leonardo Micheloni</name><uri>http://www.blogger.com/profile/12085246040181097881</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='30' src='http://3.bp.blogspot.com/_t9Bh42Thfqo/S6TVOJqYWcI/AAAAAAAAANU/MlZc6HpYZis/S220/yo+laguito+en+col%C3%B3n.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-148524916779753368.post-7791548387485691405</id><published>2011-01-04T13:02:00.000-03:00</published><updated>2011-01-04T14:11:24.145-03:00</updated><title type='text'>Año nuevo, objetivos nuevos</title><content type='html'>&lt;p&gt;Comienza un nuevo año y con él vienen las declaraciones de deseos y objetivos, y bueno, acá van los mios:&lt;/p&gt; &lt;h4&gt;Nuevo hospedaje para el blog&lt;/h4&gt; &lt;p&gt;Muchas veces me preguntaron por qué no pongo Add-Algo en el sitio para ganar un pesos y la respuesta es “porque no es la idea” además todos sabemos que si yo gano $1 Google gana $2, entonces esa reflexión se extiende a “no quiero regalarle plata a Google”, tanto es así que voy a migar este blog en algún momento del año a otra plataforma y otro hosting, posiblemente uno de pago y sobre WordPress.&lt;/p&gt; &lt;h4&gt;Escribir un Libro sobre programación usando SCRUM&lt;/h4&gt; &lt;p&gt;Muchas veces me llegaron consultas para que recomiende libros sobre programación en .Net y mi respuesta siempre fue la misma “no sé, la verdad es que no conozco ninguno recomendable” pero no me quedé nunca conforme con la respuesta, por lo tanto voy a tomar el toro por las astas y hacerlo yo, como declaración dejo lo único que por ahora tengo claro sobre el libro:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;Será en Castellano  &lt;li&gt;Será público  &lt;li&gt;Será sobre .Net  &lt;li&gt;Será sobre C#  &lt;li&gt;Comenzará desde POO, incluyendo conceptos de clases, objetos, interfaces, polimorfísmo, etc.  &lt;li&gt;No tocará temas sobre Winforms  &lt;li&gt;Habrá conceptos web de base, http, html, xml, etc. siempre es mejor comprender lo que pasa  &lt;li&gt;Se hablará de herramientas como Reflector, Fiddler y otras.  &lt;li&gt;Hablará de patrones que yo uso, y no de cosas demasíado poco comunes y que confunden más de lo que aclaran.  &lt;li&gt;Se tocará mucho el temas de test de unidad  &lt;li&gt;Se hablará de mocking y moq.  &lt;li&gt;Se hablará sobre legibildiad de código, comentarios, etc.  &lt;li&gt;Se hablará de frameworks como MVC  &lt;li&gt;Se hablará de Javascript  &lt;li&gt;Se hablará de jQuery&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;Y mucho más, es ambicioso, pero como si fuera poco lo pienso desarrollar usando SCRUM, de la siguiente manera:&lt;/p&gt; &lt;p&gt;La lista anterior sería un backlog del producto, la visión es la siguiente: “Escribir un libro de programación en .net que toque los temas básicos que muchos libros dan por obvios y abarque los conceptos y herramientas de todos los días”.&lt;/p&gt; &lt;p&gt;El modelo de desarrollo será Scrum con sprint mensuales, por supuesto, el resultado de cada sprint es un entregable.&lt;/p&gt; &lt;p&gt;En fin, es una primera aproximación, me falta definir la fecha de inicio, voy a ir refinando el backlog el cual pronto publicaré de modo público.&lt;/p&gt; &lt;p&gt;Saludos, Leonardo.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;Leonardo Micheloni&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/148524916779753368-7791548387485691405?l=leomicheloni.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://leomicheloni.blogspot.com/feeds/7791548387485691405/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=148524916779753368&amp;postID=7791548387485691405' title='14 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default/7791548387485691405'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default/7791548387485691405'/><link rel='alternate' type='text/html' href='http://leomicheloni.blogspot.com/2011/01/ano-nuevo-objetivos-nuevos.html' title='Año nuevo, objetivos nuevos'/><author><name>Leonardo Micheloni</name><uri>http://www.blogger.com/profile/12085246040181097881</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='30' src='http://3.bp.blogspot.com/_t9Bh42Thfqo/S6TVOJqYWcI/AAAAAAAAANU/MlZc6HpYZis/S220/yo+laguito+en+col%C3%B3n.jpg'/></author><thr:total>14</thr:total></entry><entry><id>tag:blogger.com,1999:blog-148524916779753368.post-2003354640731522379</id><published>2010-10-17T00:09:00.002-03:00</published><updated>2010-10-18T16:05:34.955-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='desarrollo ágil'/><title type='text'>El pajarraco Scrumero</title><content type='html'>&lt;p&gt;&lt;b&gt;Introducción&lt;/b&gt;&lt;/p&gt; &lt;p&gt;&lt;a href="http://lh6.ggpht.com/_t9Bh42Thfqo/TLpoioKBFBI/AAAAAAAAARQ/ZrbJo9vTJmc/s1600-h/CIMG0667%5B3%5D.jpg"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="CIMG0667" border="0" alt="CIMG0667" src="http://lh4.ggpht.com/_t9Bh42Thfqo/TLpokIZN8aI/AAAAAAAAARU/GpdE71F_tis/CIMG0667_thumb%5B1%5D.jpg?imgmax=800" width="641" height="267"&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;El miércoles trece de octubre pasado en el marco de la materia “Arquitectura Web” que tengo el gusto de dictar en la universidad &lt;a href="http://www.caece.edu.ar/index.asp"&gt;CAECE&lt;/a&gt; vivimos una experiencia muy gratificante.&lt;/p&gt; &lt;p&gt;Como parte de una humilde evangelización de metodología ágiles al principio de la cursada se dicta una clase introductoria a SCRUM, mi idea siempre fue hacerlo más práctico entonces envié una pregunta sobre cómo podría hacer una práctica grupal de introducción a la &lt;a href="http://www.agiles.org/"&gt;lista de ágiles&lt;/a&gt;, como era de esperar recibí muchísimas sugerencias pero además recibí un mail privado de &lt;a href="http://tierraygirasoles.blogspot.com/"&gt;Ingrid Astiz&lt;/a&gt; ofreciéndose a venir ella personalmente a hacer el &lt;a href="http://tierraygirasoles.blogspot.com/2010/09/juego-del-pajarraco.html"&gt;juego del pajarraco&lt;/a&gt; obra del gran &lt;a href="http://twitter.com/acyment"&gt;Alan Cyment&lt;/a&gt;.&lt;/p&gt; &lt;p&gt;Después de coordinar unas semanas llegó el día y recibimos a Ingrid en el aula.&lt;/p&gt; &lt;p&gt;&lt;a href="http://lh6.ggpht.com/_t9Bh42Thfqo/TLpolWyez9I/AAAAAAAAARY/IzMFY_OcMgk/s1600-h/CIMG0666%5B2%5D.jpg"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="CIMG0666" border="0" alt="CIMG0666" src="http://lh3.ggpht.com/_t9Bh42Thfqo/TLponPOgzrI/AAAAAAAAARc/S42IzMmWRAU/CIMG0666_thumb.jpg?imgmax=800" width="244" height="184"&gt;&lt;/a&gt; &lt;a href="http://lh3.ggpht.com/_t9Bh42Thfqo/TLpooMM4i1I/AAAAAAAAARg/Mb9OGFvh4X4/s1600-h/CIMG0668%5B2%5D.jpg"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="CIMG0668" border="0" alt="CIMG0668" src="http://lh5.ggpht.com/_t9Bh42Thfqo/TLpoo2lHWiI/AAAAAAAAARk/Vn7oa9OVKjY/CIMG0668_thumb.jpg?imgmax=800" width="244" height="184"&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;&lt;b&gt;La dinámica del juego&lt;/b&gt;&lt;/p&gt; &lt;p&gt;Se armaron cinco grupos de alumnos que con una caja de &lt;a href="http://www.rasti.com.ar/"&gt;RASTIS&lt;/a&gt; cada uno.&lt;/p&gt; &lt;p&gt;Se organizaron planning meetings de 5’, sprints de 10’, reviews de 2’ y retrospectivas de 2’, este ciclo se repitió 3 veces, todos los alumnos participaron con mucho entusiasmo de la actividad y esto quedó reflejado cuando después de terminado el ejercicio hicimos entre todos una retrospectiva sobre la actividad donde surgieron preguntas sobre metodologías ágiles y grupos de trabajo, esta retrospectiva duró más de una hora.&lt;/p&gt; &lt;p&gt;&lt;a href="http://lh5.ggpht.com/_t9Bh42Thfqo/TLpopmZUTfI/AAAAAAAAARo/4XlJCd7zsNE/s1600-h/CIMG0671%5B2%5D.jpg"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="CIMG0671" border="0" alt="CIMG0671" src="http://lh4.ggpht.com/_t9Bh42Thfqo/TLpotI3NjfI/AAAAAAAAARs/8lsxTR96YVk/CIMG0671_thumb.jpg?imgmax=800" width="184" height="244"&gt;&lt;/a&gt; &lt;a href="http://lh3.ggpht.com/_t9Bh42Thfqo/TLpozvUudlI/AAAAAAAAARw/PeQFX7qkaGo/s1600-h/CIMG0669%5B2%5D.jpg"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="CIMG0669" border="0" alt="CIMG0669" src="http://lh6.ggpht.com/_t9Bh42Thfqo/TLpo0WcKtTI/AAAAAAAAAR0/h1_zYe0_jec/CIMG0669_thumb.jpg?imgmax=800" width="244" height="184"&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;La actividad ayudó mucho a la integración y a la comprensión de la metodología y demuestra que no sólo se puede usar una metodología ágil para desarrollar software, durante la actividad salieron a la superficie los mismos errores y soluciones que en un proyecto real, por supuesto a partir de ahora lo vamos a practicar en cada cursada.&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Aspectos sobresalientes:&lt;/strong&gt;&lt;/p&gt; &lt;ul&gt; &lt;li&gt;La autogestión de los equipos, sprint tras sprint se iban encontrando los roles.&lt;/li&gt; &lt;li&gt;El surgimiento de líderes naturales, que van apareciendo según la situación.&lt;/li&gt; &lt;li&gt;Preguntar, dejar de lado supuestos y repreguntar.&lt;/li&gt; &lt;li&gt;Retrospectiva, parar la pelota y pensar qué de hizo mal y qué se puede mejorar.&lt;/li&gt; &lt;li&gt;Le estimación, todos los equipos fueron encontrando su propio ritmo de trabajo después de cada sprint.&lt;/li&gt; &lt;li&gt;La sinergia que surgió naturalmente cuando todos siente el objetivo como propio y se reconocen como iguales.&lt;/li&gt; &lt;li&gt;La integración del grupo.&lt;/li&gt; &lt;li&gt;El diseño emergente, la comprensión del producto incremental.&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;&lt;a href="http://lh5.ggpht.com/_t9Bh42Thfqo/TLpo1cV9RlI/AAAAAAAAAR4/V79ENi85unA/s1600-h/CIMG0687%5B5%5D.jpg"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="CIMG0687" border="0" alt="CIMG0687" src="http://lh5.ggpht.com/_t9Bh42Thfqo/TLpo15CvO6I/AAAAAAAAAR8/QmSK3wMMkJA/CIMG0687_thumb%5B1%5D.jpg?imgmax=800" width="184" height="244"&gt;&lt;/a&gt; &lt;a href="http://lh6.ggpht.com/_t9Bh42Thfqo/TLpo2ooFX-I/AAAAAAAAASA/Cn7X6hLryLI/s1600-h/CIMG0688%5B2%5D.jpg"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="CIMG0688" border="0" alt="CIMG0688" src="http://lh3.ggpht.com/_t9Bh42Thfqo/TLpo41SB3BI/AAAAAAAAASE/BNOvyOJEGZ0/CIMG0688_thumb.jpg?imgmax=800" width="184" height="244"&gt;&lt;/a&gt; &lt;a href="http://lh3.ggpht.com/_t9Bh42Thfqo/TLpo5lXuq7I/AAAAAAAAASI/BwqFG2VUn5k/s1600-h/CIMG0676%5B2%5D.jpg"&gt;&lt;img title="CIMG0676" border="0" alt="CIMG0676" src="http://lh6.ggpht.com/_t9Bh42Thfqo/TLpo6_f8_gI/AAAAAAAAASM/ywJqF2I5NXI/CIMG0676_thumb.jpg?imgmax=800" width="184" height="244"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;Agradezco infinitamente a Ingrid por su voluntad y generosidad, a Marcela y Vero por ayudarnos, hasta la próxima.&lt;/p&gt; &lt;p&gt;&lt;a href="http://lh3.ggpht.com/_t9Bh42Thfqo/TLpo8dhTA2I/AAAAAAAAASQ/kEyurXtD_Z8/s1600-h/todos%5B3%5D.jpg"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="todos" border="0" alt="todos" src="http://lh4.ggpht.com/_t9Bh42Thfqo/TLpo9B3phLI/AAAAAAAAASU/GZPRJ3obxtc/todos_thumb%5B1%5D.jpg?imgmax=800" width="675" height="267"&gt;&lt;/a&gt;&lt;/p&gt; &lt;div class="blogger-post-footer"&gt;Leonardo Micheloni&lt;/div&gt;  &lt;div class="blogger-post-footer"&gt;Leonardo Micheloni&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/148524916779753368-2003354640731522379?l=leomicheloni.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://leomicheloni.blogspot.com/feeds/2003354640731522379/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=148524916779753368&amp;postID=2003354640731522379' title='5 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default/2003354640731522379'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default/2003354640731522379'/><link rel='alternate' type='text/html' href='http://leomicheloni.blogspot.com/2010/10/el-pajarraco-scrumero.html' title='El pajarraco Scrumero'/><author><name>Leonardo Micheloni</name><uri>http://www.blogger.com/profile/12085246040181097881</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='30' src='http://3.bp.blogspot.com/_t9Bh42Thfqo/S6TVOJqYWcI/AAAAAAAAANU/MlZc6HpYZis/S220/yo+laguito+en+col%C3%B3n.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh4.ggpht.com/_t9Bh42Thfqo/TLpokIZN8aI/AAAAAAAAARU/GpdE71F_tis/s72-c/CIMG0667_thumb%5B1%5D.jpg?imgmax=800' height='72' width='72'/><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-148524916779753368.post-4130474745066912084</id><published>2010-07-31T13:34:00.001-03:00</published><updated>2010-07-31T13:36:40.062-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='MSBuild'/><title type='text'>Introducción a Builds automáticos o “Cómo corno funciona MSBuild”</title><content type='html'>&lt;p&gt;En ambientes de desarrollo medianamente profesionales es una práctica muy común contar con Builds automáticos, esto significa que tenemos un mecanismo que por si sólo en algún momento se hace del código fuente de nuestra aplicación, lo compila, corre las pruebas unitarias y publica los resultados. Es una gran idea, por ejemplo, podemos tener configurado para que todas las noches (porque puede ser un proceso muy pesado para hacerlo cuando la gente trabaja) nuestro BuildServer (el servidor donde tenemos configurada toda esta magia) se comunica con el control de código, baja la última versión de todo, compila, corre las pruebas, etc. y nos envía un bonito mail con el resultado.&lt;/p&gt;  &lt;p&gt;Básicamente tenemos que poder contar con una herramienta que se encargue de esta automatización, casi que con mucha habilidad podemos hacerlo con el programador de taras de windows y crear tareas que ejecuten los siguientes pasos:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Bajen la última versión del código del repositorio &lt;/li&gt;    &lt;li&gt;Compilen todo en Release &lt;/li&gt;    &lt;li&gt;Corran las pruebas unitarias &lt;/li&gt;    &lt;li&gt;Adicionalmente puede verificar otra cosas como Code coverage o políticas de revisión de código, etc. &lt;/li&gt;    &lt;li&gt;Publique los resultados en un lugar de la red &lt;/li&gt;    &lt;li&gt;Nos envíen el resultado por mail &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;&lt;strong&gt;La idea detrás de esto&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;La idea final sería que si trabajamos en un equipo sobre un sistema medianamente complejo asegurarnos que nuestros cambios no rompen cosas que depende de él y viceversa, adicionalmente publique los resultados para que se encuentren disponibles para probarlos, de esta manera todos los días tendríamos la última versión (en desarrollo) lista para ser probada con un nivel de prueba de caja blanca muy bueno (siempre va a depender de nuestras pruebas unitarias) &lt;strike&gt;por lo menos sabemos que compila&lt;/strike&gt;.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Herramientas para Builds automáticos&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;No, no vamos a usar el programador de tareas, pero no por falta de valor sino porque ya existen herramientas que no sólo permiten programar tareas de este tipo, sino que además traen tareas para:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Comunicarse con control de código: TFS, VSS, SVN, Mercurial, etc. &lt;/li&gt;    &lt;li&gt;Llamar al compilador &lt;/li&gt;    &lt;li&gt;Correr los test unitarios: MSTest, NUnit, MBUnit, etc. &lt;/li&gt;    &lt;li&gt;Ejecutar políticas de codecoverage: Visual studio, etc. &lt;/li&gt;    &lt;li&gt;Enviar Mails. &lt;/li&gt;    &lt;li&gt;Etc. &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Otra cosas muy interesante que estas herramientas suelen traer es la posibilidad de ser disparadas por distintos eventos:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;En algún momento del día &lt;/li&gt;    &lt;li&gt;Un día particular de la semana &lt;/li&gt;    &lt;li&gt;Al hacer check-in del código &lt;/li&gt;    &lt;li&gt;Al hacer una cantidad de check-ins &lt;/li&gt;    &lt;li&gt;etc. &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Hay varias aplicaciones para hacer esto, entre las más conocidas (por mí al menos) tenemos:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;a href="http://nant.sourceforge.net/"&gt;NAnt&lt;/a&gt;: Port del Ant para .NET &lt;/li&gt;    &lt;li&gt;&lt;a href="http://cruisecontrol.sourceforge.net/"&gt;CruiseControl&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/wea2sca5(VS.90).aspx"&gt;MSBuild&lt;/a&gt; &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;En este post vamos a hablar de MSBuild ya que es el que yo uso y viene con el Visual Studio 2005 en adelante&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;MSBuild&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;MSBuild es una aplicación que viene con el framework desde la versión 2.0 y cuando creamos un proyecto en Visual Studio en realidad ese archivos .csprj es un archivo que le dice a MSBuild que compile nuestro proyecto, en resumen, desde Visual Studio 2005 los archivos .csprj son archivos de MSBuild que compilan lo que escribimos en Visual Studio.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Target y Task en MSBuild&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;Es hora de empezar a jugar con MSBuild, entonces vamos a empezar a jugar con la herramienta para tener claro dos conceptos muy importantes, Targets y Task.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/_t9Bh42Thfqo/TFRQGCeg7kI/AAAAAAAAAO0/OdNpULJKqIo/s1600-h/image%5B2%5D.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://lh6.ggpht.com/_t9Bh42Thfqo/TFRQGqjnmVI/AAAAAAAAAO4/AMgmOVF3nmo/image_thumb.png?imgmax=800" width="244" height="212" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Como se ve en el gráfico, un target es un conjunto de tareas, la tareas es el menor unidad de ejecución, sin embargo no podemos ejecutar una tarea que no se encuentre en un target.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Nuestro primer Build&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;El archivo de configuración para MSBuild más sencillo sería así:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/_t9Bh42Thfqo/TFRQHXF6vJI/AAAAAAAAAO8/OrcfDmx_8Mk/s1600-h/image%5B7%5D.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://lh3.ggpht.com/_t9Bh42Thfqo/TFRQH6DbtwI/AAAAAAAAAPA/mn_VcDNGaS0/image_thumb%5B3%5D.png?imgmax=800" width="564" height="74" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Sí, es un XML…..el nodo raíz es del tipo Project y apunto al namespace de Microsoft msbuild del 2003 (en mi caso) dentro tiene que existir al menos un elemento, en nuestro caso un Target con un nombre, en nuestro caso “prueba” y listo, como esto no sirve para nada vamos a agregar una tarea a nuestro Target.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/_t9Bh42Thfqo/TFRQIsveo2I/AAAAAAAAAPE/QlAEo4m9dig/s1600-h/image%5B12%5D.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://lh3.ggpht.com/_t9Bh42Thfqo/TFRQJOqCccI/AAAAAAAAAPI/MvAToka1GtQ/image_thumb%5B6%5D.png?imgmax=800" width="565" height="124" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Creamos un archivo, por defecto la extensión tiene que ser .target, pero podemos ponerle cualquiera, en mi caso hice un archivo “saludo.xml” y lo dejé en “C:\temp” para ejecutar MSBuild (y casi cualquier herramienta de línea de comandos del framework”) lo mejor es usar la línea de comandos de Visual Studio, que se instala en Tools&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/_t9Bh42Thfqo/TFRQKLEsUuI/AAAAAAAAAPM/ZQ1i7IpM-94/s1600-h/image%5B16%5D.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://lh4.ggpht.com/_t9Bh42Thfqo/TFRQK8Bw9aI/AAAAAAAAAPQ/Fj9tPmB8G44/image_thumb%5B8%5D.png?imgmax=800" width="635" height="82" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Llamamos a la línea de comandos y nos ponemos en el path del archivo que acabamos de crear con el código de arriba, la tarea que agregué es una de las tantas que trae MSBuild incorporadas y sirve para mostrar mensajes por consola, entonces escribimos en la consola:&lt;/p&gt;  &lt;p&gt;MSBuild saludos.xml&lt;/p&gt;  &lt;p&gt;y magia&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/_t9Bh42Thfqo/TFRQL3sZP-I/AAAAAAAAAPU/R9vn4KPZno8/s1600-h/image%5B20%5D.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://lh6.ggpht.com/_t9Bh42Thfqo/TFRQNMBFKSI/AAAAAAAAAPY/I-QSZsPWTU4/image_thumb%5B10%5D.png?imgmax=800" width="634" height="319" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;Por supuesto que esto no es muy interesante, pero no olvidemos que se puede llamar al compilador de C#, a MSTest, a cualquier exe, a un bat, a TFS y lo mejor de todo es que podemos crear nuestras propias tareas e invocarlas. Tampoco olvidemos que esto que acabamos de hacer puede ser llamado por TFS como parte de un Build disparado por un check-in.&lt;/p&gt;  &lt;p&gt;&lt;font color="#ffff00"&gt;Tip: podemos tener n Targets y ejecutar lo que querramos indicandole a MSBuild con al argumente /t:nombreTarget&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Compilando y ejecutando desde MSBuild&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;Vamos a crear una pequeña aplicación con C#, compilarla y luego invocarla con MSBuild, el código de la aplicación es éste&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/_t9Bh42Thfqo/TFRQOUszIZI/AAAAAAAAAPc/HsDkX9whypw/s1600-h/image%5B24%5D.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://lh4.ggpht.com/_t9Bh42Thfqo/TFRQPM0_2BI/AAAAAAAAAPg/DFAd98pHa2o/image_thumb%5B12%5D.png?imgmax=800" width="611" height="363" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;En el mismo directorio “C:\Temp” cree una clase class.cs con un punto de entrada, que simplemente escribe los parámetros en la consola si los hay, en caso que no los haya escribe “sin elementos” una gran pieza de software si me permiten decirlo, creamos un archivo “compilacion.xml” de este modo:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/_t9Bh42Thfqo/TFRQP3_kIeI/AAAAAAAAAPk/xz608Li6ql4/s1600-h/image%5B28%5D.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://lh5.ggpht.com/_t9Bh42Thfqo/TFRQQnm-tmI/AAAAAAAAAPo/xFNfpemTImM/image_thumb%5B14%5D.png?imgmax=800" width="616" height="168" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Como vemos la tarea “Csc” invoca al compilador de C# es una tarea predefinida de MSBuild, le decimos que compile class.cs sin más, luego un mensaje y por último la tarea “Exec” permite ejecutar cualquier ejecutable (o un archivo con un ejecutable asociado como un pdf por ejemplo) si todo sale bien deberíamos ver esto:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh6.ggpht.com/_t9Bh42Thfqo/TFRQR5zizoI/AAAAAAAAAPs/fOyPcRCWcEA/s1600-h/image%5B36%5D.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://lh5.ggpht.com/_t9Bh42Thfqo/TFRQThaKOTI/AAAAAAAAAPw/AS_iqhTAW5Y/image_thumb%5B18%5D.png?imgmax=800" width="611" height="383" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Funcionó, la salida de la aplicación al ser una aplicación de consola va directamente a la línea de comandos de Visual Studio.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Parámetros&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;Muchas veces necesitamos pasar parámetros a las aplicaciones que invocamos, esto es bien sencillo, las pasamos detrás del nombre del ejecutable, así:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/_t9Bh42Thfqo/TFRQUn2yMVI/AAAAAAAAAP0/97SaB9R2YwI/s1600-h/image%5B40%5D.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://lh5.ggpht.com/_t9Bh42Thfqo/TFRQVn0ObzI/AAAAAAAAAP4/U6pY70LThvI/image_thumb%5B20%5D.png?imgmax=800" width="608" height="161" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh6.ggpht.com/_t9Bh42Thfqo/TFRQWuyvAuI/AAAAAAAAAP8/JiPLXYA1YVg/s1600-h/image%5B45%5D.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://lh3.ggpht.com/_t9Bh42Thfqo/TFRQXoSI8sI/AAAAAAAAAQA/zv2mT6sZ4Ik/image_thumb%5B23%5D.png?imgmax=800" width="609" height="382" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;Perfecto, algo un poco más interesante sería poder pasar parámetro que vengan de otro lado&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Propiedades&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;Otro de los elementos que pueden estar a nivel de Target (es decir ser hijos directos de Project) es “PropertyGroup” elemento dentro del cual podemos definir propiedades, es decir, pares clave-valor que podemos definir a nuestro gusto y utilizarlo dentro del proyecto del MSBuild, por ejemplo:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/_t9Bh42Thfqo/TFRQYUdupqI/AAAAAAAAAQE/Y6YT3pmg2_o/s1600-h/image%5B53%5D.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://lh4.ggpht.com/_t9Bh42Thfqo/TFRQZMl3-II/AAAAAAAAAQI/KHcfqT0CwSs/image_thumb%5B27%5D.png?imgmax=800" width="606" height="249" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Vemos que hacemos referencia a las propiedades dentro de la tarea Exec haciendo $(nombrePropiedad), como resultado vemos esto:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/_t9Bh42Thfqo/TFRQZ38wJrI/AAAAAAAAAQM/Cylc_th5DXk/s1600-h/image%5B57%5D.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://lh6.ggpht.com/_t9Bh42Thfqo/TFRQbf6QrEI/AAAAAAAAAQQ/_WfwgRfT8JM/image_thumb%5B29%5D.png?imgmax=800" width="607" height="380" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Mágico.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Condiciones&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;Otra cosa interesante es la posibilidad de que diferentes cosas ocurran a partir de condiciones, por ejemplo&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/_t9Bh42Thfqo/TFRQcIeQuoI/AAAAAAAAAQY/eATPyoj3t78/s1600-h/image%5B61%5D.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://lh4.ggpht.com/_t9Bh42Thfqo/TFRQdp7h4xI/AAAAAAAAAQc/zXxBER3ESvU/image_thumb%5B31%5D.png?imgmax=800" width="608" height="176" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;En este caso indicamos que si la propiedad Configuration tiene el valor “debug” ejecute la segunda tarea de Csc.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/_t9Bh42Thfqo/TFRQeUJJ2mI/AAAAAAAAAQg/UvWsj4XGNXM/s1600-h/image%5B66%5D.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://lh4.ggpht.com/_t9Bh42Thfqo/TFRQfCkflvI/AAAAAAAAAQk/1t8F5wMZsg4/image_thumb%5B34%5D.png?imgmax=800" width="609" height="383" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;&lt;font color="#ffff80"&gt;Tip: La propiedad Configuration es una &lt;a href="http://msdn.microsoft.com/en-us/library/bb629394.aspx"&gt;propiedad reservada de MSBuild&lt;/a&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Ahora sí, algo un poco más real&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;Ahora vamos a ver un ejemplo más completo de un escenario real, basado en el post de nuestro gran amigo &lt;a href="http://jfromaniello.blogspot.com/"&gt;José Romanielo&lt;/a&gt; en su blog &lt;a href="http://jfromaniello.blogspot.com/2010/06/integracion-continua-en-net-y-basta-de.html"&gt;“Integración Continua en .net y basta de cháchara”&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;La idea es tener una pequeña configuración que compile nuestro proyecto y ejecute los test. Vamos a hacerlo de a poco.&lt;/p&gt;  &lt;p&gt;&lt;font color="#ffff80"&gt;Tip. Podemos importar proyectos de MSBuild con el tag import, una escenario común es importar tareas comunes que se instalan en nuestra máquina al instalar Visual Studio &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#ffff80"&gt;&amp;lt;Import Project=&amp;quot;$(MSBuildToolsPath)\Microsoft.CSharp.targets&amp;quot; /&amp;gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;Vamos a crear una librería de clases con una calculadora (tuve un ataque de originalidad) y otro proyecto dentro de la misma solución que compile ambos, corra los test con Nunit y publique los resultados, vamos de a poco.&lt;/p&gt;  &lt;p&gt;Presentamos el código de la aplicación:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/_t9Bh42Thfqo/TFRQf_qkREI/AAAAAAAAAQo/Kpow7oLyvv8/s1600-h/image%5B76%5D.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://lh5.ggpht.com/_t9Bh42Thfqo/TFRQhT5r1CI/AAAAAAAAAQs/u3KvtzNp3ws/image_thumb%5B40%5D.png?imgmax=800" width="645" height="699" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;El archivo de configuración para el Build sería el siguiente:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh6.ggpht.com/_t9Bh42Thfqo/TFRQiUv8RrI/AAAAAAAAAQw/K7BPNpQe2_g/s1600-h/image%5B71%5D.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://lh4.ggpht.com/_t9Bh42Thfqo/TFRQjytc3CI/AAAAAAAAAQ0/3ggDym3LjA0/image_thumb%5B37%5D.png?imgmax=800" width="647" height="213" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;En “PropertyGrupo definimos paths de la solución, de salida y donde se encuentra NUnit.&lt;/p&gt;  &lt;p&gt;El Target “All” es necesario para invocar a los otros dos, esto lo indicamos en la propiedad “DependsOnTargets” sino MSBuild ejecutaría el primer target y se detendría.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/z7f65y0d.aspx"&gt;MSBuild task&lt;/a&gt; es interesante porque nos permite invocar a una solución y ejecutar todo lo que está dentro, si pensamos un poco nos damos cuenta que la solución invoca csproj que son también archivos de MSBuild!! un detalle piola es la posibilidad de &lt;a href="http://msdn.microsoft.com/en-us/library/bb629394.aspx"&gt;modificar Properties&lt;/a&gt;, en este caso modificamos la propiedad OutputPath para que los proyectos envíen el resultado a el directorio que nos interesa.&lt;/p&gt;  &lt;p&gt;Ejecutamos y todo funciona según lo esperado.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/_t9Bh42Thfqo/TFRQlhKCaDI/AAAAAAAAAQ4/9yY2pB7ygx0/s1600-h/image%5B80%5D.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://lh6.ggpht.com/_t9Bh42Thfqo/TFRQoGQRPqI/AAAAAAAAAQ8/NbiyPiT7yV0/image_thumb%5B42%5D.png?imgmax=800" width="643" height="630" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Mágico, faltaría indicar a NUnit que publique los resultados, esto es simplemente pasarle un parámetro adicional, así:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/_t9Bh42Thfqo/TFRQomf9QCI/AAAAAAAAARA/1COE12WqO8Y/s1600-h/image%5B84%5D.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://lh6.ggpht.com/_t9Bh42Thfqo/TFRQpR9wwzI/AAAAAAAAARE/QcY7tzyO7-g/image_thumb%5B44%5D.png?imgmax=800" width="652" height="151" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Y listo.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Qué nos faltaría?&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;Como dije al principio es interesante que esto se ejecute automáticamente cuando hacemos check-in o en ciertos momentos del día, si tenemos TFS podemos instalar el TFSBuildAgent que se encarga de hacer esto sino CruiseControl o algo similar.&lt;/p&gt;  &lt;p&gt;Otras cosas para ver es dar una vuelta por MSBuild Extension Pack donde hay una gran referencia y muchas tareas comunes, también invetigar un poco .target que vienen por defecto en los archivos csproj.&lt;/p&gt;  &lt;p&gt;Saludos, Leonardo.&lt;/p&gt;  &lt;p&gt;Referencias&lt;/p&gt;  &lt;p&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/bb629394.aspx"&gt;MSBuild References&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://msbuildextensionpack.codeplex.com/"&gt;MSBuild Extension Pack&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://cruisecontrol.sourceforge.net/"&gt;Cruise Control&lt;/a&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;Leonardo Micheloni&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/148524916779753368-4130474745066912084?l=leomicheloni.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://leomicheloni.blogspot.com/feeds/4130474745066912084/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=148524916779753368&amp;postID=4130474745066912084' title='2 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default/4130474745066912084'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default/4130474745066912084'/><link rel='alternate' type='text/html' href='http://leomicheloni.blogspot.com/2010/07/introduccion-builds-automaticos-o-como.html' title='Introducción a Builds automáticos o “Cómo corno funciona MSBuild”'/><author><name>Leonardo Micheloni</name><uri>http://www.blogger.com/profile/12085246040181097881</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='30' src='http://3.bp.blogspot.com/_t9Bh42Thfqo/S6TVOJqYWcI/AAAAAAAAANU/MlZc6HpYZis/S220/yo+laguito+en+col%C3%B3n.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh6.ggpht.com/_t9Bh42Thfqo/TFRQGqjnmVI/AAAAAAAAAO4/AMgmOVF3nmo/s72-c/image_thumb.png?imgmax=800' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-148524916779753368.post-76458529580055969</id><published>2010-07-05T17:38:00.001-03:00</published><updated>2010-07-05T17:38:24.224-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='VAN'/><category scheme='http://www.blogger.com/atom/ns#' term='alt.net'/><category scheme='http://www.blogger.com/atom/ns#' term='Vale'/><title type='text'>Vale: Framework de validación de la comunidad Alt.Net Hispano</title><content type='html'>&lt;p&gt;Hace algunos días nomás la comunidad de &lt;a href="http://altnethispano.org/Inicio.aspx"&gt;Alt.Net Hispano&lt;/a&gt; ha dado vida a un nuevo proyecto de código abierto llamado Vale.&lt;/p&gt;  &lt;p&gt;A partir de la iniciativa de &lt;a href="http://fabiomaulo.blogspot.com/2010/06/altnet-hispano-vale.html"&gt;Fabio Maulo&lt;/a&gt; y el apoyo de &lt;a href="http://www.jorgegamba.com/"&gt;Jorge Gamba&lt;/a&gt;, &lt;a href="http://jfromaniello.blogspot.com/"&gt;José Romaniello&lt;/a&gt; y otros se decidió hacer un framework de validación que sirva de puerta para que más gente se acerque al código abierto.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Metodología de desarrollo&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;Una de las grandes cosas que tiene este proyecto es que el desarrollo se hace en vivo…si si, cada tanto (por ahora semanalmente pero no hay un periodo fijo) a través de un Alt.Net Café alguien (Fabio generalmente) va programando en vivo el desarrollo, gracias a la magia de internet todos pueden opinar durante el desarrollo usando TDD.&lt;/p&gt;  &lt;p&gt;Se se realizaron dos de estos encuentros y el framework está casi para usarlo, dejo el link del primero&lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.viddler.com/explore/AltNet-Hispano/videos/48/"&gt;Primer Alt.Net Café “Vale: desarrollando un framework desde cero con TDD”&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Hablemos del framework, validación no - intrusiva&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;Algunos comentarios de Vale, en comparación con otros frameworks de validación como &lt;a href="http://msdn.microsoft.com/en-us/library/ff648831.aspx"&gt;EntLib VAP&lt;/a&gt;, el primero que me viene a la mente es la validación no intrusiva, es decir en lugar de tener una clase Person así:&lt;/p&gt;  &lt;pre class="code"&gt;&lt;span style="color: teal"&gt;public class &lt;/span&gt;&lt;span style="color: #2b91af"&gt;Person
&lt;/span&gt;&lt;span style="color: white"&gt;{
    &lt;/span&gt;&lt;span style="color: teal"&gt;public string &lt;/span&gt;&lt;span style="color: white"&gt;Name { &lt;/span&gt;&lt;span style="color: teal"&gt;get&lt;/span&gt;&lt;span style="color: white"&gt;; &lt;/span&gt;&lt;span style="color: teal"&gt;set&lt;/span&gt;&lt;span style="color: white"&gt;; }
    &lt;/span&gt;&lt;span style="color: teal"&gt;public string &lt;/span&gt;&lt;span style="color: white"&gt;Surname { &lt;/span&gt;&lt;span style="color: teal"&gt;get&lt;/span&gt;&lt;span style="color: white"&gt;; &lt;/span&gt;&lt;span style="color: teal"&gt;set&lt;/span&gt;&lt;span style="color: white"&gt;; }
    &lt;/span&gt;&lt;span style="color: teal"&gt;public &lt;/span&gt;&lt;span style="color: #2b91af"&gt;DateTime &lt;/span&gt;&lt;span style="color: white"&gt;Birthday { &lt;/span&gt;&lt;span style="color: teal"&gt;get&lt;/span&gt;&lt;span style="color: white"&gt;; &lt;/span&gt;&lt;span style="color: teal"&gt;set&lt;/span&gt;&lt;span style="color: white"&gt;; }
}
&lt;/span&gt;&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;y para validar agregar atributos en las propiedades así:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: white"&gt;{
    [RequiredValidator]
    &lt;/span&gt;&lt;span style="color: teal"&gt;public string &lt;/span&gt;&lt;span style="color: white"&gt;Name { &lt;/span&gt;&lt;span style="color: teal"&gt;get&lt;/span&gt;&lt;span style="color: white"&gt;; &lt;/span&gt;&lt;span style="color: teal"&gt;set&lt;/span&gt;&lt;span style="color: white"&gt;; }
    [StringLenghtValidator(20)]
    &lt;/span&gt;&lt;span style="color: teal"&gt;public string &lt;/span&gt;&lt;span style="color: white"&gt;Surname    { &lt;/span&gt;&lt;span style="color: teal"&gt;get&lt;/span&gt;&lt;span style="color: white"&gt;; &lt;/span&gt;&lt;span style="color: teal"&gt;set&lt;/span&gt;&lt;span style="color: white"&gt;; }
    [TypeValidator(&lt;/span&gt;&lt;span style="color: teal"&gt;typeof&lt;/span&gt;&lt;span style="color: white"&gt;(&lt;/span&gt;&lt;span style="color: #2b91af"&gt;DateTime&lt;/span&gt;&lt;span style="color: white"&gt;)]
    &lt;/span&gt;&lt;span style="color: teal"&gt;public &lt;/span&gt;&lt;span style="color: #2b91af"&gt;DateTime &lt;/span&gt;&lt;span style="color: white"&gt;Birthday { &lt;/span&gt;&lt;span style="color: teal"&gt;get&lt;/span&gt;&lt;span style="color: white"&gt;; &lt;/span&gt;&lt;span style="color: teal"&gt;set&lt;/span&gt;&lt;span style="color: white"&gt;; }
}
&lt;/span&gt;&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;un método que deja “pegadas” las validaciones al modelo, con Vale hacemos esto:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: #2b91af"&gt;IValidator &lt;/span&gt;&lt;span style="color: white"&gt;validator = &lt;/span&gt;&lt;span style="color: teal"&gt;new &lt;/span&gt;&lt;span style="color: #2b91af"&gt;Validator&lt;/span&gt;&lt;span style="color: white"&gt;();
validator.Register&amp;lt;&lt;/span&gt;&lt;span style="color: #2b91af"&gt;Person&lt;/span&gt;&lt;span style="color: white"&gt;&amp;gt;(p =&amp;gt; validator.StringIsRequired(&lt;/span&gt;&lt;span style="color: #a31515"&gt;&amp;quot;Name&amp;quot;&lt;/span&gt;&lt;span style="color: white"&gt;, p.Name));
validator.Register&amp;lt;&lt;/span&gt;&lt;span style="color: #2b91af"&gt;Person&lt;/span&gt;&lt;span style="color: white"&gt;&amp;gt;(p =&amp;gt; validator.StringIsRequired(&lt;/span&gt;&lt;span style="color: #a31515"&gt;&amp;quot;Surname&amp;quot;&lt;/span&gt;&lt;span style="color: white"&gt;, p.Surname));
validator.Register&amp;lt;&lt;/span&gt;&lt;span style="color: #2b91af"&gt;Person&lt;/span&gt;&lt;span style="color: white"&gt;&amp;gt;(p =&amp;gt; validator.DateIsInThePast(&lt;/span&gt;&lt;span style="color: #a31515"&gt;&amp;quot;Birthday&amp;quot;&lt;/span&gt;&lt;span style="color: white"&gt;, p.Birthday));
&lt;/span&gt;&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;La interface IValidator es tiene un método Register&amp;lt;T&amp;gt; que permite registrar validaciones sobre un tipo en particular sin que dicho tipo no se modifique, interesante.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Analizando la implementación:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Como dije antes el desarrollo se hizo on-line y se fueron tomando decisiones allí mismo, vamos a recorrer el código de &lt;a href="http://vale.codeplex.com/SourceControl/changeset/changes/a8f84d1a2a2c"&gt;esta versión&lt;/a&gt; y a contar un poco el por qué de cada parte.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;La interface IValidator&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: teal"&gt;public interface &lt;/span&gt;&lt;span style="color: #2b91af"&gt;IValidator
&lt;/span&gt;&lt;span style="color: white"&gt;{
    &lt;/span&gt;&lt;span style="color: teal"&gt;void &lt;/span&gt;&lt;span style="color: white"&gt;Register&amp;lt;T&amp;gt;(&lt;/span&gt;&lt;span style="color: #2b91af"&gt;Func&lt;/span&gt;&lt;span style="color: white"&gt;&amp;lt;T, &lt;/span&gt;&lt;span style="color: teal"&gt;string&lt;/span&gt;&lt;span style="color: white"&gt;&amp;gt; assert);
    &lt;/span&gt;&lt;span style="color: #2b91af"&gt;IEnumerable&lt;/span&gt;&lt;span style="color: white"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: teal"&gt;string&lt;/span&gt;&lt;span style="color: white"&gt;&amp;gt; GetInvalidMessages(&lt;/span&gt;&lt;span style="color: teal"&gt;object &lt;/span&gt;&lt;span style="color: white"&gt;entity);
}

&lt;/span&gt;&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;Básicamente la idea de esta interface es permitir a través del método Register&amp;lt;T&amp;gt; registrar validaciones para un tipo en particular, y con IEnumerable&amp;lt;T&amp;gt; GetInvalidMessages&amp;#160; recuperar los errores, la utilización es la siguiente:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: #2b91af"&gt;IValidator &lt;/span&gt;&lt;span style="color: white"&gt;validator = &lt;/span&gt;&lt;span style="color: teal"&gt;new &lt;/span&gt;&lt;span style="color: #2b91af"&gt;Validator&lt;/span&gt;&lt;span style="color: white"&gt;();
validator.Register&amp;lt;&lt;/span&gt;&lt;span style="color: #2b91af"&gt;Person&lt;/span&gt;&lt;span style="color: white"&gt;&amp;gt;(p =&amp;gt; validator.StringIsRequired(&lt;/span&gt;&lt;span style="color: #a31515"&gt;&amp;quot;Name&amp;quot;&lt;/span&gt;&lt;span style="color: white"&gt;, p.Name));

&lt;/span&gt;&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;Para todos las entidades del tipo Person que quisiéramos validar se aplicarán todas las reglas que hayamos registrado de este modo.&lt;/p&gt;

&lt;p&gt;Actualmente no existe la posibilidad de tener diferentes políticas o reglas de validación para hacer algo así:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: #2b91af"&gt;IValidator &lt;/span&gt;&lt;span style="color: white"&gt;validator = &lt;/span&gt;&lt;span style="color: teal"&gt;new &lt;/span&gt;&lt;span style="color: #2b91af"&gt;Validator&lt;/span&gt;&lt;span style="color: white"&gt;();
validator.Register&amp;lt;&lt;/span&gt;&lt;span style="color: #2b91af"&gt;Person&lt;/span&gt;&lt;span style="color: white"&gt;&amp;gt;(p =&amp;gt; validator.StringIsRequired(&lt;/span&gt;&lt;span style="color: #a31515"&gt;&amp;quot;Name&amp;quot;&lt;/span&gt;&lt;span style="color: white"&gt;, p.Name), &lt;/span&gt;&lt;span style="color: #a31515"&gt;&amp;quot;default&amp;quot;&lt;/span&gt;&lt;span style="color: white"&gt;);

&lt;/span&gt;&lt;span style="color: teal"&gt;var &lt;/span&gt;&lt;span style="color: white"&gt;invalidMessages = validator.GetInvalidMessages(person, &lt;/span&gt;&lt;span style="color: #a31515"&gt;&amp;quot;default&amp;quot;&lt;/span&gt;&lt;span style="color: white"&gt;);

&lt;/span&gt;&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;Por el momento &lt;a href="http://vale.codeplex.com/workitem/11"&gt;ya subí el Issue a codeplex&lt;/a&gt;, veremos si se implementa en alguna versión, o no, lo decidirá la comunidad.&lt;/p&gt;

&lt;p&gt;El otro método que tiene por ahora la interface es IEnumerable&amp;lt;T&amp;gt; GetInvalidMessage, que básicamente aplica las validaciones y recupera los errores.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;La implementación interna&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Pongo es código de Validator en su primer versión (quité un par de líneas para simplificar) comentadas para su comprensión&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: teal"&gt;public class &lt;/span&gt;&lt;span style="color: #2b91af"&gt;Validator &lt;/span&gt;&lt;span style="color: white"&gt;: &lt;/span&gt;&lt;span style="color: #2b91af"&gt;IValidator
&lt;/span&gt;&lt;span style="color: white"&gt;{
    &lt;/span&gt;&lt;span style="color: gray"&gt;/// &amp;lt;summary&amp;gt;
    /// &lt;/span&gt;&lt;span style="color: green"&gt;Lista de (tipo, lista) de validaciones para el tipo, 
    &lt;/span&gt;&lt;span style="color: gray"&gt;/// &lt;/span&gt;&lt;span style="color: green"&gt;el tipo es la clave del diccionario
    &lt;/span&gt;&lt;span style="color: gray"&gt;/// &amp;lt;/summary&amp;gt;
    &lt;/span&gt;&lt;span style="color: #2b91af"&gt;Dictionary&lt;/span&gt;&lt;span style="color: white"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #2b91af"&gt;Type&lt;/span&gt;&lt;span style="color: white"&gt;, &lt;/span&gt;&lt;span style="color: #2b91af"&gt;List&lt;/span&gt;&lt;span style="color: white"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #2b91af"&gt;Func&lt;/span&gt;&lt;span style="color: white"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: teal"&gt;object&lt;/span&gt;&lt;span style="color: white"&gt;, &lt;/span&gt;&lt;span style="color: teal"&gt;string&lt;/span&gt;&lt;span style="color: white"&gt;&amp;gt;&amp;gt;&amp;gt; validatorsHolder = 
        &lt;/span&gt;&lt;span style="color: teal"&gt;new &lt;/span&gt;&lt;span style="color: #2b91af"&gt;Dictionary&lt;/span&gt;&lt;span style="color: white"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #2b91af"&gt;Type&lt;/span&gt;&lt;span style="color: white"&gt;, &lt;/span&gt;&lt;span style="color: #2b91af"&gt;List&lt;/span&gt;&lt;span style="color: white"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #2b91af"&gt;Func&lt;/span&gt;&lt;span style="color: white"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: teal"&gt;object&lt;/span&gt;&lt;span style="color: white"&gt;, &lt;/span&gt;&lt;span style="color: teal"&gt;string&lt;/span&gt;&lt;span style="color: white"&gt;&amp;gt;&amp;gt;&amp;gt;();

    &lt;/span&gt;&lt;span style="color: gray"&gt;/// &amp;lt;summary&amp;gt;
    /// &lt;/span&gt;&lt;span style="color: green"&gt;Permite registrar validaciones para un tipo, si ya existen validaciones 
    &lt;/span&gt;&lt;span style="color: gray"&gt;/// &lt;/span&gt;&lt;span style="color: green"&gt;para el tipo las agrega sino crea el grupo de validaciones.
    &lt;/span&gt;&lt;span style="color: gray"&gt;/// &lt;/span&gt;&lt;span style="color: green"&gt;Al permitir que los validadores sean Func&amp;amp;lt;T,string&amp;amp;gt; se puede hacer
    &lt;/span&gt;&lt;span style="color: gray"&gt;/// &lt;/span&gt;&lt;span style="color: green"&gt;validator.Register&amp;amp;lt;Person&amp;amp;gt;(p =&amp;gt; validator.StringIsRequired(&amp;quot;Name value&amp;quot;)
    &lt;/span&gt;&lt;span style="color: gray"&gt;/// &lt;/span&gt;&lt;span style="color: green"&gt;llamar al Func&amp;amp;lt;T,string&amp;amp;gt; y recuperar el string como resultado
    &lt;/span&gt;&lt;span style="color: gray"&gt;/// &lt;/span&gt;&lt;span style="color: green"&gt;de la ejecución de la Func sobre T
    &lt;/span&gt;&lt;span style="color: gray"&gt;/// &amp;lt;/summary&amp;gt;
    /// &amp;lt;typeparam name=&amp;quot;T&amp;quot;&amp;gt;&lt;/span&gt;&lt;span style="color: green"&gt;El tipo al que se aplican las validaciones&lt;/span&gt;&lt;span style="color: gray"&gt;&amp;lt;/typeparam&amp;gt;
    /// &amp;lt;param name=&amp;quot;assert&amp;quot;&amp;gt;&lt;/span&gt;&lt;span style="color: green"&gt;La validación&lt;/span&gt;&lt;span style="color: gray"&gt;&amp;lt;/param&amp;gt;
    &lt;/span&gt;&lt;span style="color: teal"&gt;public void &lt;/span&gt;&lt;span style="color: white"&gt;Register&amp;lt;T&amp;gt;(&lt;/span&gt;&lt;span style="color: #2b91af"&gt;Func&lt;/span&gt;&lt;span style="color: white"&gt;&amp;lt;T, &lt;/span&gt;&lt;span style="color: teal"&gt;string&lt;/span&gt;&lt;span style="color: white"&gt;&amp;gt; assert)
    {
        &lt;/span&gt;&lt;span style="color: green"&gt;//recupera el tipo al que se aplicaran las validaciones
        &lt;/span&gt;&lt;span style="color: teal"&gt;var &lt;/span&gt;&lt;span style="color: white"&gt;objType = &lt;/span&gt;&lt;span style="color: teal"&gt;typeof&lt;/span&gt;&lt;span style="color: white"&gt;(T);

        &lt;/span&gt;&lt;span style="color: green"&gt;//verifica si ya existe la lista de validaciones para T, sino la crea
        &lt;/span&gt;&lt;span style="color: #2b91af"&gt;List&lt;/span&gt;&lt;span style="color: white"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #2b91af"&gt;Func&lt;/span&gt;&lt;span style="color: white"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: teal"&gt;object&lt;/span&gt;&lt;span style="color: white"&gt;, &lt;/span&gt;&lt;span style="color: teal"&gt;string&lt;/span&gt;&lt;span style="color: white"&gt;&amp;gt;&amp;gt; actions;
        &lt;/span&gt;&lt;span style="color: teal"&gt;if &lt;/span&gt;&lt;span style="color: white"&gt;(!validatorsHolder.TryGetValue(objType, &lt;/span&gt;&lt;span style="color: teal"&gt;out &lt;/span&gt;&lt;span style="color: white"&gt;actions))
        {
            actions = &lt;/span&gt;&lt;span style="color: teal"&gt;new &lt;/span&gt;&lt;span style="color: #2b91af"&gt;List&lt;/span&gt;&lt;span style="color: white"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #2b91af"&gt;Func&lt;/span&gt;&lt;span style="color: white"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: teal"&gt;object&lt;/span&gt;&lt;span style="color: white"&gt;, &lt;/span&gt;&lt;span style="color: teal"&gt;string&lt;/span&gt;&lt;span style="color: white"&gt;&amp;gt;&amp;gt;();
        }

        &lt;/span&gt;&lt;span style="color: green"&gt;//agrega la nueva validación a la lista de validaciones
        &lt;/span&gt;&lt;span style="color: white"&gt;actions.Add(x =&amp;gt; assert((T)x));

        &lt;/span&gt;&lt;span style="color: green"&gt;//agrega la lista al holder de todas las validaciones
        &lt;/span&gt;&lt;span style="color: white"&gt;validatorsHolder[objType] = actions;
    }

    &lt;/span&gt;&lt;span style="color: gray"&gt;/// &amp;lt;summary&amp;gt;
    /// &lt;/span&gt;&lt;span style="color: green"&gt;Ejecuta las validaciones sobre la instancia y retorna los mensajes de error
    &lt;/span&gt;&lt;span style="color: gray"&gt;/// &amp;lt;/summary&amp;gt;
    /// &amp;lt;param name=&amp;quot;entity&amp;quot;&amp;gt;&lt;/span&gt;&lt;span style="color: green"&gt;La entidad sobre la que se aplicarán las validaciones&lt;/span&gt;&lt;span style="color: gray"&gt;&amp;lt;/param&amp;gt;
    /// &amp;lt;returns&amp;gt;&lt;/span&gt;&lt;span style="color: green"&gt;El listado de error, string[0] si no existen&lt;/span&gt;&lt;span style="color: gray"&gt;&amp;lt;/returns&amp;gt;
    &lt;/span&gt;&lt;span style="color: teal"&gt;public &lt;/span&gt;&lt;span style="color: #2b91af"&gt;IEnumerable&lt;/span&gt;&lt;span style="color: white"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: teal"&gt;string&lt;/span&gt;&lt;span style="color: white"&gt;&amp;gt; GetInvalidMessages(&lt;/span&gt;&lt;span style="color: teal"&gt;object &lt;/span&gt;&lt;span style="color: white"&gt;entity)
    {

        &lt;/span&gt;&lt;span style="color: green"&gt;//recupera el tipo del objeto a validar
        &lt;/span&gt;&lt;span style="color: teal"&gt;var &lt;/span&gt;&lt;span style="color: white"&gt;objType = entity.GetType();

        
        &lt;/span&gt;&lt;span style="color: #2b91af"&gt;List&lt;/span&gt;&lt;span style="color: white"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #2b91af"&gt;Func&lt;/span&gt;&lt;span style="color: white"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: teal"&gt;object&lt;/span&gt;&lt;span style="color: white"&gt;, &lt;/span&gt;&lt;span style="color: teal"&gt;string&lt;/span&gt;&lt;span style="color: white"&gt;&amp;gt;&amp;gt; actions;
        &lt;/span&gt;&lt;span style="color: green"&gt;//si existe una lista de validaciones para T se ejecutan
        &lt;/span&gt;&lt;span style="color: teal"&gt;if &lt;/span&gt;&lt;span style="color: white"&gt;(validatorsHolder.TryGetValue(objType, &lt;/span&gt;&lt;span style="color: teal"&gt;out &lt;/span&gt;&lt;span style="color: white"&gt;actions))
        {
            &lt;/span&gt;&lt;span style="color: green"&gt;//se llama a todas las validaciones dentro de actions 
            //(las validaciones para T dentro del holder)
            //ejecuta las action que no tienen mensaje vacio
            &lt;/span&gt;&lt;span style="color: teal"&gt;return &lt;/span&gt;&lt;span style="color: white"&gt;actions.Select(action =&amp;gt; action(entity))
                .Where(message =&amp;gt; !&lt;/span&gt;&lt;span style="color: teal"&gt;string&lt;/span&gt;&lt;span style="color: white"&gt;.Empty.Equals(message));
        }
        &lt;/span&gt;&lt;span style="color: teal"&gt;return new string&lt;/span&gt;&lt;span style="color: white"&gt;[0];
    }

&lt;/span&gt;&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;Como se puede ver es muy sencillo, un IDictionary que tiene como clave de cada valor el tipo (el tipo que queremos validar) y como valor una lista de validadores, que en este caso son Func&amp;lt;T,string&amp;gt; donde T es el mismo tipo que queremos validar y string el mensaje de error.&lt;/p&gt;

&lt;p&gt;Entonces un validador no sería más que un simple método que acepte T y retorne un string en caso de error, la implementación más sencilla sería:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: teal"&gt;public class &lt;/span&gt;&lt;span style="color: #2b91af"&gt;Validadores
&lt;/span&gt;&lt;span style="color: white"&gt;{
    &lt;/span&gt;&lt;span style="color: teal"&gt;public string &lt;/span&gt;&lt;span style="color: white"&gt;StringIsRequired(&lt;/span&gt;&lt;span style="color: teal"&gt;string &lt;/span&gt;&lt;span style="color: white"&gt;value)
    {
        &lt;/span&gt;&lt;span style="color: teal"&gt;if &lt;/span&gt;&lt;span style="color: white"&gt;(&lt;/span&gt;&lt;span style="color: teal"&gt;string&lt;/span&gt;&lt;span style="color: white"&gt;.IsNullOrEmpty(value))
        {
            &lt;/span&gt;&lt;span style="color: teal"&gt;return string&lt;/span&gt;&lt;span style="color: white"&gt;.Format(&lt;/span&gt;&lt;span style="color: #a31515"&gt;&amp;quot;field is required.&amp;quot;&lt;/span&gt;&lt;span style="color: white"&gt;);
        }
        &lt;/span&gt;&lt;span style="color: teal"&gt;return string&lt;/span&gt;&lt;span style="color: white"&gt;.Empty;
    }

}
&lt;/span&gt;&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;Para usarlo así:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: #2b91af"&gt;IValidator &lt;/span&gt;&lt;span style="color: white"&gt;validator = &lt;/span&gt;&lt;span style="color: teal"&gt;new &lt;/span&gt;&lt;span style="color: #2b91af"&gt;Validator&lt;/span&gt;&lt;span style="color: white"&gt;();
validator.Register&amp;lt;&lt;/span&gt;&lt;span style="color: #2b91af"&gt;Person&lt;/span&gt;&lt;span style="color: white"&gt;&amp;gt;(p =&amp;gt; &lt;/span&gt;&lt;span style="color: teal"&gt;new &lt;/span&gt;&lt;span style="color: #2b91af"&gt;Validadores&lt;/span&gt;&lt;span style="color: white"&gt;().StringIsRequired(p.Name));

&lt;/span&gt;&lt;span style="color: teal"&gt;var &lt;/span&gt;&lt;span style="color: white"&gt;person = &lt;/span&gt;&lt;span style="color: teal"&gt;new &lt;/span&gt;&lt;span style="color: #2b91af"&gt;Person &lt;/span&gt;&lt;span style="color: white"&gt;{ Name = &lt;/span&gt;&lt;span style="color: teal"&gt;null&lt;/span&gt;&lt;span style="color: white"&gt;, Surname = &lt;/span&gt;&lt;span style="color: teal"&gt;null&lt;/span&gt;&lt;span style="color: white"&gt;, Birthday = &lt;/span&gt;&lt;span style="color: #2b91af"&gt;DateTime&lt;/span&gt;&lt;span style="color: white"&gt;.Today };
&lt;/span&gt;&lt;span style="color: teal"&gt;var &lt;/span&gt;&lt;span style="color: white"&gt;invalidMessages = validator.GetInvalidMessages(person);

&lt;/span&gt;&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;Para mayor comodidad se implementaron como Extension Methods para IValidator en la clase estática CommonValidator y el uso es el siguiente:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: #2b91af"&gt;IValidator &lt;/span&gt;&lt;span style="color: white"&gt;validator = &lt;/span&gt;&lt;span style="color: teal"&gt;new &lt;/span&gt;&lt;span style="color: #2b91af"&gt;Validator&lt;/span&gt;&lt;span style="color: white"&gt;();
validator.Register&amp;lt;&lt;/span&gt;&lt;span style="color: #2b91af"&gt;Person&lt;/span&gt;&lt;span style="color: white"&gt;&amp;gt;(p =&amp;gt; validator.StringIsRequired(&lt;/span&gt;&lt;span style="color: #a31515"&gt;&amp;quot;Name&amp;quot;&lt;/span&gt;&lt;span style="color: white"&gt;, p.Name));
validator.Register&amp;lt;&lt;/span&gt;&lt;span style="color: #2b91af"&gt;Person&lt;/span&gt;&lt;span style="color: white"&gt;&amp;gt;(p =&amp;gt; validator.StringIsRequired(&lt;/span&gt;&lt;span style="color: #a31515"&gt;&amp;quot;Surname&amp;quot;&lt;/span&gt;&lt;span style="color: white"&gt;, p.Surname));
validator.Register&amp;lt;&lt;/span&gt;&lt;span style="color: #2b91af"&gt;Person&lt;/span&gt;&lt;span style="color: white"&gt;&amp;gt;(p =&amp;gt; validator.DateIsInThePast(&lt;/span&gt;&lt;span style="color: #a31515"&gt;&amp;quot;Birthday&amp;quot;&lt;/span&gt;&lt;span style="color: white"&gt;, p.Birthday));

&lt;/span&gt;&lt;span style="color: teal"&gt;var &lt;/span&gt;&lt;span style="color: white"&gt;person = &lt;/span&gt;&lt;span style="color: teal"&gt;new &lt;/span&gt;&lt;span style="color: #2b91af"&gt;Person &lt;/span&gt;&lt;span style="color: white"&gt;{ Name = &lt;/span&gt;&lt;span style="color: teal"&gt;null&lt;/span&gt;&lt;span style="color: white"&gt;, Surname = &lt;/span&gt;&lt;span style="color: teal"&gt;null&lt;/span&gt;&lt;span style="color: white"&gt;, Birthday = &lt;/span&gt;&lt;span style="color: #2b91af"&gt;DateTime&lt;/span&gt;&lt;span style="color: white"&gt;.Today };
&lt;/span&gt;&lt;span style="color: teal"&gt;var &lt;/span&gt;&lt;span style="color: white"&gt;invalidMessages = validator.GetInvalidMessages(person);

&lt;/span&gt;&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;Mágico por todos lados, nos vemos la próxima.&lt;/p&gt;

&lt;p&gt;Links&lt;/p&gt;

&lt;p&gt;&lt;a href="http://vale.codeplex.com/"&gt;Proyecto Vale en Codeplex&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="http://twitter.com/AltNetHispano"&gt;Twitter de la comunidad Alt.Net Hispano&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="http://groups.google.com/group/altnet-hispano"&gt;Lista de correo de Alt.Net Hispano&lt;/a&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;Leonardo Micheloni&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/148524916779753368-76458529580055969?l=leomicheloni.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://leomicheloni.blogspot.com/feeds/76458529580055969/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=148524916779753368&amp;postID=76458529580055969' title='3 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default/76458529580055969'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default/76458529580055969'/><link rel='alternate' type='text/html' href='http://leomicheloni.blogspot.com/2010/07/vale-framework-de-validacion-de-la.html' title='Vale: Framework de validación de la comunidad Alt.Net Hispano'/><author><name>Leonardo Micheloni</name><uri>http://www.blogger.com/profile/12085246040181097881</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='30' src='http://3.bp.blogspot.com/_t9Bh42Thfqo/S6TVOJqYWcI/AAAAAAAAANU/MlZc6HpYZis/S220/yo+laguito+en+col%C3%B3n.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-148524916779753368.post-7112316398629559984</id><published>2010-06-27T13:26:00.001-03:00</published><updated>2010-06-27T13:27:13.346-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='JQuery'/><category scheme='http://www.blogger.com/atom/ns#' term='AJAX'/><category scheme='http://www.blogger.com/atom/ns#' term='REST'/><category scheme='http://www.blogger.com/atom/ns#' term='json'/><category scheme='http://www.blogger.com/atom/ns#' term='c#'/><title type='text'>Cómo hacer llamas AJAX a otros sitios, o qué es JSONP</title><content type='html'>&lt;p&gt;Una de las limitaciones que tiene el objeto XMLHTTPRequest (el objeto que da vida a AJAX) es no poder hacer llamadas a URLs fuera de nuestro dominio, es decir, si desde mi sitio quisiera traer las fotos de Flikr con el tag “dog” llamando a la URL &lt;a title="http://api.flickr.com/services/feeds/photos_public.gne?tags=dog" href="http://api.flickr.com/services/feeds/photos_public.gne?tags=dog"&gt;http://api.flickr.com/services/feeds/photos_public.gne?tags=dog&lt;/a&gt; con el siguiente código&lt;/p&gt;  &lt;p&gt;&amp;lt;html&amp;gt;   &lt;br /&gt;&amp;lt;head&amp;gt;    &lt;br /&gt;&amp;#160; &amp;lt;script src=&amp;quot;&lt;a href="http://code.jquery.com/jquery-latest.min.js&amp;quot;"&gt;http://code.jquery.com/jquery-latest.min.js&amp;quot;&lt;/a&gt;&amp;gt;&amp;lt;/script&amp;gt;    &lt;br /&gt;&amp;#160; &amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; $(function()    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; $(&amp;quot;#boton&amp;quot;).click(ajax);    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }); &lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; function ajax()   &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; var url = &amp;quot;&lt;a href="http://api.flickr.com/services/feeds/photos_public.gne?tags=dog&amp;quot;;"&gt;http://api.flickr.com/services/feeds/photos_public.gne?tags=dog&amp;quot;;&lt;/a&gt;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; $.get(url, null, function(data)    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; $(&amp;quot;#contenedor&amp;quot;).html(data);    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; });    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;lt;/script&amp;gt;    &lt;br /&gt;&amp;lt;/head&amp;gt;    &lt;br /&gt;&amp;lt;body&amp;gt;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;lt;div id=&amp;quot;contenedor&amp;quot; /&amp;gt;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;lt;input type=&amp;quot;button&amp;quot; id=&amp;quot;boton&amp;quot; value=&amp;quot;probar&amp;quot; /&amp;gt;    &lt;br /&gt;&amp;lt;/body&amp;gt;    &lt;br /&gt;&amp;lt;/html&amp;gt;&lt;/p&gt;  &lt;p&gt;Utilizando jQuery hacemos un simple llamada AJAX y no pasa nada, vemos qué nos dice Fiddler&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/_t9Bh42Thfqo/TCd7iPGfIcI/AAAAAAAAAOc/wXjvFSLwCig/s1600-h/image%5B9%5D.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://lh3.ggpht.com/_t9Bh42Thfqo/TCd7jL0jsNI/AAAAAAAAAOg/0meNgCs2w6U/image_thumb%5B5%5D.png?imgmax=800" width="672" height="339" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;Vemos que la llamada se hace y los datos vienen pero no pasa nada, vamos al Firebug y vemos algo interesante&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh6.ggpht.com/_t9Bh42Thfqo/TCd7j7LH7GI/AAAAAAAAAOk/Er4uw2tfjyI/s1600-h/image%5B14%5D.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://lh3.ggpht.com/_t9Bh42Thfqo/TCd7kgrVJGI/AAAAAAAAAOo/tF5pWwflqd0/image_thumb%5B8%5D.png?imgmax=800" width="673" height="210" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Firebug no nos muestra datos, esto es porque no se permiten llamadas a otro dominio con XMLHTTPRequest, he aquí el problema.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;JSONP la solución&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;Una cosa que si permiten los navegadores es cargar recursos desde otros dominios, es decir, nada impide que un elemento &amp;lt;img&amp;gt; tenga su src apuntando a un recurso externo, es más, un &amp;lt;script&amp;gt; puede tener su origen en un dominio externo como en el ejemplo anterior que cargamos el archivo de jQuery desde &lt;a title="http://code.jquery.com/jquery-latest.min.js" href="http://code.jquery.com/jquery-latest.min.js"&gt;http://code.jquery.com/jquery-latest.min.js&lt;/a&gt; y funciona perfectamente, otra cosa que podemos hacer es crear dinámicamente elementos &amp;lt;script&amp;gt;, entonces imaginemos que el recurso externo que queremos cargar en lugar de traernos solamente un conjunto de datos nos trae una llamada a un función dentro de nuestro código? para ser más claros, imaginemos que queremos llamar una URL que nos trae el valor “hola mundo”, no podemos recuperarlo con AJAX por la limitación que comentamos, pero qué pasaría si en lugar de traer “hola mundo” no trae código Javascript que incluya una llamada a una función?, así: MiFuncion(“hola mundo) y generamos dinámicamente un tag &amp;lt;script&amp;gt; que apunta a la URL esa, es decir, hacemos esto:&lt;/p&gt;  &lt;p&gt;function jsonp()   &lt;br /&gt;{    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; var url = &amp;quot;&lt;a href="http://hostRemoto/datos&amp;quot;;"&gt;http://hostRemoto/datos&amp;quot;;&lt;/a&gt;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; $(&amp;quot;&amp;lt;script&amp;gt;&amp;quot;).attr(&amp;quot;src&amp;quot;,url).appendTo(&amp;quot;head&amp;quot;);    &lt;br /&gt;} &lt;/p&gt;  &lt;p&gt;function MiFuncion(data)   &lt;br /&gt;{    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; alert(data);    &lt;br /&gt;}&lt;/p&gt;  &lt;p&gt;y &lt;a href="http://hostRemot/datos"&gt;http://hostRemot/datos&lt;/a&gt; retorna MiFuncion(“hola mundo”)&lt;/p&gt;  &lt;p&gt;Entonces conseguimos utilizar datos generados en hostRemoto, a esto se le llama JSONP JSON+Padding, lo interesante de esta técnica es que muchas API públicas la implementan, la de Yahoo, Flikr, Twitter, etc. En general la forma de utilizarlas es indicando como parámetro el nombre de nuestra función, es decir&lt;/p&gt;  &lt;p&gt;&lt;a href="http://hostRemoto/datos?callback=MiFuncion"&gt;http://hostRemoto/datos?callback=MiFuncion&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Con eso le indicamos a hostRemoto que agregue delante de los datos que retorna una llamada a MiFuncion, en el caso de Flickr es así&lt;/p&gt;  &lt;p&gt;&lt;a title="http://api.flickr.com/services/feeds/photos_public.gne?tags=dog&amp;amp;format=json&amp;amp;jsoncallback=cargar" href="http://api.flickr.com/services/feeds/photos_public.gne?tags=dog&amp;amp;format=json&amp;amp;jsoncallback=MiFuncion"&gt;http://api.flickr.com/services/feeds/photos_public.gne?tags=dog&amp;amp;format=json&amp;amp;jsoncallback=MiFuncion&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Entonces, un ejemplos completo de una implementación de JSONP llamando a Flickr sería así:&lt;/p&gt;  &lt;p&gt;&amp;lt;html&amp;gt;   &lt;br /&gt;&amp;lt;head&amp;gt;    &lt;br /&gt;&amp;#160; &amp;lt;script src=&amp;quot;&lt;a href="http://code.jquery.com/jquery-latest.min.js&amp;quot;"&gt;http://code.jquery.com/jquery-latest.min.js&amp;quot;&lt;/a&gt;&amp;gt;&amp;lt;/script&amp;gt;    &lt;br /&gt;&amp;#160; &amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; $(function()    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; $(&amp;quot;#boton&amp;quot;).click(jsonp);    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; });    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; function jsonp()    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; var url = &amp;quot;&lt;a href="http://api.flickr.com/services/feeds/photos_public.gne?tags=dog&amp;amp;format=json&amp;amp;jsoncallback=MiFuncion&amp;quot;;"&gt;http://api.flickr.com/services/feeds/photos_public.gne?tags=dog&amp;amp;format=json&amp;amp;jsoncallback=MiFuncion&amp;quot;;&lt;/a&gt;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; $(&amp;quot;&amp;lt;script&amp;gt;&amp;quot;).attr(&amp;quot;src&amp;quot;,url).appendTo(&amp;quot;head&amp;quot;);    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; function MiFuncion(data)    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; $.each(data.items, function(i,item){    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; $(&amp;quot;&amp;lt;img/&amp;gt;&amp;quot;).attr(&amp;quot;src&amp;quot;, item.media.m).appendTo(&amp;quot;#contenedor&amp;quot;);    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; });    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;lt;/script&amp;gt;    &lt;br /&gt;&amp;lt;/head&amp;gt;    &lt;br /&gt;&amp;lt;body&amp;gt;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;lt;input type=&amp;quot;button&amp;quot; id=&amp;quot;boton&amp;quot; value=&amp;quot;probar&amp;quot; /&amp;gt;&amp;lt;br /&amp;gt;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;lt;div id=&amp;quot;contenedor&amp;quot; /&amp;gt;    &lt;br /&gt;&amp;lt;/body&amp;gt;    &lt;br /&gt;&amp;lt;/html&amp;gt;&lt;/p&gt;  &lt;p&gt;Llamamos a la API, le decimos que el nombre de nuestra función es MiFuncion, cargamos dentro de un &amp;lt;script&amp;gt; generado dinámicamente y se ejecuta la llamada a MiFuncion, esta recibe los datos JSON y genera elementos &amp;lt;img&amp;gt; que se van agregando al DIV contenedor, mágico.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;JSONP en jQuery&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;Los que acabamos de hacer funciona perfecto, pero es un poco trabajoso, para evitarnos semejante cantidad de trabajo jQuery ya trae la posibilidad de hacer llamadas JSONP y lo mejor es que lo hace de manera que es transparente para nosotros.&lt;/p&gt;  &lt;p&gt;&amp;lt;html&amp;gt;   &lt;br /&gt;&amp;lt;head&amp;gt;    &lt;br /&gt;&amp;#160; &amp;lt;script src=&amp;quot;&lt;a href="http://code.jquery.com/jquery-latest.min.js&amp;quot;"&gt;http://code.jquery.com/jquery-latest.min.js&amp;quot;&lt;/a&gt;&amp;gt;&amp;lt;/script&amp;gt;    &lt;br /&gt;&amp;#160; &amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; $(function()    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; $(&amp;quot;#boton&amp;quot;).click(jsonp);    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; });    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; function jsonp()    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; var url = &amp;quot;&lt;a href="http://api.flickr.com/services/feeds/photos_public.gne?tags=dog&amp;amp;format=json&amp;amp;jsoncallback=?&amp;quot;;"&gt;http://api.flickr.com/services/feeds/photos_public.gne?tags=dog&amp;amp;format=json&amp;amp;jsoncallback=?&amp;quot;;&lt;/a&gt;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; $.getJSON(url, null, function(data)    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; $.each(data.items, function(i,item){    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; $(&amp;quot;&amp;lt;img/&amp;gt;&amp;quot;).attr(&amp;quot;src&amp;quot;, item.media.m).appendTo(&amp;quot;#contenedor&amp;quot;);    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; });    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; });    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;lt;/script&amp;gt;    &lt;br /&gt;&amp;lt;/head&amp;gt;    &lt;br /&gt;&amp;lt;body&amp;gt;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;lt;input type=&amp;quot;button&amp;quot; id=&amp;quot;boton&amp;quot; value=&amp;quot;probar&amp;quot; /&amp;gt;&amp;lt;br /&amp;gt;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;lt;div id=&amp;quot;contenedor&amp;quot; /&amp;gt;    &lt;br /&gt;&amp;lt;/body&amp;gt;    &lt;br /&gt;&amp;lt;/html&amp;gt;&lt;/p&gt;  &lt;p&gt;Vemos la generación dinámica del tag &amp;lt;script&amp;gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/_t9Bh42Thfqo/TCd7lPkblZI/AAAAAAAAAOs/sXMjOXSKdDc/s1600-h/image%5B21%5D.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://lh4.ggpht.com/_t9Bh42Thfqo/TCd7mrYKO3I/AAAAAAAAAOw/-XjhHr_8AMQ/image_thumb%5B11%5D.png?imgmax=800" width="680" height="429" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Básicamente la funcion getJSON al detectar la cadena callback=? en la URL que recibe genera automáticamente el tag &amp;lt;script&amp;gt; y llama a la URL reemplazando el ? por un nombre generado al azar, recupera la llamada y hace que el funcionamiento de JSONP sea transparente para nosotros, el parámetro jsoncallback es propio de la API de Flickr. Enjoy.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Referencias:&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.flickr.com/services/api/response.json.html"&gt;FlickAPI&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://api.jquery.com/jQuery.getJSON/"&gt;jQuery getJSON&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://en.wikipedia.org/wiki/Json#JSONP"&gt;JSONP&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Leonardo.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;Leonardo Micheloni&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/148524916779753368-7112316398629559984?l=leomicheloni.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://leomicheloni.blogspot.com/feeds/7112316398629559984/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=148524916779753368&amp;postID=7112316398629559984' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default/7112316398629559984'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default/7112316398629559984'/><link rel='alternate' type='text/html' href='http://leomicheloni.blogspot.com/2010/06/como-hacer-llamas-ajax-otros-sitios-o.html' title='Cómo hacer llamas AJAX a otros sitios, o qué es JSONP'/><author><name>Leonardo Micheloni</name><uri>http://www.blogger.com/profile/12085246040181097881</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='30' src='http://3.bp.blogspot.com/_t9Bh42Thfqo/S6TVOJqYWcI/AAAAAAAAANU/MlZc6HpYZis/S220/yo+laguito+en+col%C3%B3n.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh3.ggpht.com/_t9Bh42Thfqo/TCd7jL0jsNI/AAAAAAAAAOg/0meNgCs2w6U/s72-c/image_thumb%5B5%5D.png?imgmax=800' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-148524916779753368.post-8689518028025273272</id><published>2010-06-26T20:06:00.002-03:00</published><updated>2010-06-26T20:09:09.246-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='MVC'/><category scheme='http://www.blogger.com/atom/ns#' term='AJAX'/><category scheme='http://www.blogger.com/atom/ns#' term='twitter'/><title type='text'>Twitter clon</title><content type='html'>&lt;p&gt;Un grupo de alumnos de la facultad han desarrollados dos proyectos con igual objetivo, un clon de Twitter, más precisamente un fontend que utiliza la API REST de Twitter, la idea era realizar una experiencia para ver cómo interactúan diferentes tecnologías que son parte de la materia arquitectura web:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;HTTP&lt;/li&gt;&lt;li&gt;HTML&lt;/li&gt;&lt;li&gt;XML&lt;/li&gt;&lt;li&gt;Javascript&lt;/li&gt;&lt;li&gt;CSS&lt;/li&gt;&lt;li&gt;MVC&lt;/li&gt;&lt;li&gt;REST&lt;/li&gt;&lt;li&gt;AJAX&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Finalmente la semana pasar quedó publicada la primer versión de los proyectos ambos dentro de una misma solución, dejo los links al primer release y al proyecto y mi más grande agradecimiento a los chicos por la participación y el esfuerzo.&lt;/p&gt;&lt;p&gt;&lt;a href="http://caecetwitterclon.codeplex.com/"&gt;Proyecto Twitter Clon&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://caecetwitterclon.codeplex.com/releases/view/47753"&gt;Primer Release Versión 0.1 beta&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Saludos, Leonardo.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;Leonardo Micheloni&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/148524916779753368-8689518028025273272?l=leomicheloni.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://leomicheloni.blogspot.com/feeds/8689518028025273272/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=148524916779753368&amp;postID=8689518028025273272' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default/8689518028025273272'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default/8689518028025273272'/><link rel='alternate' type='text/html' href='http://leomicheloni.blogspot.com/2010/06/twitter-clon.html' title='Twitter clon'/><author><name>Leonardo Micheloni</name><uri>http://www.blogger.com/profile/12085246040181097881</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='30' src='http://3.bp.blogspot.com/_t9Bh42Thfqo/S6TVOJqYWcI/AAAAAAAAANU/MlZc6HpYZis/S220/yo+laguito+en+col%C3%B3n.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-148524916779753368.post-6976246459155180423</id><published>2010-06-03T18:05:00.001-03:00</published><updated>2010-06-03T18:05:44.496-03:00</updated><title type='text'>Recuperar la consulta generada por LinqToSql y ejecutar asincrónicamente</title><content type='html'>&lt;p&gt;&lt;strong&gt;Ejecución asincrónica y filtros dinámicos&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;Al interesante de LinqToSql (desde ahora L2S) es la que no genera la consulta hasta último momento si nos apoyamos en IQueryable, es decir, siempre que interactuemos con esta interface vamos a poder seguir agregando condiciones a nuestra consulta y el SQL resultante se va a resolver recién en el momento de ir a la base de datos, con esto quiero decir que no va a traer toda la tabla y después filtrar en memoria (por decirlo de una manera sencilla). Pero para resumir la cosa dejo un par de ejemplo de esto usando la base de datos AdventureWorks, enjoy.&lt;/p&gt;  &lt;p&gt;/// &amp;lt;summary&amp;gt;   &lt;br /&gt;/// Ejemplo de generación de consulta LinqToSql y ejecución posterir con SqlCommand    &lt;br /&gt;/// &amp;lt;/summary&amp;gt;    &lt;br /&gt;public static void LlamadaAsincronica()    &lt;br /&gt;{    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; //context Linq2Sql    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; DBDataContext _ctx = new DBDataContext(); &lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; //Generamos la consulta   &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; var r = from p in _ctx.Products    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; where p.ProductCategory.Name.StartsWith(&amp;quot;b&amp;quot;)    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; select p; &lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; //en lugar de ejecutarla   &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; //recuperamos el command    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; var c =&amp;#160; _ctx.GetCommand(r) as System.Data.SqlClient.SqlCommand; &lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; //tomamos el command text, o sea, el sql   &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; var query = c.CommandText; &lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; //convertimos los parámetros para pasarlos al query   &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; var parametros = c.Parameters.Cast&amp;lt;System.Data.SqlClient.SqlParameter&amp;gt;().Select(p =&amp;gt; p.Value).ToArray(); &lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; //lo ejecutamos asincrónicamente   &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; var result = _ctx.ExecuteQuery&amp;lt;Product&amp;gt;(query,&amp;#160; parametros);    &lt;br /&gt;} &lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;/// &amp;lt;summary&amp;gt;   &lt;br /&gt;/// Ejemplo de suma de filtros    &lt;br /&gt;/// &amp;lt;/summary&amp;gt;    &lt;br /&gt;public static void SumandoFiltros()    &lt;br /&gt;{    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; DBDataContext _ctx = new DBDataContext(); &lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; //generamos un IQueryable   &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; var query = _ctx.Products.AsQueryable(); &lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; //colocamos un fitro   &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; query = query.Where(p =&amp;gt; p.ProductCategory.ParentProductCategoryID == 1).AsQueryable(); &lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; //agregamos uno más   &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; query = query.Where(p =&amp;gt; p.ProductID &amp;gt; 10); &lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; //y magia se arma la consulta completa   &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; var result = query.ToArray();&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;} &lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Mapeos locos&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;A modo de regalo dejo un lindo ejemplo que demuestra como L2S mapea un resultado a cualquier tipo que le digamos siempre que pueda resolverlo, simplemente creo la clase Dummy que tiene un par de propiedades que coinciden con Product.&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; /// &amp;lt;summary&amp;gt;   &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; /// Ejemplo sobre cómo el framework de LinqToSql hace el mejor esfuerzo para    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; /// mapear un resultado a un tipo de objeto que nosotros le digamos    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; /// &amp;lt;/summary&amp;gt;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; public static void MapearOtraCosa()    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; //context Linq2Sql    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; DBDataContext _ctx = new DBDataContext(); &lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; //Generamos la consulta   &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; var r = from p in _ctx.Products    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; select p; &lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; //en lugar de ejecutarla   &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; //recuperamos el command    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; var c = _ctx.GetCommand(r); &lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; //ejecutamos la consulta asincrónicamente y además le decimos que el resultado   &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; //lo mapee al tipo Dummy intentando hacer coincidir los nobmres de las    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; //propiedades    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; var result = _ctx.ExecuteQuery(typeof(Dummy), c.CommandText);    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }    &lt;br /&gt;} &lt;/p&gt;  &lt;p&gt;public class Dummy   &lt;br /&gt;{    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; public int ProductID { get; set; }    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; public string Name { get; set; }    &lt;br /&gt;} &lt;/p&gt;  &lt;p&gt;Mágico, nos vemos la próxima.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;Leonardo Micheloni&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/148524916779753368-6976246459155180423?l=leomicheloni.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://leomicheloni.blogspot.com/feeds/6976246459155180423/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=148524916779753368&amp;postID=6976246459155180423' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default/6976246459155180423'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default/6976246459155180423'/><link rel='alternate' type='text/html' href='http://leomicheloni.blogspot.com/2010/06/recuperar-la-consulta-generada-por.html' title='Recuperar la consulta generada por LinqToSql y ejecutar asincrónicamente'/><author><name>Leonardo Micheloni</name><uri>http://www.blogger.com/profile/12085246040181097881</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='30' src='http://3.bp.blogspot.com/_t9Bh42Thfqo/S6TVOJqYWcI/AAAAAAAAANU/MlZc6HpYZis/S220/yo+laguito+en+col%C3%B3n.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-148524916779753368.post-5893449379841211830</id><published>2010-05-19T11:42:00.001-03:00</published><updated>2010-05-19T11:42:08.228-03:00</updated><title type='text'>Des-Conferencia este sábado 22 de Mayo sobre NoSql con Java Lopez</title><content type='html'>&lt;p&gt;&lt;a href="http://lh4.ggpht.com/_t9Bh42Thfqo/S_P4vVPTiOI/AAAAAAAAAOU/Xq9qBPDPttM/s1600-h/image%5B8%5D.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; margin-left: 0px; border-top: 0px; margin-right: 0px; border-right: 0px" title="image" border="0" alt="image" align="right" src="http://lh6.ggpht.com/_t9Bh42Thfqo/S_P4v2NLFGI/AAAAAAAAAOY/ce9wsFgH378/image_thumb%5B4%5D.png?imgmax=800" width="244" height="146" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt; Este sábado 22 a las 18hs GMT habrá una reunión virttual de la gente de &lt;a href="http://altnet-hispano.pbworks.com/"&gt;Alt.Net hispano&lt;/a&gt; sobre &lt;a href="http://es.wikipedia.org/wiki/NoSQL"&gt;NoSql&lt;/a&gt; a cargo del maestro &lt;a href="http://msmvps.com/blogs/lopez/default.aspx"&gt;Angel Java Lopez&lt;/a&gt;, copio un poco de su post acá:&lt;/p&gt;  &lt;p&gt;&lt;em&gt;“El movimiento NoSQL apareció promoviendo el uso de almacenes de datos no relacionales. Surgió de varias fuentes y motivaciones, y tiene sus raíces aún en implementaciones anteriores a la aparición del modelo relacional.      &lt;br /&gt;Pasaremos revista, un poco a la historia, un poco a las primeras grandes implementaciones como BigTable de Google, o el Dynamo de Amazon. En los últimos años a aparecido una plétora de implementaciones, y se ha generado discusión sobre relacional vs NoSQL, cuándo, porqué.       &lt;br /&gt;Cómo cambia el diseño de una aplicación &amp;quot;normal&amp;quot; en NoSQL.       &lt;br /&gt;Queries, no más joins, denormalización.       &lt;br /&gt;No más esquemas.       &lt;br /&gt;Características deseables: cómo consiguen escalabilidad, alta disponibilidad, alto rendimiento.       &lt;br /&gt;El teorema CAP       &lt;br /&gt;Distintas formas de implementación:       &lt;br /&gt;Distribuidas vs No Distribuidas       &lt;br /&gt;En memoria vs En Disco       &lt;br /&gt;Key-Value vs Document vs Graph vs Column       &lt;br /&gt;Eventual Consistency       &lt;br /&gt;Proyectos más conocidos: Voldemort, Cassandra, CouchDB, MongoDB, SimpleDB, Memcached, BigTable, Dynamo, HBase...       &lt;br /&gt;Programaremos finalmente en .NET contra una de esas implementaciones, posiblemente MongoDB.       &lt;br /&gt;Espero que al final de la charla, todos tengamos una idea general de NoSQL, algunas características, código de ejemplo, disponible. Y entender, que al final, es una herramienta más: habrá casos en los que es más aplicable y otros en los que no.”&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;Nos vemos el sábado virtualmente ;) .&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;Leonardo Micheloni&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/148524916779753368-5893449379841211830?l=leomicheloni.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://leomicheloni.blogspot.com/feeds/5893449379841211830/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=148524916779753368&amp;postID=5893449379841211830' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default/5893449379841211830'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default/5893449379841211830'/><link rel='alternate' type='text/html' href='http://leomicheloni.blogspot.com/2010/05/des-conferencia-este-sabado-22-de-mayo.html' title='Des-Conferencia este sábado 22 de Mayo sobre NoSql con Java Lopez'/><author><name>Leonardo Micheloni</name><uri>http://www.blogger.com/profile/12085246040181097881</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='30' src='http://3.bp.blogspot.com/_t9Bh42Thfqo/S6TVOJqYWcI/AAAAAAAAANU/MlZc6HpYZis/S220/yo+laguito+en+col%C3%B3n.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh6.ggpht.com/_t9Bh42Thfqo/S_P4v2NLFGI/AAAAAAAAAOY/ce9wsFgH378/s72-c/image_thumb%5B4%5D.png?imgmax=800' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-148524916779753368.post-9162778145918028274</id><published>2010-05-10T12:07:00.001-03:00</published><updated>2010-05-10T12:09:09.321-03:00</updated><title type='text'>Error poco descriptivo en Microsoft Reporting</title><content type='html'>&lt;p&gt;En estos días me encuentro haciendo algunos reportes con Microsoft Reporting, una herramienta muy buena y poderosa, con la que incluso podemos invocar código .NET al generar reportes, etc. Por motivos de diseño de la aplicación que llama a la generación de reportes tengo que pasarle la gran mayoría de los datos como DataSources, hasta acá todo bien, en cierto momento haciendo esto:&lt;/p&gt;  &lt;pre style="width: 480px; height: 56px" class="code"&gt;&lt;span style="background: black; color: #ccffcc"&gt;localReport&lt;/span&gt;&lt;span style="background: black; color: yellow"&gt;.&lt;/span&gt;&lt;span style="background: black; color: #ccffcc"&gt;DataSources&lt;/span&gt;&lt;span style="background: black; color: yellow"&gt;.&lt;/span&gt;&lt;span style="background: black; color: #ccffcc"&gt;Add&lt;/span&gt;&lt;span style="background: black; color: white"&gt;(&lt;/span&gt;&lt;span style="background: black; color: cyan"&gt;new &lt;/span&gt;&lt;span style="background: black; color: #2b91af"&gt;ReportDataSource&lt;/span&gt;&lt;span style="background: black; color: white"&gt;(&lt;/span&gt;&lt;span style="background: black; color: red"&gt;&amp;quot;Dato&amp;quot;&lt;/span&gt;&lt;span style="background: black; color: white"&gt;, &lt;/span&gt;&lt;span style="background: black; color: #ccffcc"&gt;data&lt;/span&gt;&lt;span style="background: black; color: white"&gt;));
&lt;/span&gt;&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt; me encontré con un mensaje de error muy poco descriptivo que me dejó desorientado, el mismo decía así:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&amp;quot;Value does not fall within the expected range.&amp;quot;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;ok, rápido fui al stacktrace esperando más detalles, pero el mismo no dice nada al respecto, luego fui a &lt;a href="http://www.bing.com"&gt;www.bing.com&lt;/a&gt; y tampoco encontré nada al respecto, de última eché mano del amigo &lt;a href="http://www.red-gate.com/products/reflector/"&gt;Reflecto Pro y su increíble feature&lt;/a&gt; que permite ver el código de cualquier assembly (realmente con este tipo de cosas se paga sólo el&amp;#160; Reflector) me encontré con que en el set del value del DataSource hay esto:&lt;/p&gt;

&lt;pre style="width: 492px; height: 120px" class="code"&gt;&lt;span style="background: black; color: cyan"&gt;if &lt;/span&gt;&lt;span style="background: black; color: white"&gt;((&lt;/span&gt;&lt;span style="background: black; color: cyan"&gt;value &lt;/span&gt;&lt;span style="background: black; color: yellow"&gt;!= &lt;/span&gt;&lt;span style="background: black; color: cyan"&gt;null&lt;/span&gt;&lt;span style="background: black; color: white"&gt;) &lt;/span&gt;&lt;span style="background: black; color: yellow"&gt;&amp;amp;&amp;amp; !&lt;/span&gt;&lt;span style="background: black; color: white"&gt;((((&lt;/span&gt;&lt;span style="background: black; color: cyan"&gt;value is &lt;/span&gt;&lt;span style="background: black; color: #ccffcc"&gt;DataTable&lt;/span&gt;&lt;span style="background: black; color: white"&gt;) &lt;/span&gt;&lt;span style="background: black; color: yellow"&gt;|| &lt;/span&gt;&lt;span style="background: black; color: white"&gt;(&lt;/span&gt;&lt;span style="background: black; color: cyan"&gt;value is &lt;/span&gt;&lt;span style="background: black; color: #ccffcc"&gt;BindingSource&lt;/span&gt;&lt;span style="background: black; color: white"&gt;)) &lt;/span&gt;&lt;span style="background: black; color: yellow"&gt;|| &lt;/span&gt;&lt;span style="background: black; color: white"&gt;(&lt;/span&gt;&lt;span style="background: black; color: cyan"&gt;value is &lt;/span&gt;&lt;span style="background: black; color: #ccffcc"&gt;System&lt;/span&gt;&lt;span style="background: black; color: yellow"&gt;.&lt;/span&gt;&lt;span style="background: black; color: #2b91af"&gt;Type&lt;/span&gt;&lt;span style="background: black; color: white"&gt;)) &lt;/span&gt;&lt;span style="background: black; color: yellow"&gt;|| &lt;/span&gt;&lt;span style="background: black; color: white"&gt;(&lt;/span&gt;&lt;span style="background: black; color: cyan"&gt;value is &lt;/span&gt;&lt;span style="background: black; color: #2b91af"&gt;IEnumerable&lt;/span&gt;&lt;span style="background: black; color: white"&gt;)))
{
  &lt;/span&gt;&lt;span style="background: black; color: cyan"&gt;throw new &lt;/span&gt;&lt;span style="background: black; color: #2b91af"&gt;ArgumentException&lt;/span&gt;&lt;span style="background: black; color: white"&gt;();
}&lt;/span&gt;&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;O sea que lanza una excepción porque no lo estaba pasando un dato de ninguno de&amp;#160; estos tipo, con lo cual la solución fue hacer esto:&lt;/p&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;pre style="width: 488px; height: 78px" class="code"&gt;&lt;span style="background: black; color: #ccffcc"&gt;localReport&lt;/span&gt;&lt;span style="background: black; color: yellow"&gt;.&lt;/span&gt;&lt;span style="background: black; color: #ccffcc"&gt;DataSources&lt;/span&gt;&lt;span style="background: black; color: yellow"&gt;.&lt;/span&gt;&lt;span style="background: black; color: #ccffcc"&gt;Add&lt;/span&gt;&lt;span style="background: black; color: white"&gt;(&lt;/span&gt;&lt;span style="background: black; color: cyan"&gt;new &lt;/span&gt;&lt;span style="background: black; color: #2b91af"&gt;ReportDataSource&lt;/span&gt;&lt;span style="background: black; color: white"&gt;(&lt;/span&gt;&lt;span style="background: black; color: red"&gt;&amp;quot;Dato&amp;quot;&lt;/span&gt;&lt;span style="background: black; color: white"&gt;, &lt;/span&gt;&lt;span style="background: black; color: cyan"&gt;new &lt;/span&gt;&lt;span style="background: black; color: #2b91af"&gt;BindingSource&lt;/span&gt;&lt;span style="background: black; color: white"&gt;() { &lt;/span&gt;&lt;span style="background: black; color: #ccffcc"&gt;DataSource &lt;/span&gt;&lt;span style="background: black; color: yellow"&gt;= &lt;/span&gt;&lt;span style="background: black; color: #ccffcc"&gt;data &lt;/span&gt;&lt;span style="background: black; color: white"&gt;}));
&lt;/span&gt;&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;O sea, poner mi objeto dentro de un BindingSource, y santo remedio, secillo, pero oscuro. Nos leemos.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;Leonardo Micheloni&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/148524916779753368-9162778145918028274?l=leomicheloni.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://leomicheloni.blogspot.com/feeds/9162778145918028274/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=148524916779753368&amp;postID=9162778145918028274' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default/9162778145918028274'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default/9162778145918028274'/><link rel='alternate' type='text/html' href='http://leomicheloni.blogspot.com/2010/05/error-poco-descriptivo-en-microsoft.html' title='Error poco descriptivo en Microsoft Reporting'/><author><name>Leonardo Micheloni</name><uri>http://www.blogger.com/profile/12085246040181097881</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='30' src='http://3.bp.blogspot.com/_t9Bh42Thfqo/S6TVOJqYWcI/AAAAAAAAANU/MlZc6HpYZis/S220/yo+laguito+en+col%C3%B3n.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-148524916779753368.post-6060816672277366860</id><published>2010-05-09T14:50:00.001-03:00</published><updated>2010-05-09T16:30:44.648-03:00</updated><title type='text'>VAN sobre Moq publicada en Alt.Net hispano</title><content type='html'>&lt;p&gt;El pasado 27 de marzo tuve el honor de ser invitado por la gente de &lt;a href="http://altnet-hispano.pbworks.com"&gt;Alt.Net hispano&lt;/a&gt; a dar una VAN sobre &lt;a href="http://moq.me"&gt;Moq&lt;/a&gt;, fue una experiencia muy interesante sobre todo porque uno está sólo hablando a una pantalla y no sabe si los demás duermen o se fueron a pasear :) . Doy las gracias a &lt;a href="http://gambasoft.net"&gt;Jorge Gamba&lt;/a&gt; y a todos los asistentes por la invitación, les dejo el link del video y los invito a participar de la comunidad. &lt;/p&gt;  &lt;p&gt;&lt;a href="http://altnet-hispano.pbworks.com/van-2010-03-27-moq"&gt;VAN Sobre Moq en Alt.Net Hispano&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;PD: primer post desde &lt;a href="http://windowslivewriter.spaces.live.com/"&gt;Windows Live Writer&lt;/a&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;Leonardo Micheloni&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/148524916779753368-6060816672277366860?l=leomicheloni.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://leomicheloni.blogspot.com/feeds/6060816672277366860/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=148524916779753368&amp;postID=6060816672277366860' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default/6060816672277366860'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default/6060816672277366860'/><link rel='alternate' type='text/html' href='http://leomicheloni.blogspot.com/2010/05/van-sobre-moq-publicada-en-altnet.html' title='VAN sobre Moq publicada en Alt.Net hispano'/><author><name>Leonardo Micheloni</name><uri>http://www.blogger.com/profile/12085246040181097881</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='30' src='http://3.bp.blogspot.com/_t9Bh42Thfqo/S6TVOJqYWcI/AAAAAAAAANU/MlZc6HpYZis/S220/yo+laguito+en+col%C3%B3n.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-148524916779753368.post-1232742749505941627</id><published>2010-03-24T20:20:00.003-03:00</published><updated>2010-03-24T20:46:38.215-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='VAN'/><category scheme='http://www.blogger.com/atom/ns#' term='alt.net'/><category scheme='http://www.blogger.com/atom/ns#' term='moq'/><title type='text'>Reunión virtual sobre Moq este sábado por la tarde</title><content type='html'>&lt;a href="http://3.bp.blogspot.com/_t9Bh42Thfqo/S6qkWF_KOOI/AAAAAAAAAOE/89M7HEci4So/s1600/blue-old-van.gif"&gt;&lt;img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;width: 254px; height: 212px;" src="http://3.bp.blogspot.com/_t9Bh42Thfqo/S6qkWF_KOOI/AAAAAAAAAOE/89M7HEci4So/s320/blue-old-van.gif" border="0" alt=""id="BLOGGER_PHOTO_ID_5452350998356572386" /&gt;&lt;/a&gt;

&lt;strong&gt;VAN sobre Moq este sábado 18hs GMT (15hs Bueno Aires)&lt;/strong&gt;
&lt;p&gt;
Este sábado 27 de Marzo a las 18hs GMT (15hs de Argentina) la gente de &lt;a href="http://altnet-hispano.pbworks.com/"&gt;Alt.Net Hispano&lt;/a&gt;
organiza una &lt;a href="http://www.zachariahyoung.com/zy/post/2009/01/15/Introduction-to-Virtual-ALTNET.aspx"&gt;
VAN (Virtual Alt.Net) &lt;/a&gt; una reunión virtual para la cual es necesario acceder a la url 
&lt;a href="http://snipr.com/virtualaltnet"&gt;http://snipr.com/virtualaltnet&lt;/a&gt; con 
    &lt;a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=26c9da7c-f778-4422-a6f4-efb8abba021e&amp;amp;displaylang=en"&gt;NetMeeting&lt;/a&gt; (si no lo tenés te va a pedir que lo instales).
El espíritu de esta reunión es compartir el conocimiento acerca de este tema de una manera lo más interactiva posible, para ello
hay un &lt;a href="http://spreadsheets.google.com/ccc?key=taAgGxq4HRvJNCiVS9zrFSQ&amp;hl=es"&gt;google doc compartido &lt;/a&gt;para votar lo temas, sumar una al que más interese o proponer temas nuevos, es abierto.
No va a hacer ppt, ya que vamos a ver todos los ejemplos a través del código, entonce, está hecha la invitación, espero
ver sus nombre en el meeting este sábado. 
&lt;/p&gt;
&lt;p&gt;
    Esto es lo que escribí en el post en la lista del Alt.Net&lt;/p&gt;
&lt;p&gt;
&lt;b&gt;Resumen:&lt;/b&gt;
&lt;/p&gt;
&lt;p&gt;
    En la actualidad el software requiere altos niveles de calidad, las
    pruebas unitarias son una herramienta indispensable para alcanzar
    dicha calidad, desarrollar un software que sea fácil de probar
    requiere utilizar herramientas y patrones de diseño específicos, el
    mocking permite simular escenarios controlados para relizar nuestras
    pruebas. Dentro de los framework de mocking disponibles para .NET se
    destaca &lt;a href="http://moq.me"&gt;Moq&lt;/a&gt; por su facilidad de uso y limpieza de código, en este
    reunión virtual vamos a repasar los conceptos que son necesarios para
    una correcta prueba unitaria y descubriremos la potencia y belleza de
    &lt;a href="http://moq.me"&gt;Moq&lt;/a&gt;.
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;Leonardo Micheloni&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/148524916779753368-1232742749505941627?l=leomicheloni.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://leomicheloni.blogspot.com/feeds/1232742749505941627/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=148524916779753368&amp;postID=1232742749505941627' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default/1232742749505941627'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default/1232742749505941627'/><link rel='alternate' type='text/html' href='http://leomicheloni.blogspot.com/2010/03/reunion-virtual-sobre-moq-este-sabado.html' title='Reunión virtual sobre Moq este sábado por la tarde'/><author><name>Leonardo Micheloni</name><uri>http://www.blogger.com/profile/12085246040181097881</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='30' src='http://3.bp.blogspot.com/_t9Bh42Thfqo/S6TVOJqYWcI/AAAAAAAAANU/MlZc6HpYZis/S220/yo+laguito+en+col%C3%B3n.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_t9Bh42Thfqo/S6qkWF_KOOI/AAAAAAAAAOE/89M7HEci4So/s72-c/blue-old-van.gif' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-148524916779753368.post-4639554667440323466</id><published>2010-03-16T23:29:00.009-03:00</published><updated>2010-04-18T16:26:43.972-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='MVC'/><category scheme='http://www.blogger.com/atom/ns#' term='JQuery'/><category scheme='http://www.blogger.com/atom/ns#' term='MUG'/><title type='text'>Curso de capacitación "ASP.NET MVC + jQuery en Acción"</title><content type='html'>&lt;a href="http://2.bp.blogspot.com/_t9Bh42Thfqo/S6T8Y5OA07I/AAAAAAAAAN0/Lix9BrinaCM/s1600-h/asp-net-mvc.png"&gt;&lt;img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;width: 160px; height: 153px;" src="http://2.bp.blogspot.com/_t9Bh42Thfqo/S6T8Y5OA07I/AAAAAAAAAN0/Lix9BrinaCM/s320/asp-net-mvc.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5450758953631798194" /&gt;&lt;/a&gt;
&lt;div&gt;
&lt;strong&gt;CURSO DE CAPACITACIÓN: "ASP.NET MVC + JQUERY EN ACCIÓN"&lt;/strong&gt;

&lt;p&gt;El lunes, 12 de abril de 2010 en el auditorio del &lt;a href="http://www.mug.org.ar"&gt;MUG&lt;/a&gt; (Rivadavia 1479 1er Piso - Of. A - Ciudad de Buenos Aires) voy a estar dando un curso
sobre ASP.NET MVC + jQuery, se va a dividir en tres encuentros, el primero el lunes 12 una clase teórica para treinta personas y luego
dos días de práctica para quince personas cada uno, el martes 13 y el lunes 19, todo en el mismo lugar.
La idea es cubrir los aspectos teóricos necesarios para comenzar a trabajar con estas tecnologías y después hacer una pequeña aplicación desde 
cero apovechando su capacidad de interacción. El temario es el siguiente:
&lt;/p&gt;
&lt;p&gt;&lt;b&gt; jQuery:&lt;/b&gt; &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;NECESIDAD&lt;/li&gt;
&lt;li&gt;SELECTORES&lt;/li&gt;
&lt;li&gt;MANIPULACIÓN&lt;/li&gt;
&lt;li&gt;EFECTOS&lt;/li&gt;
&lt;li&gt;AJAX&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;b&gt;ASP.NET MVC:&lt;/b&gt; &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;HTML&lt;/li&gt;
&lt;li&gt;FORMULARIOS&lt;/li&gt;
&lt;li&gt;POST GET&lt;/li&gt;
&lt;li&gt;QUÉ ES MVC?&lt;/li&gt;
&lt;li&gt;MODEL&lt;/li&gt;
&lt;li&gt;VIEW&lt;/li&gt;
&lt;li&gt;CONTROLLERS&lt;/li&gt;
&lt;li&gt;ACTION FILTERS&lt;/li&gt; 
&lt;/ul&gt;

&lt;p&gt;Entonces nos vemos en el MUG, &lt;a href="http://www.mug.org.ar/Eventos/3438.aspx"&gt;dejo el link para registrarse&lt;/a&gt;, hasta entonces.&lt;/p&gt;
&lt;/div&gt;
&lt;p style="color: black; background-color: yellow"&gt;
&lt;strong&gt;UPDATE: Se agregó una fecha práctica más para el Martes 20 de Abril &lt;/strong&gt; &lt;/p&gt;
&lt;p&gt;Las fechas serían entonces:
&lt;ul&gt;
&lt;li&gt;Lunes 12/4 Teoría todos juntos en el auditorio&lt;/li&gt;
&lt;li&gt;Martes 13/4 Práctica grupo 1 en el laboratoio&lt;/li&gt;
&lt;li&gt;Lunes 19/4 Práctica grupo 2 en el laboratoio&lt;/li&gt;
&lt;li&gt;Martes 20/4 Práctica grupo 3 en el laboratoio&lt;/li&gt;
&lt;/ul&gt;
&lt;/p&gt;
&lt;p&gt;No vemos allá, salut&lt;/p&gt;
&lt;p style="color: black; background-color: yellow"&gt;
&lt;strong&gt;UPDATE: pueden descargar la ppt desde &lt;a href="http://cid-c9e9afda80ba37c1.skydrive.live.com/self.aspx/.Public/mvc%20mas%20jquery%20en%20accion.pptx"&gt;acá&lt;/a&gt; y el ejemplo que desarrollamos durante la teoría &lt;a href="http://cid-c9e9afda80ba37c1.skydrive.live.com/self.aspx/.Public/ejemploMVC.rar"&gt;acá&lt;/a&gt;&lt;/strong&gt;
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;Leonardo Micheloni&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/148524916779753368-4639554667440323466?l=leomicheloni.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://leomicheloni.blogspot.com/feeds/4639554667440323466/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=148524916779753368&amp;postID=4639554667440323466' title='4 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default/4639554667440323466'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default/4639554667440323466'/><link rel='alternate' type='text/html' href='http://leomicheloni.blogspot.com/2010/03/curso-de-capacitacion-aspnet-mvc-jquery.html' title='Curso de capacitación &quot;ASP.NET MVC + jQuery en Acción&quot;'/><author><name>Leonardo Micheloni</name><uri>http://www.blogger.com/profile/12085246040181097881</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='30' src='http://3.bp.blogspot.com/_t9Bh42Thfqo/S6TVOJqYWcI/AAAAAAAAANU/MlZc6HpYZis/S220/yo+laguito+en+col%C3%B3n.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_t9Bh42Thfqo/S6T8Y5OA07I/AAAAAAAAAN0/Lix9BrinaCM/s72-c/asp-net-mvc.png' height='72' width='72'/><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-148524916779753368.post-8873189483302618563</id><published>2010-02-18T12:16:00.005-03:00</published><updated>2010-02-24T22:58:15.780-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='MUG'/><title type='text'>Charla en el MUG "Repasando VS 2008 - Introducción al Framework 3.5 y C#3.0"</title><content type='html'>&lt;p class="style2"&gt;&lt;span class="style6"&gt;&lt;span style="font-family:verdana;"&gt;&lt;span style="font-size:130%;"&gt;&lt;span style="color:#009900;"&gt;Repasando VS 2008 - Introducción al Framework 3.5 y C#3.0&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family:verdana;"&gt; &lt;/span&gt;&lt;/p&gt;&lt;span style="font-family:verdana;"&gt;&lt;/span&gt;&lt;p class="style1"&gt;&lt;span style="font-family:verdana;"&gt;&lt;em&gt;La semana que viene voy a estar por el MUG dando una &lt;a href="http://www.mug.org.ar/Eventos/3427.aspx"&gt;nueva charla&lt;/a&gt;, en este caso sobre cositas del framework 3.5 y C#3, la idea es ir haciendo el camino de los conceptos hasta llegar a Linq y sus variantes. Nos vemos en el MUG.&lt;/em&gt;&lt;/span&gt;&lt;b&gt;&lt;span style="font-family:verdana;"&gt;
&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;&lt;p class="style1"&gt;&lt;span style="font-family:verdana;"&gt;&lt;/span&gt;&lt;b&gt;&lt;span style="font-family:verdana;"&gt;Fechas y Horarios:&lt;/span&gt;&lt;/b&gt;&lt;span style="font-family:verdana;"&gt; &lt;/span&gt;&lt;span class="style5"&gt;&lt;span style="font-family:verdana;"&gt;Miércoles 24 de febrero de 2010 de 18.30 a 21.30 hs. &lt;/span&gt;&lt;/span&gt;&lt;span style="font-family:verdana;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;span style="font-family:verdana;"&gt;&lt;/span&gt;&lt;p class="style1"&gt;&lt;span style="font-family:verdana;"&gt;&lt;/span&gt;&lt;b&gt;&lt;span style="font-family:verdana;"&gt;Lugar:&lt;/span&gt;&lt;/b&gt;&lt;span style="font-family:verdana;"&gt; Auditorio del MUG: Rivadavia 1479 1er Piso - Ciudad de Buenos Aires. &lt;/span&gt;&lt;/p&gt;&lt;span style="font-family:verdana;"&gt;&lt;/span&gt;&lt;p class="style1"&gt;&lt;span style="font-family:verdana;"&gt;Mientras esperamos la llegado del framework 4.0 y Visual Studio 2010 haremos un repaso de las características más sobresalientes de C#3 y Visual Studio 2008 que nos facilitan la tarea diaria y hacen la programación más entretenida. &lt;/span&gt;&lt;/p&gt;&lt;span style="font-family:verdana;"&gt;&lt;/span&gt;&lt;p class="style2"&gt;&lt;span style="font-family:verdana;"&gt;&lt;strong&gt;Contenidos:&lt;/strong&gt; &lt;/span&gt;&lt;/p&gt;&lt;span style="font-family:verdana;"&gt;&lt;/span&gt;&lt;p class="style4"&gt;&lt;span style="font-family:verdana;"&gt;- Delegados &lt;/span&gt;&lt;/p&gt;&lt;span style="font-family:verdana;"&gt;&lt;/span&gt;&lt;p class="style4"&gt;&lt;span style="font-family:verdana;"&gt;- Inicializadores &lt;/span&gt;&lt;/p&gt;&lt;span style="font-family:verdana;"&gt;&lt;/span&gt;&lt;p class="style4"&gt;&lt;span style="font-family:verdana;"&gt;- Tipos anónimos &lt;/span&gt;&lt;/p&gt;&lt;span style="font-family:verdana;"&gt;&lt;/span&gt;&lt;p class="style4"&gt;&lt;span style="font-family:verdana;"&gt;- qué es var? &lt;/span&gt;&lt;/p&gt;&lt;span style="font-family:verdana;"&gt;&lt;/span&gt;&lt;p class="style4"&gt;&lt;span style="font-family:verdana;"&gt;- Métodos anónimos &lt;/span&gt;&lt;/p&gt;&lt;span style="font-family:verdana;"&gt;&lt;/span&gt;&lt;p class="style4"&gt;&lt;span style="font-family:verdana;"&gt;- Propiedades automáticas &lt;/span&gt;&lt;/p&gt;&lt;span style="font-family:verdana;"&gt;&lt;/span&gt;&lt;p class="style4"&gt;&lt;span style="font-family:verdana;"&gt;- Métodos de extensión &lt;/span&gt;&lt;/p&gt;&lt;span style="font-family:verdana;"&gt;&lt;/span&gt;&lt;p class="style4"&gt;&lt;span style="font-family:verdana;"&gt;- Expresiones Lambda &lt;/span&gt;&lt;/p&gt;&lt;span style="font-family:verdana;"&gt;&lt;/span&gt;&lt;p class="style4"&gt;&lt;span style="font-family:verdana;"&gt;- Linq - LinqToXml, LinqToSql - &lt;/span&gt;&lt;/p&gt;&lt;span style="font-family:verdana;"&gt;&lt;/span&gt;&lt;p class="style4"&gt;&lt;span style="font-family:verdana;"&gt;Y otras características de C#3 &lt;/span&gt;&lt;/p&gt;&lt;span style="font-family:verdana;"&gt;&lt;/span&gt;&lt;p class="style1"&gt;&lt;span style="font-family:verdana;"&gt;&lt;/span&gt;&lt;span class="style3"&gt;&lt;span style="font-family:verdana;"&gt;&lt;span style="color:#3333ff;"&gt;&lt;a href="http://www.mug.org.ar/Eventos/3427.aspx"&gt;EVENTO GRATUITO ignore la pregunta sobre forma de pago. VACANTES LIMITADAS.&lt;/a&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong style="background-color:yellow"&gt;UPDATE dejo un &lt;a href="http://cid-c9e9afda80ba37c1.skydrive.live.com/self.aspx/.Public/VS2008.rar"&gt;link con el código y la ppt &lt;/a&gt;de la charla &lt;/strong&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;Leonardo Micheloni&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/148524916779753368-8873189483302618563?l=leomicheloni.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://leomicheloni.blogspot.com/feeds/8873189483302618563/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=148524916779753368&amp;postID=8873189483302618563' title='2 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default/8873189483302618563'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default/8873189483302618563'/><link rel='alternate' type='text/html' href='http://leomicheloni.blogspot.com/2010/02/charla-en-el-mug-repasando-vs-2008.html' title='Charla en el MUG &quot;Repasando VS 2008 - Introducción al Framework 3.5 y C#3.0&quot;'/><author><name>Leonardo Micheloni</name><uri>http://www.blogger.com/profile/12085246040181097881</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='30' src='http://3.bp.blogspot.com/_t9Bh42Thfqo/S6TVOJqYWcI/AAAAAAAAANU/MlZc6HpYZis/S220/yo+laguito+en+col%C3%B3n.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-148524916779753368.post-6682818838066309723</id><published>2010-02-06T22:58:00.005-03:00</published><updated>2010-02-06T23:04:26.974-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='REST'/><category scheme='http://www.blogger.com/atom/ns#' term='xml'/><category scheme='http://www.blogger.com/atom/ns#' term='c#'/><category scheme='http://www.blogger.com/atom/ns#' term='LINQ'/><title type='text'>Actualizar Twitter desde .net</title><content type='html'>&lt;strong&gt;Actualizar y recuperar el timeline de Twitter desde .net&lt;/strong&gt;
&lt;p&gt;Luego de una larga ausencia (que no se repetirá hasta que se repita) dejo un pequño ejemplo autodescriptivo sobre cómo actualizar y recuperar el timeline de Twitter con nuestro querido .net&lt;/p&gt;
&lt;p&gt;Es un gran ejemplo sobre REST y las facilidades de System.Net y de LinqToXML, enjoy&lt;/p&gt;

&lt;br /&gt;

&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
&lt;pre class="csharpcode"&gt;
&lt;span class="kwrd"&gt;using&lt;/span&gt; System;
&lt;span class="kwrd"&gt;using&lt;/span&gt; System.Linq;
&lt;span class="kwrd"&gt;using&lt;/span&gt; System.Net;
&lt;span class="kwrd"&gt;using&lt;/span&gt; System.Text;
&lt;span class="kwrd"&gt;using&lt;/span&gt; System.Xml.Linq;

&lt;span class="kwrd"&gt;namespace&lt;/span&gt; twitterUpdater
{
    &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;
    &lt;span class="rem"&gt;/// Ejemplo sobre cómo actualizar twitter y leer el timeline desde .net&lt;/span&gt;
    &lt;span class="rem"&gt;/// http://apiwiki.twitter.com/Twitter-API-Documentation&lt;/span&gt;
    &lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;
    &lt;span class="kwrd"&gt;class&lt;/span&gt; Program
    {
        &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;
        &lt;span class="rem"&gt;/// Nuestras credenciales de twitter&lt;/span&gt;
        &lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;public&lt;/span&gt; NetworkCredential Credential
        {
            get
            {
                &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;new&lt;/span&gt; NetworkCredential(&lt;span class="str"&gt;"leomicheloni"&lt;/span&gt;, &lt;span class="str"&gt;"mi_password"&lt;/span&gt;);
            }
        }

        &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Main(&lt;span class="kwrd"&gt;string&lt;/span&gt;[] args)
        {
            var p = &lt;span class="kwrd"&gt;new&lt;/span&gt; Program();

            &lt;span class="rem"&gt;//Actualizamos nuestro estado&lt;/span&gt;
            p.Update(&lt;span class="str"&gt;"puedo tuitearte?"&lt;/span&gt;);

            &lt;span class="rem"&gt;//traemos el timeline&lt;/span&gt;
            p.GetTimeLine();

            Console.ReadLine();
        }

        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Update(&lt;span class="kwrd"&gt;string&lt;/span&gt; status)
        {
            var url = &lt;span class="str"&gt;"http://twitter.com/statuses/update.xml?status={0}"&lt;/span&gt;;

            var request = HttpWebRequest.Create(String.Format(url, status));

            request.ContentLength = 0; &lt;span class="rem"&gt;//el largo del contenido HTTP es cero porque todo lo necesario va en la url&lt;/span&gt;
            request.ContentType = &lt;span class="str"&gt;"application/x-www-form-urlencoded"&lt;/span&gt;; ;
            request.Credentials = Credential; &lt;span class="rem"&gt;//nuestras credenciales de twitter&lt;/span&gt;
            request.Method = &lt;span class="str"&gt;"POST"&lt;/span&gt;; &lt;span class="rem"&gt;//para enviar usamos el verbo POST&lt;/span&gt;

            &lt;span class="rem"&gt;//simplemente enviamos el request&lt;/span&gt;
            var response = request.GetResponse() &lt;span class="kwrd"&gt;as&lt;/span&gt; HttpWebResponse;

            &lt;span class="kwrd"&gt;if&lt;/span&gt; (response.StatusCode != HttpStatusCode.OK &amp;amp;&amp;amp; response.StatusCode != HttpStatusCode.Continue)
                &lt;span class="kwrd"&gt;throw&lt;/span&gt; &lt;span class="kwrd"&gt;new&lt;/span&gt; ApplicationException(response.StatusCode.ToString());
        }

        &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;
        &lt;span class="rem"&gt;/// Recupera la actividad de las personas que seguimos y de nosotros mismos&lt;/span&gt;
        &lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; GetTimeLine()
        {
            var url = &lt;span class="str"&gt;"http://twitter.com/statuses/friends_timeline.xml?count=3"&lt;/span&gt;;

            var request = HttpWebRequest.Create(url);

            request.ContentLength = 0;
            request.ContentType = &lt;span class="str"&gt;"application/x-www-form-urlencoded"&lt;/span&gt;; ;
            request.Credentials = Credential;
            request.Method = &lt;span class="str"&gt;"GET"&lt;/span&gt;; &lt;span class="rem"&gt;//en este caso el verbo HTTP es GET&lt;/span&gt;

            var response = request.GetResponse() &lt;span class="kwrd"&gt;as&lt;/span&gt; HttpWebResponse;

            &lt;span class="kwrd"&gt;if&lt;/span&gt; (response.StatusCode != HttpStatusCode.OK &amp;amp;&amp;amp; response.StatusCode != HttpStatusCode.Continue)
                &lt;span class="kwrd"&gt;throw&lt;/span&gt; &lt;span class="kwrd"&gt;new&lt;/span&gt; ApplicationException(response.StatusCode.ToString());

            &lt;span class="rem"&gt;//recuperamos la respuesta&lt;/span&gt;
            var stream = response.GetResponseStream();

            var length = response.ContentLength;

            var buffer = &lt;span class="kwrd"&gt;new&lt;/span&gt; &lt;span class="kwrd"&gt;byte&lt;/span&gt;[length];

            stream.Read(buffer, 0, (&lt;span class="kwrd"&gt;int&lt;/span&gt;)length);

            var xml = Encoding.UTF8.GetString(buffer);

            &lt;span class="rem"&gt;//la respuesta es un xml como se especifica en http://apiwiki.twitter.com/Twitter-REST-API-Method%3A-statuses-friends_timeline&lt;/span&gt;
            var doc = XDocument.Parse(xml);

            var statuses = from item &lt;span class="kwrd"&gt;in&lt;/span&gt; doc.Document.Element(&lt;span class="str"&gt;"statuses"&lt;/span&gt;).Nodes().ToArray()
                           select (item &lt;span class="kwrd"&gt;as&lt;/span&gt; XElement);

            &lt;span class="kwrd"&gt;foreach&lt;/span&gt; (var status &lt;span class="kwrd"&gt;in&lt;/span&gt; statuses)
            {
                Console.WriteLine(status.Element(&lt;span class="str"&gt;"user"&lt;/span&gt;).Element(&lt;span class="str"&gt;"name"&lt;/span&gt;).Value + &lt;span class="str"&gt;" = "&lt;/span&gt; + status.Element(&lt;span class="str"&gt;"text"&lt;/span&gt;).Value);
            }
        }
    }
}
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;Leonardo Micheloni&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/148524916779753368-6682818838066309723?l=leomicheloni.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://leomicheloni.blogspot.com/feeds/6682818838066309723/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=148524916779753368&amp;postID=6682818838066309723' title='2 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default/6682818838066309723'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default/6682818838066309723'/><link rel='alternate' type='text/html' href='http://leomicheloni.blogspot.com/2010/02/actualizar-tweeter-desde-net.html' title='Actualizar Twitter desde .net'/><author><name>Leonardo Micheloni</name><uri>http://www.blogger.com/profile/12085246040181097881</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='30' src='http://3.bp.blogspot.com/_t9Bh42Thfqo/S6TVOJqYWcI/AAAAAAAAANU/MlZc6HpYZis/S220/yo+laguito+en+col%C3%B3n.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-148524916779753368.post-4179188248161161790</id><published>2009-11-02T14:30:00.001-03:00</published><updated>2009-11-02T14:31:35.955-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='c#'/><title type='text'>Serialización binaria, ejemplo simple</title><content type='html'>&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
&lt;pre class="csharpcode"&gt;
&lt;span class="kwrd"&gt;using&lt;/span&gt; System;
&lt;span class="kwrd"&gt;using&lt;/span&gt; System.Collections.Generic;
&lt;span class="kwrd"&gt;using&lt;/span&gt; System.Linq;
&lt;span class="kwrd"&gt;using&lt;/span&gt; System.Text;
&lt;span class="kwrd"&gt;using&lt;/span&gt; System.Runtime.Serialization.Formatters.Binary;
&lt;span class="kwrd"&gt;using&lt;/span&gt; System.IO;
&lt;span class="kwrd"&gt;using&lt;/span&gt; System.Diagnostics;

&lt;span class="kwrd"&gt;namespace&lt;/span&gt; ConsoleApplication14
{
    &lt;span class="kwrd"&gt;class&lt;/span&gt; Program
    {
        &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Main(&lt;span class="kwrd"&gt;string&lt;/span&gt;[] args)
        {
            &lt;span class="rem"&gt;//Crea el formatter que es el encargado de serializar&lt;/span&gt;
            var formatter = &lt;span class="kwrd"&gt;new&lt;/span&gt; BinaryFormatter();

            &lt;span class="rem"&gt;//Es necesario un Strema de cualquier tipo (un FileStream por ejemplo)&lt;/span&gt;
            var stream = &lt;span class="kwrd"&gt;new&lt;/span&gt; MemoryStream();

            &lt;span class="rem"&gt;//se instancia el objeto a serializar&lt;/span&gt;
            var o = &lt;span class="kwrd"&gt;new&lt;/span&gt; MyClass() { MyProperty = 1, MyProperty2 = &lt;span class="str"&gt;"dos"&lt;/span&gt;, PropiedadIgnorada =&lt;span class="str"&gt;"Ignorar"&lt;/span&gt; };
            o.SetValorPrivado(&lt;span class="kwrd"&gt;true&lt;/span&gt;);

            &lt;span class="rem"&gt;//Se serializa el objeto y se pone en el Stream&lt;/span&gt;
            formatter.Serialize(stream, o);

            var data = stream.ToArray();

            &lt;span class="rem"&gt;//De-serializamos&lt;/span&gt;
            var o2 = (MyClass) formatter.Deserialize(&lt;span class="kwrd"&gt;new&lt;/span&gt; MemoryStream(data));

            
            &lt;span class="rem"&gt;//verificamos que el objeto de-serializado sea igual al original&lt;/span&gt;
            Debug.Assert(o.MyProperty.Equals(o2.MyProperty));
            Debug.Assert(o.MyProperty2.Equals(o2.MyProperty2));

            &lt;span class="rem"&gt;//La propiedad que no se serializó queda en null&lt;/span&gt;
            Debug.Assert(o2.PropiedadIgnorada==&lt;span class="kwrd"&gt;null&lt;/span&gt;);

            &lt;span class="rem"&gt;//notar que se serilizan los valores privados también&lt;/span&gt;
            Debug.Assert(o.VerificarValorPrivado().Equals(o2.VerificarValorPrivado()));
        }
    }

    &lt;span class="rem"&gt;//Las clases para serializar con el serializador binario tienen que estar marcadas&lt;/span&gt;
    &lt;span class="rem"&gt;//como Serilizable&lt;/span&gt;
    [Serializable]
    &lt;span class="kwrd"&gt;class&lt;/span&gt; MyClass
    {
        &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;bool&lt;/span&gt; _private;

        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;int&lt;/span&gt; MyProperty { get; set; }
        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; MyProperty2 { get; set; }

        &lt;span class="rem"&gt;//con el atributo NonSerialized se ignoran propiedades&lt;/span&gt;
        &lt;span class="rem"&gt;//que no queremos serilizar&lt;/span&gt;
        [System.NonSerialized]
        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; PropiedadIgnorada;

        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; SetValorPrivado(&lt;span class="kwrd"&gt;bool&lt;/span&gt; valor)
        {
            _private = valor;
        }

        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;bool&lt;/span&gt; VerificarValorPrivado()
        {
            &lt;span class="kwrd"&gt;return&lt;/span&gt; _private;
        }
    }
}
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;Leonardo Micheloni&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/148524916779753368-4179188248161161790?l=leomicheloni.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://leomicheloni.blogspot.com/feeds/4179188248161161790/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=148524916779753368&amp;postID=4179188248161161790' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default/4179188248161161790'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default/4179188248161161790'/><link rel='alternate' type='text/html' href='http://leomicheloni.blogspot.com/2009/11/serializacion-binaria-ejemplo-simple.html' title='Serialización binaria, ejemplo simple'/><author><name>Leonardo Micheloni</name><uri>http://www.blogger.com/profile/12085246040181097881</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='30' src='http://3.bp.blogspot.com/_t9Bh42Thfqo/S6TVOJqYWcI/AAAAAAAAANU/MlZc6HpYZis/S220/yo+laguito+en+col%C3%B3n.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-148524916779753368.post-7010064104415687648</id><published>2009-10-17T14:01:00.001-03:00</published><updated>2009-10-17T14:03:29.950-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='teoria de objetos'/><title type='text'>Teoría de objetos: Diferencia entre clase y objeto</title><content type='html'>&lt;p&gt;
        &lt;b&gt;Diferencia entre clase y objeto&lt;/b&gt;&lt;/p&gt;
    &lt;p&gt;
        Antes que nada vamos a comenzar aclarando una diferencia que muchas veces cuesta 
        comprender: diferencia entre clase y objeto     &lt;/p&gt;
        &lt;ul&gt;
        &lt;li&gt;Clase: una clase es un molde, un concepto, una abstracción, por ejemplo: 
        Automóvil&lt;/li&gt;
        &lt;li&gt;Objeto: un objeto es una instancia de una clase, un elemento concreto de una 
        abstracción por ejemplo: MiAuto es una instacia de la clase auto&lt;/li&gt;
        &lt;/ul&gt;
        &lt;p&gt;En C# sería así:&lt;/p&gt;
        &lt;p&gt;Clase Automóvil:&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
&lt;pre class="csharpcode"&gt;
&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; Automovil
{
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Arrancar();
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; Marca { get; set; }
}&lt;/pre&gt;
&lt;br /&gt;
&lt;p&gt;Objeto miAuto&lt;/p&gt;
&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
&lt;pre class="csharpcode"&gt;
Automovil miAuto = &lt;span class="kwrd"&gt;new&lt;/span&gt; Automovil();&lt;/pre&gt;
&lt;br /&gt;
&lt;p&gt;Así comenzamos con una pequeña serie de pequeños post con conceptos  básicos, espero que los disfruten. Hasta la próxima&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;Leonardo Micheloni&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/148524916779753368-7010064104415687648?l=leomicheloni.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://leomicheloni.blogspot.com/feeds/7010064104415687648/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=148524916779753368&amp;postID=7010064104415687648' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default/7010064104415687648'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default/7010064104415687648'/><link rel='alternate' type='text/html' href='http://leomicheloni.blogspot.com/2009/10/teoria-de-objetos-diferencia-entre.html' title='Teoría de objetos: Diferencia entre clase y objeto'/><author><name>Leonardo Micheloni</name><uri>http://www.blogger.com/profile/12085246040181097881</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='30' src='http://3.bp.blogspot.com/_t9Bh42Thfqo/S6TVOJqYWcI/AAAAAAAAANU/MlZc6HpYZis/S220/yo+laguito+en+col%C3%B3n.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-148524916779753368.post-5411478382860482608</id><published>2009-07-25T14:17:00.003-03:00</published><updated>2009-07-25T14:49:24.954-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='mock'/><category scheme='http://www.blogger.com/atom/ns#' term='MUG'/><category scheme='http://www.blogger.com/atom/ns#' term='IoC'/><category scheme='http://www.blogger.com/atom/ns#' term='ASP.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='patrones'/><category scheme='http://www.blogger.com/atom/ns#' term='unit test'/><category scheme='http://www.blogger.com/atom/ns#' term='LINQ'/><title type='text'>Workshop con PC: "Desarrollando aplicaciones Web con herramientas y prácticas actuales".</title><content type='html'>&lt;p&gt;Los días Lunes 24, martes 25, Lunes 31 de Agosto y Martes 1 de septiembre de 18:30 a 21:30, estaré en las instalaciones del &lt;a href="http://www.mug.org.ar"&gt;Grupo de usuarios de Microsoft&lt;/a&gt; dictando un workshop con máquina sobre desarrollo&lt;/p&gt;
&lt;p&gt;La idea es ver el desarrollo de una aplicación web utilizando herramientas y técnicas de uso diario (un poco en contraposición al clásico "novedades de .net 12") para que podamos llevarnos conocimientos para aplicarlos en el día a día, si bien el temario es extenso nada quita que podamos ir abordando temas que surgan en el momento&lt;/p&gt;
&lt;p&gt;En resumen, la idea es que todos aprendamos y nos llevemos algo que nos ayudea a mejorar nuestros desarrollos&lt;/p&gt;

&lt;p&gt;Entre los temas centrales tenemos&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;ASP.NET MVC&lt;/li&gt;
&lt;li&gt;UNIT TEST/ MOCKING&lt;/li&gt;
&lt;li&gt;PATRONES&lt;/li&gt;
&lt;li&gt;LINQ&lt;/li&gt;
&lt;li&gt;EXPRESIONES LAMBDA&lt;/li&gt;
&lt;li&gt;INVERSIÓN DE CONTROL/ INYECCIÓN DE DEPENDENCIAS&lt;/li&gt;
&lt;li&gt;MÉTODOS DE EXTENSIÓN&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Dejo el &lt;a href="http://www.mug.org.ar/Eventos/3337.aspx"&gt;link de la charla&lt;/a&gt; para que se anoten, nos vemos en el MUG&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;Leonardo Micheloni&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/148524916779753368-5411478382860482608?l=leomicheloni.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://leomicheloni.blogspot.com/feeds/5411478382860482608/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=148524916779753368&amp;postID=5411478382860482608' title='2 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default/5411478382860482608'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default/5411478382860482608'/><link rel='alternate' type='text/html' href='http://leomicheloni.blogspot.com/2009/07/workshop-con-pc-desarrollando.html' title='Workshop con PC: &quot;Desarrollando aplicaciones Web con herramientas y prácticas actuales&quot;.'/><author><name>Leonardo Micheloni</name><uri>http://www.blogger.com/profile/12085246040181097881</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='30' src='http://3.bp.blogspot.com/_t9Bh42Thfqo/S6TVOJqYWcI/AAAAAAAAANU/MlZc6HpYZis/S220/yo+laguito+en+col%C3%B3n.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-148524916779753368.post-1242189730364712063</id><published>2009-07-16T17:37:00.005-03:00</published><updated>2009-07-16T17:41:57.040-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='mock'/><category scheme='http://www.blogger.com/atom/ns#' term='MVC'/><category scheme='http://www.blogger.com/atom/ns#' term='JQuery'/><category scheme='http://www.blogger.com/atom/ns#' term='MUG'/><category scheme='http://www.blogger.com/atom/ns#' term='extension methods'/><category scheme='http://www.blogger.com/atom/ns#' term='expresiones lambda'/><category scheme='http://www.blogger.com/atom/ns#' term='unit test'/><category scheme='http://www.blogger.com/atom/ns#' term='LINQ'/><category scheme='http://www.blogger.com/atom/ns#' term='eventos'/><category scheme='http://www.blogger.com/atom/ns#' term='delegados'/><title type='text'>UPDATE: Curso sobre desarrollo en el MUG</title><content type='html'>&lt;p&gt;Casi termino de redondear el temario para el pequeño curso que voy a dictar en el &lt;a href="http://www.mug.org.ar"&gt;MUG&lt;/a&gt; seguramente a mitad de Agosto, aún falta definir si los cuatro encuentros ser dividirán en dos semanas de dos encuentros y cuatro de uno y los días, lo seguro es que será de 18:30 a 21:30. Dejo el temario actualizado.&lt;/p&gt;
&lt;br /&gt;
&lt;strong&gt;Desarrollando aplicaciones Web con herramientas y prácticas actuales.&lt;/strong&gt;
&lt;p&gt;Cuatro sesiones recorriendo los elementos actuales del desarrollo web utilizando la tecnología.NET &lt;/p&gt;
&lt;p&gt;
  &lt;ul&gt;
    &lt;li&gt;
      1 - Conceptos básicos:
      &lt;ul&gt;
        &lt;li&gt;Delegados, Eventos&lt;/li&gt;
        &lt;li&gt;Reflector, la herramienta indispensable&lt;/li&gt;
        &lt;li&gt;Extension methods&lt;/li&gt;
        &lt;li&gt;Expresiones lambda&lt;/li&gt;
        &lt;li&gt;Linq&lt;/li&gt;
        &lt;li&gt;Refactor, mejorando el código&lt;/li&gt;
        &lt;li&gt;Http, verbos, qué pasa en el cable?&lt;/li&gt;
        &lt;li&gt;Html, css&lt;/li&gt;
      &lt;/ul&gt;
    &lt;/li&gt;
    &lt;li&gt;
    &lt;ul&gt;2-Comenzando con la aplicación web, paso a paso:
      &lt;li&gt;Fiddler, firebug, IEDeveloper toolbar herramientas para tener a mano&lt;/li&gt;
      &lt;li&gt;Asp.net MVC. ¿Por qué? ¿Qué ventajas tiene?&lt;/li&gt;
      &lt;li&gt;jQuery para acelerar el desarrollo de javascript&lt;/li&gt;
      &lt;li&gt;Ajax para hacer más interactiva las aplicaciones&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;3-Mejorando el diseño:
    &lt;ul&gt;
      &lt;li&gt;Más de lo anterior&lt;/li&gt;
      &lt;li&gt;Desacoplando las cosas&lt;/li&gt;
      &lt;li&gt;Patrones para todos los días Repository, Factory, etc.&lt;/li&gt;
      &lt;li&gt;IoC&lt;/li&gt;
      &lt;li&gt;Inyección de dependencias&lt;/li&gt;
      &lt;li&gt;ORM&lt;/li&gt;
      &lt;li&gt;Linq2sql&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;
    4-Testing y otras cuestiones:
    &lt;ul&gt;
      &lt;li&gt;Aumentando la calidad de nuestra aplicación&lt;/li&gt;
      &lt;li&gt;Unit test&lt;/li&gt;
      &lt;li&gt;Code coverage. ¿Qué tanto se ha probado?&lt;/li&gt;
      &lt;li&gt;Mocking&lt;/li&gt;
      &lt;li&gt;TDD&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;/ul&gt;
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;Leonardo Micheloni&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/148524916779753368-1242189730364712063?l=leomicheloni.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://leomicheloni.blogspot.com/feeds/1242189730364712063/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=148524916779753368&amp;postID=1242189730364712063' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default/1242189730364712063'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default/1242189730364712063'/><link rel='alternate' type='text/html' href='http://leomicheloni.blogspot.com/2009/07/update-curso-sobre-desarrollo-en-el-mug.html' title='UPDATE: Curso sobre desarrollo en el MUG'/><author><name>Leonardo Micheloni</name><uri>http://www.blogger.com/profile/12085246040181097881</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='30' src='http://3.bp.blogspot.com/_t9Bh42Thfqo/S6TVOJqYWcI/AAAAAAAAANU/MlZc6HpYZis/S220/yo+laguito+en+col%C3%B3n.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-148524916779753368.post-7701859600447346285</id><published>2009-07-01T11:25:00.001-03:00</published><updated>2009-07-01T11:25:59.641-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='agiles2008'/><category scheme='http://www.blogger.com/atom/ns#' term='agiles2009'/><title type='text'>Llamada a participación Ágiles2009 en Brasil</title><content type='html'>&lt;p&gt;
        Estimado colega,
    &lt;/p&gt;
    &lt;p&gt;
        Qué opinas de formar parte del equipo de expositores que reune nombres como 
        Brian Marick, Diana Larsen, Matt Gelbwaks, Naresh Jain, Dave Nicolette, Alan 
        Cyment, Alexandre Magno, entre otros?&lt;/p&gt;
    &lt;p&gt;
&amp;nbsp;El próximo lunes 6 de julio será la última oportunidad para presentar tu propuesta 
        de charla en Ágiles 2009!
    &lt;/p&gt;
    &lt;p&gt;
        Ágiles 2009, a realizarse en Florianópolis, Brasil, es un evento sin fines de 
        lucro, organizado por profesionales entusiastas del tema, unidos por el objetivo 
        de crear un espacio amplio de discusión sobre las metodologías ágiles y su 
        adopción en América Latina. Como expositor, tendrás acceso libre a la 
        conferencia y otras ventajas que los organizadores están preparando para ti! 
        Puedes proponer una presentación, un tutorial, un reporte de experiencias o un 
        workshop.
    &lt;/p&gt;
    &lt;p&gt;
        Accede a http://www.agiles2009.org/es/submissions.php para ver la información 
        que debes proporcionar para presentar tus propuestas.&lt;/p&gt;
    &lt;p&gt;
&amp;nbsp;Esperamos contar contigo en Ágiles 2009!&lt;/p&gt;
    &lt;p&gt;
&amp;nbsp;Comité Organizador &lt;a href="http://www.agiles2009.org"&gt;www.agiles2009.org&lt;/a&gt;&lt;/p&gt;
    &lt;p&gt;
        &amp;nbsp;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;Leonardo Micheloni&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/148524916779753368-7701859600447346285?l=leomicheloni.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://leomicheloni.blogspot.com/feeds/7701859600447346285/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=148524916779753368&amp;postID=7701859600447346285' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default/7701859600447346285'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default/7701859600447346285'/><link rel='alternate' type='text/html' href='http://leomicheloni.blogspot.com/2009/07/llamada-participacion-agiles2009-en.html' title='Llamada a participación Ágiles2009 en Brasil'/><author><name>Leonardo Micheloni</name><uri>http://www.blogger.com/profile/12085246040181097881</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='30' src='http://3.bp.blogspot.com/_t9Bh42Thfqo/S6TVOJqYWcI/AAAAAAAAANU/MlZc6HpYZis/S220/yo+laguito+en+col%C3%B3n.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-148524916779753368.post-5674234834846577838</id><published>2009-06-30T19:28:00.010-03:00</published><updated>2009-07-02T11:11:02.154-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='mock'/><category scheme='http://www.blogger.com/atom/ns#' term='MVC'/><category scheme='http://www.blogger.com/atom/ns#' term='JQuery'/><category scheme='http://www.blogger.com/atom/ns#' term='MUG'/><category scheme='http://www.blogger.com/atom/ns#' term='ASP.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='moq'/><title type='text'>Qué temas y con qué profundidad te gustaría ver en una capacitación?</title><content type='html'>&lt;a href="http://4.bp.blogspot.com/_t9Bh42Thfqo/SkqUw-fcy7I/AAAAAAAAAMI/wy2Z1npXTrM/s1600-h/net.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 160px; height: 152px;" src="http://4.bp.blogspot.com/_t9Bh42Thfqo/SkqUw-fcy7I/AAAAAAAAAMI/wy2Z1npXTrM/s320/net.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5353254676212796338" /&gt;&lt;/a&gt;
&lt;p&gt;Estoy delineando algunas ideas para una capacitación con máquina y todo en 2, 3 o 4 encuentros. La idea es ver algunos de los temas que fui presentando en el MUG pero aplicados a problemas reales y vinculados, como "en la vida real"&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Qué temas tratar?&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;La idea es ver:&lt;/p&gt;
&lt;ul&gt;
 &lt;li&gt;Delegados y esas cosas&lt;/li&gt;
 &lt;li&gt;Linq&lt;/li&gt;
 &lt;li&gt;Exmpresiones Lambda&lt;/li&gt;
 &lt;li&gt;Linq2Sql o Entity Framework&lt;/li&gt;
 &lt;li&gt;ASP.NET MVC&lt;/li&gt;
 &lt;li&gt;jQuery&lt;/li&gt;
 &lt;li&gt;IoC&lt;/li&gt;
 &lt;li&gt;Un poco de patrones&lt;/li&gt;
 &lt;li&gt;Mocking&lt;/li&gt;
 &lt;li&gt;TDD&lt;/li&gt;
 &lt;li&gt;Algunas herramientas como Fiddler, Visual Studio, nUnit, etc.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;La idea es recopilar adeptos para armar el curso e ir definiendo el temario para definir el tiempo y sobre todo el costo (si, van a tener que pagar para escucharme :P ) &lt;/p&gt;
&lt;p&gt;&lt;b&gt;Condiciones&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;El lugar será el MUG y el horario de 18:30 a 21:30 ya que me parece que pocos pueden (incluído yo) pedirse 3 o 4 días para algo así &lt;/p&gt;
&lt;p&gt;Bueno, tiro la piedra, espero sumar adeptos e idea y las iremos sumando para que sea una buena experiencia y que todos podamos aprender&lt;/p&gt;
&lt;strong&gt;UPDATE&lt;/strong&gt;
&lt;p&gt;Más o menos voy dando forma al temario, a ver qué les parece&lt;/p&gt;
&lt;p&gt;Desarrollo de una aplicacion Web con herramientas y prácticas actuales, en .NET, obvio.&lt;/p&gt;
&lt;p&gt;
-Conceptos básicos, para entender lo otro:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Delegados&lt;/li&gt;
&lt;li&gt;Eventos&lt;/li&gt;
&lt;li&gt;Reflector, la herramienta indispensable&lt;/li&gt;
&lt;li&gt;Extension methods&lt;/li&gt;
&lt;li&gt;Expresiones lambda&lt;/li&gt;
&lt;li&gt;Linq&lt;/li&gt;
&lt;li&gt;Refactor, mejorando el código&lt;/li&gt;
&lt;li&gt;Http, verbos, qué pasa en el cable?&lt;/li&gt;
&lt;li&gt;Html, css&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;-Comenzando con la aplicación web, de a poco:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Fiddler, firebug, IEDeveloper toolbar herramientas para tener a mano&lt;/li&gt;
&lt;li&gt;Asp.net MVC, por qué, qué ventajas tiene?&lt;/li&gt;
&lt;li&gt;jQuery para acelerar el desarrollo de javascript&lt;/li&gt;
&lt;li&gt;Ajax para hacer más interactiva las aplicaciones&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;-Mejorando el diseño:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Más de lo anterior&lt;/li&gt;
&lt;li&gt;Desacoplando las cosas&lt;/li&gt;
&lt;li&gt;Patrones para todos los días Repository, Factory, etc.&lt;/li&gt;
&lt;li&gt;IoC&lt;/li&gt;
&lt;li&gt;Inyección de dependencias&lt;/li&gt;
&lt;li&gt;ORM&lt;/li&gt;
&lt;li&gt;Linq2sql&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;-Testing:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Aumentando la calidad de nuestra aplicación&lt;/li&gt;
&lt;li&gt;Unit test&lt;/li&gt;
&lt;li&gt;Code coverage, qué tanto se ha probado?&lt;/li&gt;
&lt;li&gt;Mocking&lt;/li&gt;
&lt;li&gt;TDD&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Es una idea pero para ir definiendo cosas, sobretodo el objetivo, cómo vincular los conceptos de uso diario y actuales&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;Leonardo Micheloni&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/148524916779753368-5674234834846577838?l=leomicheloni.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://leomicheloni.blogspot.com/feeds/5674234834846577838/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=148524916779753368&amp;postID=5674234834846577838' title='10 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default/5674234834846577838'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default/5674234834846577838'/><link rel='alternate' type='text/html' href='http://leomicheloni.blogspot.com/2009/06/que-temas-y-con-que-profundidad-te.html' title='Qué temas y con qué profundidad te gustaría ver en una capacitación?'/><author><name>Leonardo Micheloni</name><uri>http://www.blogger.com/profile/12085246040181097881</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='30' src='http://3.bp.blogspot.com/_t9Bh42Thfqo/S6TVOJqYWcI/AAAAAAAAANU/MlZc6HpYZis/S220/yo+laguito+en+col%C3%B3n.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_t9Bh42Thfqo/SkqUw-fcy7I/AAAAAAAAAMI/wy2Z1npXTrM/s72-c/net.jpg' height='72' width='72'/><thr:total>10</thr:total></entry><entry><id>tag:blogger.com,1999:blog-148524916779753368.post-8552129189918233295</id><published>2009-06-24T23:09:00.003-03:00</published><updated>2009-06-24T23:12:49.848-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='JQuery'/><title type='text'>Cómo pasar elementos desde una lista a otra con javascript: con la ayuda de jQuery</title><content type='html'>&lt;strong&gt;Intercambio de items entre listas con jQuery&lt;/strong&gt;
    &lt;p&gt;Como digo siempre el verdadero poder de jQuery se encuentra en los selectores, si bien uno se entusiasma
    inicialmente con los efectos, animaciones, etc. con el tiempo uno se da cuenta que en el día a día jQuery y
    sus selectores son sus verdadres aliados, para demostrar esto vamos a ver un ejemplo sencillo de una tarea no tan simple&lt;/p&gt;
    &lt;p&gt;Seguramente les ha tocado tener que hacer la típica pantalla con dos listas, en la cual se pasan elementos de una a la otra.
    Se habrán encontrado con algunos problemas para localizar los elementos, verificar que cuando querramos pasar de una lista a la otra
    haya algo seleccionado, etc. He visto ejemplos de código bien pulidos con unas cuantas líneas de javascript y no tan claro pero que funcionan, 
    bueno, vamos a ver cómo se puede hacer esto con jQuery con 3 o 4 líneas gracias a los selectores&lt;/p&gt;
    &lt;p&gt;
    &lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
&lt;pre class="csharpcode"&gt;
&amp;lt;script language=&lt;span class="str"&gt;"javascript"&lt;/span&gt; type=&lt;span class="str"&gt;"text/javascript"&lt;/span&gt;&amp;gt;
$(function()
{
    $(&lt;span class="str"&gt;"#add"&lt;/span&gt;).click(function()
    {
        mover(&lt;span class="str"&gt;"origen"&lt;/span&gt;, &lt;span class="str"&gt;"destino"&lt;/span&gt;);
    }); 
    
    $(&lt;span class="str"&gt;"#remove"&lt;/span&gt;).click(function()
    {
        mover(&lt;span class="str"&gt;"destino"&lt;/span&gt;,&lt;span class="str"&gt;"origen"&lt;/span&gt;);
    });           
});

function mover(origen, destino)
{
    $(&lt;span class="str"&gt;"#"&lt;/span&gt; + origen + &lt;span class="str"&gt;" option:selected"&lt;/span&gt;).remove().appendTo(&lt;span class="str"&gt;"#"&lt;/span&gt; + destino);
}
&amp;lt;/script&amp;gt;
&lt;/pre&gt;
    &lt;/p&gt;
    
    &lt;p&gt;Y el HTML sería&lt;/p&gt;
    &lt;p&gt;&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
&lt;pre class="csharpcode"&gt;
&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;table&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;tr&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;td&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;select&lt;/span&gt; &lt;span class="attr"&gt;id&lt;/span&gt;&lt;span class="kwrd"&gt;="origen"&lt;/span&gt; &lt;span class="attr"&gt;multiple&lt;/span&gt;&lt;span class="kwrd"&gt;="multiple"&lt;/span&gt; &lt;span class="attr"&gt;size&lt;/span&gt;&lt;span class="kwrd"&gt;="5"&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;option&lt;/span&gt; &lt;span class="attr"&gt;value&lt;/span&gt;&lt;span class="kwrd"&gt;="1"&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;uno&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;option&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;option&lt;/span&gt; &lt;span class="attr"&gt;value&lt;/span&gt;&lt;span class="kwrd"&gt;="2"&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;dos&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;option&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;option&lt;/span&gt; &lt;span class="attr"&gt;value&lt;/span&gt;&lt;span class="kwrd"&gt;="3"&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;tres&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;option&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;option&lt;/span&gt; &lt;span class="attr"&gt;value&lt;/span&gt;&lt;span class="kwrd"&gt;="4"&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;cuatro&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;option&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;select&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;td&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;td&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;input&lt;/span&gt; &lt;span class="attr"&gt;type&lt;/span&gt;&lt;span class="kwrd"&gt;="button"&lt;/span&gt; &lt;span class="attr"&gt;id&lt;/span&gt;&lt;span class="kwrd"&gt;="add"&lt;/span&gt; &lt;span class="attr"&gt;value&lt;/span&gt;="&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;" &lt;span class="kwrd"&gt;/&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;br&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
            &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;input&lt;/span&gt; &lt;span class="attr"&gt;type&lt;/span&gt;&lt;span class="kwrd"&gt;="button"&lt;/span&gt; &lt;span class="attr"&gt;id&lt;/span&gt;&lt;span class="kwrd"&gt;="remove"&lt;/span&gt; &lt;span class="attr"&gt;value&lt;/span&gt;&lt;span class="kwrd"&gt;="&amp;lt;"&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;td&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;td&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;select&lt;/span&gt; &lt;span class="attr"&gt;id&lt;/span&gt;&lt;span class="kwrd"&gt;="destino"&lt;/span&gt; &lt;span class="attr"&gt;size&lt;/span&gt;&lt;span class="kwrd"&gt;="5"&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;option&lt;/span&gt; &lt;span class="attr"&gt;value&lt;/span&gt;&lt;span class="kwrd"&gt;="5"&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;cinco&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;option&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;select&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;td&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;tr&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;table&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/p&gt;

&lt;p&gt;Mágico, no sólo es sencillo, sino que podemos usar la función mover para mover elementos desde cualquier lista a otra con varios elementos seleccionados, incluso si fuera un combo y todo gracias a los selectores. Hasta la próxima&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;Leonardo Micheloni&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/148524916779753368-8552129189918233295?l=leomicheloni.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://leomicheloni.blogspot.com/feeds/8552129189918233295/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=148524916779753368&amp;postID=8552129189918233295' title='2 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default/8552129189918233295'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default/8552129189918233295'/><link rel='alternate' type='text/html' href='http://leomicheloni.blogspot.com/2009/06/como-pasar-elementos-desde-una-lista.html' title='Cómo pasar elementos desde una lista a otra con javascript: con la ayuda de jQuery'/><author><name>Leonardo Micheloni</name><uri>http://www.blogger.com/profile/12085246040181097881</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='30' src='http://3.bp.blogspot.com/_t9Bh42Thfqo/S6TVOJqYWcI/AAAAAAAAANU/MlZc6HpYZis/S220/yo+laguito+en+col%C3%B3n.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-148524916779753368.post-348565394170146996</id><published>2009-06-10T17:34:00.002-03:00</published><updated>2009-06-11T08:44:39.860-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='MVC'/><category scheme='http://www.blogger.com/atom/ns#' term='JQuery'/><category scheme='http://www.blogger.com/atom/ns#' term='ASP.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='json'/><title type='text'>Vinculando AJAX + ASP.NET MVC + jQuery</title><content type='html'>&lt;strong&gt;La forma fácil de bindear datos entre jQuery y ASP.NET MVC. DataBinders&lt;/strong&gt;
&lt;p&gt;Una de las ventajas de ASP.NET MVC es la capacidad de los DataBinders, que no son más que piezas de código 
que permiten relacionar la información que llega a una acción de un controlador con los parámetros del controlador,
 esto es, si desde una página llega un campo por POST con cierto nombre, etc cómo se convierte en un parámetro
 de la acción del controlador, a través de un DataBinder. Si bien podemos crear nuestros propios DataBinders de manera sencilla, con lo que viene por 
 defecto con ASP.NET MVC resuelve la mayoría de los problemas, tanto es así que esta pequeña pieza de códiigo va a intentar
 vincular los datos con los parámetros de una acción haciendo su mejor esfuerzo desligandonos de tal problema.&lt;/p&gt;
 &lt;p&gt;&lt;b&gt;Usando Objetos en los parámetros de las acciones&lt;/b&gt;&lt;/p&gt;
 &lt;p&gt;La gracia de usar objetos como parámetros de las acciones es mucha, es decir, si la acción recibe los datos de un formulario
 de alta de un usuario por qué no crear un tipo de datos &lt;i&gt;RegisterForm&lt;/i&gt; usarlo como parámetro y ver cómo hacemos para que nuestras
 páginas puedan "bindear" sus datos al parámetro. No, en principio no hay que escribir un DataBinder, porque podemos aprovechar la intereporabilidad 
 entre jQuery y ASP.NET MVC y no hacer absolutamente nada raro para que esto ocurra.&lt;/p&gt;
 &lt;p&gt;&lt;b&gt;Cómo hacer el binding automático si usamos AJAX con jQuery?&lt;/b&gt;&lt;/p&gt;
 &lt;p&gt;Esta es la parte divertida del asunto, imaginemos que tenemos un formulario con un panel para que usuario ingrese al sistema, pero 
 es una aplicación bien "ajaxificada" y el formulario envía los datos asincrónicamente y la respuesta llega del mismo modo, todo sin cambiar de página,&lt;/p&gt;
 
 &lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
&lt;pre class="csharpcode"&gt;
    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;div&lt;/span&gt; &lt;span class="attr"&gt;style&lt;/span&gt;&lt;span class="kwrd"&gt;="width: 180px"&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;form&lt;/span&gt; &lt;span class="attr"&gt;id&lt;/span&gt;&lt;span class="kwrd"&gt;="formulario"&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;fieldset&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;input&lt;/span&gt; &lt;span class="attr"&gt;type&lt;/span&gt;&lt;span class="kwrd"&gt;="text"&lt;/span&gt; &lt;span class="attr"&gt;id&lt;/span&gt;&lt;span class="kwrd"&gt;="NOMBRE"&lt;/span&gt; &lt;span class="attr"&gt;name&lt;/span&gt;&lt;span class="kwrd"&gt;="NOMBRE"&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;input&lt;/span&gt; &lt;span class="attr"&gt;type&lt;/span&gt;&lt;span class="kwrd"&gt;="text"&lt;/span&gt; &lt;span class="attr"&gt;id&lt;/span&gt;&lt;span class="kwrd"&gt;="APELLIDO"&lt;/span&gt; &lt;span class="attr"&gt;name&lt;/span&gt;&lt;span class="kwrd"&gt;="APELLIDO"&lt;/span&gt;&lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;input&lt;/span&gt; &lt;span class="attr"&gt;type&lt;/span&gt;&lt;span class="kwrd"&gt;="text"&lt;/span&gt; &lt;span class="attr"&gt;name&lt;/span&gt;&lt;span class="kwrd"&gt;="EDAD"&lt;/span&gt; &lt;span class="attr"&gt;id&lt;/span&gt;&lt;span class="kwrd"&gt;="EDAD"&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;input&lt;/span&gt; &lt;span class="attr"&gt;type&lt;/span&gt;&lt;span class="kwrd"&gt;="text"&lt;/span&gt; &lt;span class="attr"&gt;id&lt;/span&gt;&lt;span class="kwrd"&gt;="EMAIL"&lt;/span&gt; &lt;span class="attr"&gt;name&lt;/span&gt;&lt;span class="kwrd"&gt;="EMAIL"&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;br&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt; 
    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;input&lt;/span&gt; &lt;span class="attr"&gt;type&lt;/span&gt;&lt;span class="kwrd"&gt;="checkbox"&lt;/span&gt; &lt;span class="attr"&gt;id&lt;/span&gt;&lt;span class="kwrd"&gt;="TERMINOS"&lt;/span&gt; &lt;span class="attr"&gt;name&lt;/span&gt;&lt;span class="kwrd"&gt;="TERMINOS"&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;span&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;Aceptar términos&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;span&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;  &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;br&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt; 
    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;input&lt;/span&gt; &lt;span class="attr"&gt;type&lt;/span&gt;&lt;span class="kwrd"&gt;="button"&lt;/span&gt; &lt;span class="attr"&gt;id&lt;/span&gt;&lt;span class="kwrd"&gt;="enviar"&lt;/span&gt; &lt;span class="attr"&gt;value&lt;/span&gt;&lt;span class="kwrd"&gt;="Enviar"&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;fieldset&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;form&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;div&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;
    
    &lt;p&gt;Bien, este el es formulario, como vemos hay varios campos, entonces definamos una clase simplemente para mapear las propiedades de éste&lt;/p&gt;
    
    &lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
&lt;pre class="csharpcode"&gt;
&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; RegisterForm
{
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; Nombre { get; set; }
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; Apellido { get; set; }
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;int&lt;/span&gt; Edad { get; set; }
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; Email { get; set; }
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; Terminos { get; set; }

}&lt;/pre&gt;

&lt;p&gt;Perfecto, ahora hacemos una acción en nuestro controller para que tome los datos del formulario&lt;/p&gt;
&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
&lt;pre class="csharpcode"&gt;
&lt;span class="kwrd"&gt;public&lt;/span&gt; ActionResult BindingTest(RegisterForm registerForm)
{
    &lt;span class="kwrd"&gt;return&lt;/span&gt; Json(registerForm);
}&lt;/pre&gt;
&lt;p&gt;Esta acción siemplemente toma los datos y los devuelve en JSON como para verlos en el cliente nomás, a modo de prueba,
 la idea es por supuesto hacer algo con ellos, entonces, cómo hacemos para invocar con AJAX la acción y de paso que todos los datos 
 del formulario se "bindeen" o vinculen con el parámetro, así:&lt;/p&gt;
 &lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
&lt;pre class="csharpcode"&gt;
&amp;lt;script language=&lt;span class="str"&gt;"javascript"&lt;/span&gt; type=&lt;span class="str"&gt;"text/javascript"&lt;/span&gt;&amp;gt;
    $(function() {
        $(&lt;span class="str"&gt;"#enviar"&lt;/span&gt;).click(sendData);
    });
    
    function sendData() {
        $.get(&lt;span class="str"&gt;"/home/BindingTest/"&lt;/span&gt;, $(&lt;span class="str"&gt;"#formulario"&lt;/span&gt;).serialize(), function(data) {
            alert(data);
        });        
    }
&amp;lt;/script&amp;gt;&lt;/pre&gt;
&lt;p&gt;Estoy usando &lt;a href="http://jquery.com"&gt;jQuery&lt;/a&gt;, y como verán es un simple get con AJAX, el truco está en la función
serialize(), que seriliza el formulario, o sea, transforma el objeto y su estado de modo que se pueda transportar o guardar, en este caso
 como un querystring que es perfectamente comprensible por ASP.NET MVC y sobre todo por el ModelBinder por defecto, como resultado
  vemos lo que funciona de pelos, porque imprimimos la respuesta de la acción en un alert y comprobamos que el objeto se cargó y luego
  fue devuelto por la accion en formato JSON, mágico&lt;/p&gt;
&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_t9Bh42Thfqo/SjAZJSuTF7I/AAAAAAAAALU/x9YZCtcpEqQ/s1600-h/respuestaAJAX.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 92px;" src="http://3.bp.blogspot.com/_t9Bh42Thfqo/SjAZJSuTF7I/AAAAAAAAALU/x9YZCtcpEqQ/s320/respuestaAJAX.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5345800405124323250" /&gt;&lt;/a&gt;  &lt;p&gt;Hasta la próxima.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;Leonardo Micheloni&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/148524916779753368-348565394170146996?l=leomicheloni.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://leomicheloni.blogspot.com/feeds/348565394170146996/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=148524916779753368&amp;postID=348565394170146996' title='1 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default/348565394170146996'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default/348565394170146996'/><link rel='alternate' type='text/html' href='http://leomicheloni.blogspot.com/2009/06/vinculando-ajax-aspnet-mvc-jquery.html' title='Vinculando AJAX + ASP.NET MVC + jQuery'/><author><name>Leonardo Micheloni</name><uri>http://www.blogger.com/profile/12085246040181097881</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='30' src='http://3.bp.blogspot.com/_t9Bh42Thfqo/S6TVOJqYWcI/AAAAAAAAANU/MlZc6HpYZis/S220/yo+laguito+en+col%C3%B3n.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_t9Bh42Thfqo/SjAZJSuTF7I/AAAAAAAAALU/x9YZCtcpEqQ/s72-c/respuestaAJAX.png' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-148524916779753368.post-701377352557783134</id><published>2009-06-09T08:28:00.005-03:00</published><updated>2009-06-11T08:45:06.750-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='agiles2008'/><title type='text'>Ágiles 2009 en Brasil</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_t9Bh42Thfqo/Si5JgwY39aI/AAAAAAAAALM/w4dlWW8cri0/s1600-h/banner_esp.png"&gt;&lt;img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;width: 320px; height: 47px;" src="http://3.bp.blogspot.com/_t9Bh42Thfqo/Si5JgwY39aI/AAAAAAAAALM/w4dlWW8cri0/s320/banner_esp.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5345290634829231522" /&gt;&lt;/a&gt;&lt;br /&gt;



&lt;p&gt;Como continuidad de los que fue el éxito de &lt;a href="http://www.agiles2008.org"&gt;Ágiles 2008&lt;/a&gt; les cuento que la versión 2009 se va a realizar en el hermano país de Brasil, más específicamente en Florianópolis, pueden seguir el progreso de la organización desde &lt;a href="http://www.agiles2009.org"&gt;Acá&lt;/a&gt; y si tienen ganas colaborar :) , la fecha es octubre y ya confirmó &lt;a href="http://www.agiles2009.org/es/resume.php?id=brianMarick"&gt;Brian Marick&lt;/a&gt; uno de los firmantes del manifiesto ágil allá por el 2001, así que la invitación está hecha, les aseguro que voy a tratar de estar, no olviden que siempre se pueden consultar las novedades de la comunidad en &lt;a href="http://www.agiles.org"&gt;el sitio de ágiles&lt;/a&gt; y las actividades no son pocas por suerte. Saludos.&lt;div class="blogger-post-footer"&gt;Leonardo Micheloni&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/148524916779753368-701377352557783134?l=leomicheloni.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://leomicheloni.blogspot.com/feeds/701377352557783134/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=148524916779753368&amp;postID=701377352557783134' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default/701377352557783134'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default/701377352557783134'/><link rel='alternate' type='text/html' href='http://leomicheloni.blogspot.com/2009/06/agiles-2009-en-brasil.html' title='Ágiles 2009 en Brasil'/><author><name>Leonardo Micheloni</name><uri>http://www.blogger.com/profile/12085246040181097881</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='30' src='http://3.bp.blogspot.com/_t9Bh42Thfqo/S6TVOJqYWcI/AAAAAAAAANU/MlZc6HpYZis/S220/yo+laguito+en+col%C3%B3n.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_t9Bh42Thfqo/Si5JgwY39aI/AAAAAAAAALM/w4dlWW8cri0/s72-c/banner_esp.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-148524916779753368.post-2618048468634724511</id><published>2009-05-27T19:51:00.004-03:00</published><updated>2009-06-03T12:00:19.821-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='MVC'/><category scheme='http://www.blogger.com/atom/ns#' term='MUG'/><title type='text'>Charla MVC desde cero en el MUG DONE!!</title><content type='html'>&lt;p&gt;Ayer junto a mi secuaz de laburos freelance &lt;a href="http://www.wearequbit.net/"&gt;Rodrigo Obi-Wan Iloro&lt;/a&gt; tuvimos el agrado de dar una pequeña charla introductoria acerca de ASP.NET MVC en el &lt;a href="http://www.mug.org.ar"&gt;Microsoft User Group&lt;/a&gt;, una vez más tengo que agradecerles a todos los que concurrieron y a la gente del MUG por su buena onda&lt;/p&gt;
&lt;p&gt;Dejo la PPT que usamos ayer, voy a ir subiendo los ejemplos e intentar de explicar un poco junto con cada uno (remarco la palabra intentar, siempre prometo y no tengo tiempo después), así que enjoy.

&lt;a href="http://cid-c9e9afda80ba37c1.skydrive.live.com/self.aspx/.Public/Qu%c3%a9%20es%20MVC.rar"&gt;PPT ASP.NET MVC desde cero&lt;/a&gt;
&lt;br /&gt;
&lt;p&gt;&lt;strong&gt;UPDATE!!! &lt;a href="http://cid-c9e9afda80ba37c1.skydrive.live.com/self.aspx/.Public/MvcApplication2.rar"&gt;Código de ejemplo&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;Leonardo Micheloni&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/148524916779753368-2618048468634724511?l=leomicheloni.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://leomicheloni.blogspot.com/feeds/2618048468634724511/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=148524916779753368&amp;postID=2618048468634724511' title='2 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default/2618048468634724511'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default/2618048468634724511'/><link rel='alternate' type='text/html' href='http://leomicheloni.blogspot.com/2009/05/charla-mvc-desde-cero-en-el-mug-done.html' title='Charla MVC desde cero en el MUG DONE!!'/><author><name>Leonardo Micheloni</name><uri>http://www.blogger.com/profile/12085246040181097881</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='30' src='http://3.bp.blogspot.com/_t9Bh42Thfqo/S6TVOJqYWcI/AAAAAAAAANU/MlZc6HpYZis/S220/yo+laguito+en+col%C3%B3n.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-148524916779753368.post-8813758113097164882</id><published>2009-05-23T20:03:00.004-03:00</published><updated>2009-05-23T22:03:01.776-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='alt.net'/><title type='text'>Alt.Net Argetina 09 Fotos</title><content type='html'>&lt;p&gt;Con un poco de retraso pero aquí dejo el link a algunas fotos de Alt.Net Argentina versión 2009, la verdad es que fue muy bueno, intentaré dejar mis impresiones sobre las charlas en las que participé durante estas semanas&lt;/p&gt;

&lt;img src="http://farm4.static.flickr.com/3330/3518795574_eaab819e39.jpg" /&gt;
&lt;img src="http://farm4.static.flickr.com/3657/3518803452_088ffffcac.jpg" /&gt;
&lt;img src="http://farm4.static.flickr.com/3366/3518803472_0f057abf2e.jpg" /&gt;
&lt;img src="http://farm4.static.flickr.com/3312/3518803458_c2f37d1114.jpg" /&gt;
&lt;img src="http://farm4.static.flickr.com/3326/3518812428_228668129e.jpg" /&gt;



&lt;a href="http://www.flickr.com/photos/32140881@N04/sets/72157617858437849/"&gt;Álbun de todos Flickr&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;Leonardo Micheloni&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/148524916779753368-8813758113097164882?l=leomicheloni.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://leomicheloni.blogspot.com/feeds/8813758113097164882/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=148524916779753368&amp;postID=8813758113097164882' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default/8813758113097164882'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default/8813758113097164882'/><link rel='alternate' type='text/html' href='http://leomicheloni.blogspot.com/2009/05/altnet-argetina-09-fotos.html' title='Alt.Net Argetina 09 Fotos'/><author><name>Leonardo Micheloni</name><uri>http://www.blogger.com/profile/12085246040181097881</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='30' src='http://3.bp.blogspot.com/_t9Bh42Thfqo/S6TVOJqYWcI/AAAAAAAAANU/MlZc6HpYZis/S220/yo+laguito+en+col%C3%B3n.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://farm4.static.flickr.com/3330/3518795574_eaab819e39_t.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-148524916779753368.post-4849411943471296548</id><published>2009-05-20T10:31:00.001-03:00</published><updated>2009-05-20T10:33:26.399-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='c#'/><title type='text'>¿Cómo hacemos una interface fluyente o fluent interface?</title><content type='html'>&lt;p&gt;&lt;strong&gt;Cómo crear una fluent interface? o métodos que fluyen&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Este pequeño post viene a colación sobre una pregunta acerca de un estilo interesante de diseño de fremwork
las &lt;b&gt;Fluent interface&lt;/b&gt;, están por todos lados &lt;b&gt;jQuery&lt;/b&gt;, &lt;b&gt;Moq&lt;/b&gt;, &lt;b&gt;Rhino Mocks&lt;/b&gt;, por nombrar 
herramientas que nombré en este blog&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Qué es una Fluent Interface, o interface fluyente?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Sencillo, es cuando podemos hacer llamadas a un metodo e ir encadenando llamadas sucesivas, por ejemplo en jQuery&lt;/p&gt;
&lt;p&gt;$("div").draggable().resizable()&lt;/p&gt;
&lt;p&gt;Es decir, llamamos a un método y el mismo nos permite hacer llamadas sucesivas a otros métodos. Interesante, pero cómo se hace? bien vamos directamente al código autodescriptivo&lt;/p&gt;


&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
&lt;pre class="csharpcode"&gt;
&lt;span class="kwrd"&gt;class&lt;/span&gt; Program
{
    &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Main(&lt;span class="kwrd"&gt;string&lt;/span&gt;[] args)
    {
        var fluent = &lt;span class="kwrd"&gt;new&lt;/span&gt; Fluent();

        &lt;span class="rem"&gt;//Lamamos a la clase "fluyente" repetidamente para ir agregando mensajes&lt;/span&gt;
        &lt;span class="rem"&gt;//por defector Console.WriteLine llama al método ToString que sobre-escrimos&lt;/span&gt;
        Console.WriteLine(
            fluent.AddMessage(&lt;span class="str"&gt;"hola "&lt;/span&gt;).AddMessage(&lt;span class="str"&gt;" mundo"&lt;/span&gt;).AddMessage(&lt;span class="str"&gt;"que tal?"&lt;/span&gt;));

        Console.ReadLine();
    }
}

&lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;
&lt;span class="rem"&gt;/// Esta clase tiene algunos método "fluet" o sea, "flueyente", todo el truco&lt;/span&gt;
&lt;span class="rem"&gt;/// está en que dicos métodos devuelvan una referencia el mismo objeto&lt;/span&gt;
&lt;span class="rem"&gt;/// o sea this&lt;/span&gt;
&lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;
&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; Fluent
{
    StringBuilder _messageList = &lt;span class="kwrd"&gt;new&lt;/span&gt; StringBuilder();

    &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;
    &lt;span class="rem"&gt;/// Los métdos "fluyentes" devuelven un objeto del mismo tipo&lt;/span&gt;
    &lt;span class="rem"&gt;/// que la clase que los contiene, en definitiva, devuelven&lt;/span&gt;
    &lt;span class="rem"&gt;/// el mismo objeto con this&lt;/span&gt;
    &lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;
    &lt;span class="rem"&gt;/// &amp;lt;returns&amp;gt;El mismo objeto que contiene el método&amp;lt;/returns&amp;gt;&lt;/span&gt;
    &lt;span class="kwrd"&gt;public&lt;/span&gt; Fluent AddMessage(&lt;span class="kwrd"&gt;string&lt;/span&gt; message)
    {
        _messageList.AppendLine(message);
        &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;this&lt;/span&gt;;        
    }

    &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;
    &lt;span class="rem"&gt;/// Sobre-escribimos el ToString para ver el resultado&lt;/span&gt;
    &lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;
    &lt;span class="rem"&gt;/// &amp;lt;returns&amp;gt;&amp;lt;/returns&amp;gt;&lt;/span&gt;
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;override&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; ToString()
    {
        &lt;span class="kwrd"&gt;return&lt;/span&gt; _messageList.ToString();
    }
}
&lt;/pre&gt;

&lt;p&gt;
Lo ejecutamos y mágia! Hasta la próxima&lt;/p&gt;

&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_t9Bh42Thfqo/ShQGOa92vVI/AAAAAAAAAK8/JAedHBs0ARI/s1600-h/fluent.png"&gt;&lt;img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;width: 320px; height: 158px;" src="http://2.bp.blogspot.com/_t9Bh42Thfqo/ShQGOa92vVI/AAAAAAAAAK8/JAedHBs0ARI/s320/fluent.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5337898303167577426" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;Leonardo Micheloni&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/148524916779753368-4849411943471296548?l=leomicheloni.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://leomicheloni.blogspot.com/feeds/4849411943471296548/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=148524916779753368&amp;postID=4849411943471296548' title='4 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default/4849411943471296548'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default/4849411943471296548'/><link rel='alternate' type='text/html' href='http://leomicheloni.blogspot.com/2009/05/como-hacemos-una-interface-fluyente-o.html' title='¿Cómo hacemos una interface fluyente o fluent interface?'/><author><name>Leonardo Micheloni</name><uri>http://www.blogger.com/profile/12085246040181097881</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='30' src='http://3.bp.blogspot.com/_t9Bh42Thfqo/S6TVOJqYWcI/AAAAAAAAANU/MlZc6HpYZis/S220/yo+laguito+en+col%C3%B3n.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_t9Bh42Thfqo/ShQGOa92vVI/AAAAAAAAAK8/JAedHBs0ARI/s72-c/fluent.png' height='72' width='72'/><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-148524916779753368.post-2534813732520370975</id><published>2009-05-12T22:52:00.007-03:00</published><updated>2009-05-13T21:47:27.370-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='JQuery'/><category scheme='http://www.blogger.com/atom/ns#' term='MUG'/><category scheme='http://www.blogger.com/atom/ns#' term='json'/><title type='text'>Charla sobre jQuery en el MUG DONE - ppt</title><content type='html'>&lt;p&gt;Recién llego de la presentación sobre jQuery en el MUG, la verdad es que estuvo muy bueno, al menos yo la pase bien :) . Gracias a todos los asistentes y a la gente del MUG, dejo la presentación que usé esta noche, en estoy días voy a subir los ejemplos de código como prometí, de paso voy a agregar algunas cosas que surgieron, como databindings para los objetos dom y tabs con AJAX.&lt;/p&gt;
&lt;a href="http://cid-c9e9afda80ba37c1.skydrive.live.com/self.aspx/.Public/jQuery%7C_pptx.zip?ccr=6011"&gt;Bajar archivo presentación (Skydrive)&lt;/a&gt;
&lt;p&gt;&lt;strong&gt;UPDATE!!!&lt;/strong&gt;&lt;/p&gt;
&lt;a href="http://cid-c9e9afda80ba37c1.skydrive.live.com/self.aspx/.Public/EjemplosMUG.rar"&gt;Código de los ejemplos&lt;/a&gt;
&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;Leonardo Micheloni&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/148524916779753368-2534813732520370975?l=leomicheloni.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://leomicheloni.blogspot.com/feeds/2534813732520370975/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=148524916779753368&amp;postID=2534813732520370975' title='5 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default/2534813732520370975'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default/2534813732520370975'/><link rel='alternate' type='text/html' href='http://leomicheloni.blogspot.com/2009/05/charla-sobre-jquery-en-el-mug-done-ppt.html' title='Charla sobre jQuery en el MUG DONE - ppt'/><author><name>Leonardo Micheloni</name><uri>http://www.blogger.com/profile/12085246040181097881</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='30' src='http://3.bp.blogspot.com/_t9Bh42Thfqo/S6TVOJqYWcI/AAAAAAAAANU/MlZc6HpYZis/S220/yo+laguito+en+col%C3%B3n.jpg'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-148524916779753368.post-4502596773127695529</id><published>2009-04-24T11:47:00.003-03:00</published><updated>2009-04-24T11:59:46.887-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='MVC'/><category scheme='http://www.blogger.com/atom/ns#' term='JQuery'/><category scheme='http://www.blogger.com/atom/ns#' term='MUG'/><title type='text'>Charla sobre ASP.NET MVC en el MUG</title><content type='html'>&lt;img src="http://upload.wikimedia.org/wikipedia/commons/2/2e/ModelViewControllerDiagram.svg" /&gt;

&lt;strong&gt;Charla ASP.NET MVC en el MUG&lt;/strong&gt;
&lt;p&gt;Vamos a estar dando una charla introductoria a ASP.NET MVC en el &lt;a href="http://www.mug.org.ar"&gt;Microsoft User Group&lt;/a&gt; el día 26 de Mayo después del trabajdo, digo vamos porque me va a dar una mano Rodrigo Alias "Obi" un experto en la materia, la idea es ver un poco de teoría y aprovechar el marco del MUG para darle mucho al código y que la cosa sea lo más interactiva y enriquecedora posible para todos, no me queda otra que empezar a preparar el material así que trataré de ir subiendo cosas, no se olviden que el 9 del mayo (quince días antes) vamos a ver un poco de JQuery en otra charla del MUG, si el entusiasmo lo permite tenemos en mente armar algo más tipo capacitación con las dos cosas, así que están todos invitados, dejo el link&lt;/p&gt;

&lt;a href="http://www.mug.org.ar/Eventos/3278.aspx"&gt;ASP.NET MVC desde cero&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;Leonardo Micheloni&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/148524916779753368-4502596773127695529?l=leomicheloni.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://leomicheloni.blogspot.com/feeds/4502596773127695529/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=148524916779753368&amp;postID=4502596773127695529' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default/4502596773127695529'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default/4502596773127695529'/><link rel='alternate' type='text/html' href='http://leomicheloni.blogspot.com/2009/04/charla-sobre-aspnet-mvc-en-el-mug.html' title='Charla sobre ASP.NET MVC en el MUG'/><author><name>Leonardo Micheloni</name><uri>http://www.blogger.com/profile/12085246040181097881</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='30' src='http://3.bp.blogspot.com/_t9Bh42Thfqo/S6TVOJqYWcI/AAAAAAAAANU/MlZc6HpYZis/S220/yo+laguito+en+col%C3%B3n.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-148524916779753368.post-8139554141482669098</id><published>2009-04-03T15:10:00.004-03:00</published><updated>2009-04-03T15:21:29.594-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='JQuery'/><category scheme='http://www.blogger.com/atom/ns#' term='MUG'/><category scheme='http://www.blogger.com/atom/ns#' term='json'/><title type='text'>Charla sobre JQuery en el MUG</title><content type='html'>&lt;strong&gt;Charla sobre JQuery en el Microsoft User Grouop&lt;/strong&gt;&lt;br /&gt;
&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_t9Bh42Thfqo/SdZTUxNutdI/AAAAAAAAAK0/9nrgO51Ozmc/s1600-h/logo_jquery_215x53.gif"&gt;&lt;img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;width: 215px; height: 53px;" src="http://2.bp.blogspot.com/_t9Bh42Thfqo/SdZTUxNutdI/AAAAAAAAAK0/9nrgO51Ozmc/s320/logo_jquery_215x53.gif" border="0" alt=""id="BLOGGER_PHOTO_ID_5320531626058233298" /&gt;&lt;/a&gt;&lt;br /&gt;
&lt;p&gt;Una vez más tengo que agradecer a la gente del MUG la posiblidad de estar en las instalaciones de la calle Rivadavia con una charla, en este caso sobre &lt;a href="http://jquery.com/"&gt;JQuery&lt;/a&gt; el framework de Javascript del que todos hablan (no sé si es así pero queda bien). La idea es ir viendo de a poco cómo se utiliza y qué tipo de cosas podemos resolver facilmente con su ayuda a través de ejemplos de código, como me gusta a mí :P . Así que los invito a participar, vamos a ver cómo hacer selecciones, manipulaciones de elementos, animaciones, Ajax, invocación de Web Services, todo desde Javascript muy fácil gracias a JQuery, les dejo el link para que se anoten y apurensé que todos mis familiares se van a anotar para hacer bulto.&lt;/p&gt;

&lt;a href="http://www.mug.org.ar/Eventos/3256.aspx"&gt;JQuery la respuesta para el desarrollo de aplicaciones web ricas con Javascript y Ajax&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;Leonardo Micheloni&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/148524916779753368-8139554141482669098?l=leomicheloni.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://leomicheloni.blogspot.com/feeds/8139554141482669098/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=148524916779753368&amp;postID=8139554141482669098' title='5 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default/8139554141482669098'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default/8139554141482669098'/><link rel='alternate' type='text/html' href='http://leomicheloni.blogspot.com/2009/04/charla-sobre-jquery-en-el-mug.html' title='Charla sobre JQuery en el MUG'/><author><name>Leonardo Micheloni</name><uri>http://www.blogger.com/profile/12085246040181097881</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='30' src='http://3.bp.blogspot.com/_t9Bh42Thfqo/S6TVOJqYWcI/AAAAAAAAANU/MlZc6HpYZis/S220/yo+laguito+en+col%C3%B3n.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_t9Bh42Thfqo/SdZTUxNutdI/AAAAAAAAAK0/9nrgO51Ozmc/s72-c/logo_jquery_215x53.gif' height='72' width='72'/><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-148524916779753368.post-7079588585679297566</id><published>2009-03-20T11:28:00.004-03:00</published><updated>2009-03-20T11:33:48.206-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='alt.net'/><title type='text'>Alt.Net En Argentina y LA</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_t9Bh42Thfqo/ScOo13gS2YI/AAAAAAAAAKs/JEQEo3LbWpQ/s1600-h/altdotnet%5B3%5D.png"&gt;&lt;img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;width: 150px; height: 58px;" src="http://3.bp.blogspot.com/_t9Bh42Thfqo/ScOo13gS2YI/AAAAAAAAAKs/JEQEo3LbWpQ/s320/altdotnet%5B3%5D.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5315277628613253506" /&gt;&lt;/a&gt;
&lt;p&gt;&lt;/p&gt;&lt;p&gt;Hace unas horas ha nacido la versión regional de &lt;a href="http://altnetconf.com/"&gt;Alt.Net&lt;/a&gt; y se ha creado &lt;a href="http://groups.google.com/group/altnet-argentina"&gt;un grupo&lt;/a&gt; (muy a mi pesar en googlegroups) para la organización y demás menesteres, así que a participar.&lt;div class="blogger-post-footer"&gt;Leonardo Micheloni&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/148524916779753368-7079588585679297566?l=leomicheloni.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://leomicheloni.blogspot.com/feeds/7079588585679297566/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=148524916779753368&amp;postID=7079588585679297566' title='7 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default/7079588585679297566'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default/7079588585679297566'/><link rel='alternate' type='text/html' href='http://leomicheloni.blogspot.com/2009/03/altnet-en-argentina-y-la.html' title='Alt.Net En Argentina y LA'/><author><name>Leonardo Micheloni</name><uri>http://www.blogger.com/profile/12085246040181097881</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='30' src='http://3.bp.blogspot.com/_t9Bh42Thfqo/S6TVOJqYWcI/AAAAAAAAANU/MlZc6HpYZis/S220/yo+laguito+en+col%C3%B3n.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_t9Bh42Thfqo/ScOo13gS2YI/AAAAAAAAAKs/JEQEo3LbWpQ/s72-c/altdotnet%5B3%5D.png' height='72' width='72'/><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-148524916779753368.post-6660199868101267189</id><published>2009-03-18T14:51:00.001-03:00</published><updated>2009-03-18T14:52:14.302-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Generics'/><category scheme='http://www.blogger.com/atom/ns#' term='c#'/><title type='text'>Predicado con parámetros o cómo poder pasar un parámetro al método Find de List</title><content type='html'>&lt;strong&gt;Predicados con parámetros&lt;/strong&gt;
&lt;p&gt;Una vez más un post que surge de una consulta cotidiana, un predicado es un tipo de delegado, o sea una firma de un método, en el caso del predicado genérico (que es el que nos interesa)
la firma es la siguiente
&lt;/p&gt;
&lt;p&gt;public delegate bool Predicate&amp;lt;T&amp;gt;(T obj);&lt;/p&gt;
&lt;p&gt;Entonces, lo que esto nos dice es que representamos un método que recibe T como parámetro y devuelve true o false, el objetivo de un predicado
es que ese valor de retorno responda a una condición que nosotros consideramos verdadera, por ejemplo T fuese un tipo persona podriamos decir que 
será true el valor de retorno cuando su edad sea mayor de dieciocho años, para ser claro, un método que responda a esa regla y represente un predicado sería así:&lt;/p&gt;

&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
&lt;pre class="csharpcode"&gt;
&lt;span class="kwrd"&gt;private&lt;/span&gt; Predicate&amp;lt;Persona&amp;gt; PredicadoConParametro(&lt;span class="kwrd"&gt;string&lt;/span&gt; param)
{
    &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;new&lt;/span&gt; Predicate&amp;lt;Persona&amp;gt;(&lt;span class="kwrd"&gt;delegate&lt;/span&gt;(Persona target)
    {
        &lt;span class="kwrd"&gt;return&lt;/span&gt; target.Edad &amp;gt; 18;
    });
}
&lt;/pre&gt;
&lt;p&gt;
La duda es, si quiero que ese valor (18) sea parametrizable tengo que poner el predicado in-line para que "vea" el valor, así:
&lt;/p&gt;
&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
&lt;pre class="csharpcode"&gt;
&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; PredicadoInLine()
{
    List&amp;lt;Persona&amp;gt; personas = &lt;span class="kwrd"&gt;new&lt;/span&gt; List&amp;lt;Persona&amp;gt;()
    {
        &lt;span class="kwrd"&gt;new&lt;/span&gt; Persona{Nombre = &lt;span class="str"&gt;"Enzo"&lt;/span&gt;, Edad=36}, &lt;span class="kwrd"&gt;new&lt;/span&gt; Persona{Nombre = &lt;span class="str"&gt;"Ariel"&lt;/span&gt;, Edad=30}
    };

    &lt;span class="kwrd"&gt;int&lt;/span&gt; edad = 18;

    personas.Find(&lt;span class="kwrd"&gt;delegate&lt;/span&gt;(Persona target)
    {
        &lt;span class="kwrd"&gt;return&lt;/span&gt; target.Edad &amp;gt; edad;
    });
}      
&lt;/pre&gt;
&lt;p&gt;Es claro que el problema es que si queremos tener el código del predicado en otro lado por los motivos que sea y necesitamos pasar un parámetro 
(en este caso la edad) no hay forma (con una variable global se puede..) entonces la solución sería poder tener un predicado con parámetros, bien, cómo se resuelve esto? 
vamos a analizar un poco&lt;/p&gt;
&lt;p&gt;Lo que nos pide el mètodo Find es un predicado, nada nos impide poner un método que retorne un predicado, y a ese método pasarme un parámetro, en nuestro
caso la solución sería así:&lt;/p&gt;
&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
&lt;pre class="csharpcode"&gt;
&lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;
&lt;span class="rem"&gt;/// Este método acepta un parámetro edad y devuelve un predicado, es lo que necesitamos &lt;/span&gt;
&lt;span class="rem"&gt;/// para pasar al método Find de la lista&lt;/span&gt;
&lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;
&lt;span class="kwrd"&gt;private&lt;/span&gt; Predicate&amp;lt;Persona&amp;gt; PredicadoConParametro(&lt;span class="kwrd"&gt;int&lt;/span&gt; edad)
{
    &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;new&lt;/span&gt; Predicate&amp;lt;Persona&amp;gt;(&lt;span class="kwrd"&gt;delegate&lt;/span&gt;(Persona target)
    {
        &lt;span class="kwrd"&gt;return&lt;/span&gt; target.Edad &amp;gt; edad;
    });
}

&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Probar()
{
    &lt;span class="rem"&gt;//declaramos la lista con dos elementos&lt;/span&gt;
    List&amp;lt;Persona&amp;gt; personas = &lt;span class="kwrd"&gt;new&lt;/span&gt; List&amp;lt;Persona&amp;gt;()
    {
        &lt;span class="kwrd"&gt;new&lt;/span&gt; Persona{Nombre = &lt;span class="str"&gt;"Enzo"&lt;/span&gt;, Edad=36}, &lt;span class="kwrd"&gt;new&lt;/span&gt; Persona{Nombre = &lt;span class="str"&gt;"Carlos"&lt;/span&gt;, Edad=10}
    };

    &lt;span class="rem"&gt;//Verificamos que llamando al método Find de la lista utilizando nuestro predicado parametrizado nos&lt;/span&gt;
    &lt;span class="rem"&gt;//devuelva un elemento al menos&lt;/span&gt;
    Debug.Assert(personas.Find(PredicadoConParametro(18)) != &lt;span class="kwrd"&gt;null&lt;/span&gt;);
}&lt;/pre&gt;
&lt;p&gt;El método PerdicadoConParametro acepta un parámetro edad y devuelve un predicado 
    que tiene en cuena esa edad, con lo cual cubrimos nuestro requerimiento. Mágico, hasta la próxima&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;Leonardo Micheloni&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/148524916779753368-6660199868101267189?l=leomicheloni.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://leomicheloni.blogspot.com/feeds/6660199868101267189/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=148524916779753368&amp;postID=6660199868101267189' title='2 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default/6660199868101267189'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default/6660199868101267189'/><link rel='alternate' type='text/html' href='http://leomicheloni.blogspot.com/2009/03/predicado-con-parametros-o-como-poder.html' title='Predicado con parámetros o cómo poder pasar un parámetro al método Find de List&lt;T&gt;'/><author><name>Leonardo Micheloni</name><uri>http://www.blogger.com/profile/12085246040181097881</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='30' src='http://3.bp.blogspot.com/_t9Bh42Thfqo/S6TVOJqYWcI/AAAAAAAAANU/MlZc6HpYZis/S220/yo+laguito+en+col%C3%B3n.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-148524916779753368.post-4052501210353164249</id><published>2009-03-18T11:08:00.007-03:00</published><updated>2009-03-18T12:06:01.211-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='agiles2008'/><category scheme='http://www.blogger.com/atom/ns#' term='desarrollo ágil'/><title type='text'>La comunidad ágil hispanoparlante y su crecimiento</title><content type='html'>&lt;p&gt;
Como parte de toda este increible crecimiento que se está dando en la comunidad ágil de Argentina y acompañado con el resto de latam impulsado por las &lt;a href="http://www.agiles2008.org"&gt;Primeras Jornadas ágiles de Latinoamérica&lt;/a&gt;, las reuiones mensuales, el muy exitoso &lt;a href="http://sites.google.com/site/comunidadagiles/agile-open-buenos-aires-2009"&gt;Open Space de este més&lt;/a&gt;, y por supuesto el &lt;a href="http://sites.google.com/site/comunidadagiles/"&gt;sitio de la comunidad&lt;/a&gt; ahora se suma el nuevo nombre de la lista de correo de LAASD que a partir de ahora como forma de centrar todos los mensajes de todos los paises de habla hispana cuya dirección es &lt;a href="foro-agiles@yahoogroups.com"&gt;foro-agiles@yahoogroups.com&lt;/a&gt;, así que anotensé y hagamos cada vez más grande nuestra comunidad, la versión para Argentina es &lt;a href="http://tech.groups.yahoo.com/group/agiles-argentina"&gt;link&lt;/a&gt;. Saludos.
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;Leonardo Micheloni&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/148524916779753368-4052501210353164249?l=leomicheloni.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://leomicheloni.blogspot.com/feeds/4052501210353164249/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=148524916779753368&amp;postID=4052501210353164249' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default/4052501210353164249'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default/4052501210353164249'/><link rel='alternate' type='text/html' href='http://leomicheloni.blogspot.com/2009/03/la-comunidad-agil-hispanoparlante-y-su.html' title='La comunidad ágil hispanoparlante y su crecimiento'/><author><name>Leonardo Micheloni</name><uri>http://www.blogger.com/profile/12085246040181097881</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='30' src='http://3.bp.blogspot.com/_t9Bh42Thfqo/S6TVOJqYWcI/AAAAAAAAANU/MlZc6HpYZis/S220/yo+laguito+en+col%C3%B3n.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-148524916779753368.post-8888160084369762399</id><published>2009-01-28T12:01:00.001-02:00</published><updated>2009-01-28T16:09:20.038-02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='desarrollo ágil'/><title type='text'>Agile Open en Baires 09</title><content type='html'>&lt;strong&gt;Open Space en Buenos Aires, Universidad de 3 de Febrero.&lt;/strong&gt;
&lt;p&gt;El próximo 6 y 7 de Marzo en la Sede &lt;a href="http://www.ccborges.org.ar/"&gt;Centro Cultural Borges&lt;/a&gt; de la &lt;a href="http://www.untref.edu.ar/sedes.htm"&gt;Universidad de 3 de Febero&lt;/a&gt;
se realizará un &lt;a href="http://www.agiles.org/agile-open-buenos-aires-2009"&gt;Open Space
    &lt;/a&gt;para 100 personas con entrada libre y gratuita organizado por la &lt;a href="http://www.agiles.org/"&gt;
        comunidad agiles.org&lt;/a&gt;.
Creo que va a ser una experiencia muy buena para todos y muy interesante, el tema a tratar "Implementando desarrollo ágil", nos vemos allá.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;Leonardo Micheloni&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/148524916779753368-8888160084369762399?l=leomicheloni.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://leomicheloni.blogspot.com/feeds/8888160084369762399/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=148524916779753368&amp;postID=8888160084369762399' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default/8888160084369762399'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default/8888160084369762399'/><link rel='alternate' type='text/html' href='http://leomicheloni.blogspot.com/2009/01/agile-open-en-baires-09.html' title='Agile Open en Baires 09'/><author><name>Leonardo Micheloni</name><uri>http://www.blogger.com/profile/12085246040181097881</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='30' src='http://3.bp.blogspot.com/_t9Bh42Thfqo/S6TVOJqYWcI/AAAAAAAAANU/MlZc6HpYZis/S220/yo+laguito+en+col%C3%B3n.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-148524916779753368.post-7034498326226412676</id><published>2008-11-18T22:43:00.007-02:00</published><updated>2008-11-24T19:10:55.922-02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='mock'/><category scheme='http://www.blogger.com/atom/ns#' term='MUG'/><category scheme='http://www.blogger.com/atom/ns#' term='rhino'/><category scheme='http://www.blogger.com/atom/ns#' term='moq'/><category scheme='http://www.blogger.com/atom/ns#' term='unit test'/><title type='text'>Charla sobre mocking en el MUG, Done!!</title><content type='html'>&lt;p&gt;Hoy tuve la suerte de poder dar una charla sobre mocking en el &lt;a href="http://www.mug.org.ar"&gt;Grupo de Usuarios de Microsoft de Argentina&lt;/a&gt;,  hablamos de los objetivos del mocking, de &lt;a href="http://www.ayende.com"&gt;Rhino Mocks&lt;/a&gt; y &lt;a href="http://code.google.com/p/moq"&gt;Moq&lt;/a&gt; sin olvidar hacer referencia de &lt;a href="http://www.nmock.org" &gt;NMock&lt;/a&gt; y &lt;a href="http://www.typemock.com"&gt;TypeMock&lt;/a&gt;. &lt;/p&gt;
&lt;p&gt;Agradezco a los asistentes, al MUG, y a Daniel Laco por todo.&lt;/p&gt;
&lt;p&gt;Dejo los ejemplos para descargar&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="http://www.mediafire.com/?ntyzn12yhxm"&gt;Ejemplos para Visual Studio 2008 Team System&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="http://www.mediafire.com/?fjqntyjqnub"&gt;PPT en formato 2003&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;Leonardo Micheloni&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/148524916779753368-7034498326226412676?l=leomicheloni.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://leomicheloni.blogspot.com/feeds/7034498326226412676/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=148524916779753368&amp;postID=7034498326226412676' title='2 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default/7034498326226412676'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default/7034498326226412676'/><link rel='alternate' type='text/html' href='http://leomicheloni.blogspot.com/2008/11/charla-sobre-mocking-en-el-mug-done.html' title='Charla sobre mocking en el MUG, Done!!'/><author><name>Leonardo Micheloni</name><uri>http://www.blogger.com/profile/12085246040181097881</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='30' src='http://3.bp.blogspot.com/_t9Bh42Thfqo/S6TVOJqYWcI/AAAAAAAAANU/MlZc6HpYZis/S220/yo+laguito+en+col%C3%B3n.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-148524916779753368.post-2466168973070250619</id><published>2008-11-03T20:27:00.000-02:00</published><updated>2008-11-03T20:28:22.466-02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='mock'/><category scheme='http://www.blogger.com/atom/ns#' term='moq'/><category scheme='http://www.blogger.com/atom/ns#' term='unit test'/><title type='text'>¿Cómo verificar el orden de las llamadas a métodos con Moq?</title><content type='html'>&lt;p&gt;
            &lt;b&gt;¿Cómo verificar el orden de las llamadas a métodos con Moq 2.6?&lt;/b&gt;&lt;/p&gt;
        &lt;p&gt;
            En algunas ocasiones necesitamos verificar en qué orden son llamados métodos que 
            hemos &amp;quot;mockeado&amp;quot; una vez más vemos que nuestro querido Moq no tiene una 
            posibilidad para hacerlo como si la tiene Rhino, pero por supuesto, todo se 
            puede solucionar de la mano de los Callbacks, de esta manera:&lt;/p&gt;
&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
        &lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;interface&lt;/span&gt; IFoo
{
    &lt;span class="kwrd"&gt;void&lt;/span&gt; Method1();
    &lt;span class="kwrd"&gt;void&lt;/span&gt; Method2();
    &lt;span class="kwrd"&gt;void&lt;/span&gt; Method3();
}

&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; Sequencer
{
    Posicion contador;

    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;enum&lt;/span&gt; Posicion
    {
        Primero = 1,
        Segundo = 2,
        Tercero = 3,
        Cuarto = 4
    }

    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Seq(Posicion place)
    {
        &lt;span class="kwrd"&gt;if&lt;/span&gt; (++contador != place)
            &lt;span class="kwrd"&gt;throw&lt;/span&gt; &lt;span class="kwrd"&gt;new&lt;/span&gt; InvalidOperationException(
                &lt;span class="kwrd"&gt;string&lt;/span&gt;.Format(&lt;span class="str"&gt;&amp;quot;El método ha sido llamado {0} pero debería ser llamado {1}&amp;quot;&lt;/span&gt;, contador,place));
    }        
}

[TestMethod]
&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; VerificarOrdenDeLlamadas()
{
    var mock = &lt;span class="kwrd"&gt;new&lt;/span&gt; Mock&amp;lt;IFoo&amp;gt;();
    var seq = &lt;span class="kwrd"&gt;new&lt;/span&gt; Sequencer();

    mock.Expect(p =&amp;gt; p.Method1()).Callback(() =&amp;gt; seq.Seq(Sequencer.Posicion.Primero));
    mock.Expect(p =&amp;gt; p.Method2()).Callback(() =&amp;gt; seq.Seq(Sequencer.Posicion.Segundo));
    mock.Expect(p =&amp;gt; p.Method3()).Callback(() =&amp;gt; seq.Seq(Sequencer.Posicion.Tercero));

    mock.Object.Method2();

    mock.Object.Method1();

    mock.Object.Method3();

}&lt;/pre&gt;
        &lt;p&gt;
            Simple, hasta la próxima.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;Leonardo Micheloni&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/148524916779753368-2466168973070250619?l=leomicheloni.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://leomicheloni.blogspot.com/feeds/2466168973070250619/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=148524916779753368&amp;postID=2466168973070250619' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default/2466168973070250619'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default/2466168973070250619'/><link rel='alternate' type='text/html' href='http://leomicheloni.blogspot.com/2008/11/cmo-verificar-el-orden-de-las-llamadas.html' title='¿Cómo verificar el orden de las llamadas a métodos con Moq?'/><author><name>Leonardo Micheloni</name><uri>http://www.blogger.com/profile/12085246040181097881</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='30' src='http://3.bp.blogspot.com/_t9Bh42Thfqo/S6TVOJqYWcI/AAAAAAAAANU/MlZc6HpYZis/S220/yo+laguito+en+col%C3%B3n.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-148524916779753368.post-968915174657653558</id><published>2008-10-24T17:11:00.002-02:00</published><updated>2008-10-24T17:14:45.227-02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='agiles2008'/><title type='text'>Ágiles 2008, una utopía hecha realidad</title><content type='html'>&lt;p&gt;
        Bueno, han finalizado las &lt;a href="http://www.agiles2008.org"&gt;primeras jornadas 
        latinoamericanas sobre metodologías ágiles&lt;/a&gt;, de las cuales tuve el hornor de 
        participar en la organización. Fueron diez meses desde el puntapié inicial
        &lt;a href="http://tech.groups.yahoo.com/group/laasd/message/377"&gt;en la lista de 
        laass&lt;/a&gt;, luego de muchos desalientos, tropezones y otras yerbas, finalizaron 
        ayer con el salón Bolivar del hotel Bauen a pleno para ver un panel de cierre de 
        lujo formado por Mary y Tom Poppendieck, Tobiar Mayer, Matt Gelbwaks, Dave 
        Nicolette y Micah Martin, esto lo tenemos filmado y vamos a ver cómo hacemos 
        para subirlo.&lt;/p&gt;
    &lt;p&gt;
&amp;nbsp;Unas últimas palabras de
        &lt;a href="http://blog.salias.com.ar/2008/10/agiles-2008-la-emocin-de-que-las-cosas.html"&gt;
        Martín Salías&lt;/a&gt; para emocionarnos a todos que son un poco el resumen de los 
        que pasó, no puedo agregar nada a lo que dijo Martín, un gran agradecimiento a 
        todas las personas que fueron y a todos los organizadores, creo que todos nos 
        llevamos una experiencia única y momento que van a quedar grabados para siempre, 
        como la foto final de todo el equipo que demuestra que las personas son lo más 
        importante, tuve la oportunidad de interactuar la mayoría y no tengo más que 
        elogíos para todos por su entrega y su calidez personal, gracias chicas y chicos 
        y veremos qué pasa el año próximo.&lt;/p&gt;
&lt;a href="http://3.bp.blogspot.com/_t9Bh42Thfqo/SQIeS-0TBwI/AAAAAAAAAHg/WmEh6AiqPQg/s1600-h/Cierre%5B4%5D.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 213px;" src="http://3.bp.blogspot.com/_t9Bh42Thfqo/SQIeS-0TBwI/AAAAAAAAAHg/WmEh6AiqPQg/s320/Cierre%5B4%5D.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5260800626170988290" /&gt;&lt;/a&gt;        &lt;p&gt;Foto del salón bolivar durante el panel de cierre (cortesía del blog de Martín)&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;Leonardo Micheloni&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/148524916779753368-968915174657653558?l=leomicheloni.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://leomicheloni.blogspot.com/feeds/968915174657653558/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=148524916779753368&amp;postID=968915174657653558' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default/968915174657653558'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default/968915174657653558'/><link rel='alternate' type='text/html' href='http://leomicheloni.blogspot.com/2008/10/giles-2008-una-utopa-hecha-realidad.html' title='Ágiles 2008, una utopía hecha realidad'/><author><name>Leonardo Micheloni</name><uri>http://www.blogger.com/profile/12085246040181097881</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='30' src='http://3.bp.blogspot.com/_t9Bh42Thfqo/S6TVOJqYWcI/AAAAAAAAANU/MlZc6HpYZis/S220/yo+laguito+en+col%C3%B3n.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_t9Bh42Thfqo/SQIeS-0TBwI/AAAAAAAAAHg/WmEh6AiqPQg/s72-c/Cierre%5B4%5D.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-148524916779753368.post-5588959319475416700</id><published>2008-10-16T18:15:00.005-03:00</published><updated>2008-10-17T10:15:00.825-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='application block'/><category scheme='http://www.blogger.com/atom/ns#' term='EntLib'/><title type='text'>[VIDEO] Intro rápida a Data Access Application Block de Enterprise Library 3.1</title><content type='html'>&lt;p&gt;Les dejo un video muy breve sobre &lt;a href="http://www.codeplex.com/entlib"&gt;Data Access Application Block&lt;/a&gt;, saludos&lt;/p&gt;
&lt;a href="http://w14.easy-share.com/1702022690.html"&gt;Introducción a DAAB&lt;/a&gt;&lt;br /&gt;
&lt;a href="http://rapidshare.com/files/154880857/DAAB.rar.html" &gt;El mismo video en rapidshare&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;Leonardo Micheloni&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/148524916779753368-5588959319475416700?l=leomicheloni.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://leomicheloni.blogspot.com/feeds/5588959319475416700/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=148524916779753368&amp;postID=5588959319475416700' title='2 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default/5588959319475416700'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default/5588959319475416700'/><link rel='alternate' type='text/html' href='http://leomicheloni.blogspot.com/2008/10/video-intro-rpida-data-access.html' title='[VIDEO] Intro rápida a Data Access Application Block de Enterprise Library 3.1'/><author><name>Leonardo Micheloni</name><uri>http://www.blogger.com/profile/12085246040181097881</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='30' src='http://3.bp.blogspot.com/_t9Bh42Thfqo/S6TVOJqYWcI/AAAAAAAAANU/MlZc6HpYZis/S220/yo+laguito+en+col%C3%B3n.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-148524916779753368.post-6319887821806062606</id><published>2008-10-14T11:04:00.003-03:00</published><updated>2008-11-12T20:08:12.754-02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='mock'/><category scheme='http://www.blogger.com/atom/ns#' term='C# 3.0'/><category scheme='http://www.blogger.com/atom/ns#' term='moq'/><category scheme='http://www.blogger.com/atom/ns#' term='unit test'/><title type='text'>Moq 2.6: Mocks recursivos</title><content type='html'>&lt;p&gt;
            &lt;b&gt;Automocking con Moq&lt;/b&gt;&lt;/p&gt;
        &lt;p&gt;
            Una de las novedades de la versión 2.6 de nuestro framework de mocking preferido             &lt;a href="http://code.google.com/p/moq/"&gt;Moq&lt;/a&gt; es al &lt;i&gt;automocking&lt;/i&gt;  que no 
            es otra cosa más que un mockign jerárquico, es decir si &amp;quot;mockeamos&amp;quot; un objeto 
            (interface o lo que sea) y este tiene dentro otros objetos también se hace 
            mocking de estos y podemos configurar un resultado o comportamiento de 
            cualquiera de ellos, lo cual es muy práctico, veamos cómo funciona.&lt;/p&gt;
&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
        &lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;interface&lt;/span&gt; IPersona
{
    &lt;span class="kwrd"&gt;string&lt;/span&gt; Nombre { get; set; }
    &lt;span class="rem"&gt;//La propiedad Direccion es otro objeto&lt;/span&gt;
    IDireccion Direccion { get; set; }
}

&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;interface&lt;/span&gt; IDireccion
{
    &lt;span class="kwrd"&gt;string&lt;/span&gt; Calle { get; set; }
    &lt;span class="kwrd"&gt;int&lt;/span&gt; Altura { get; set; }
}

[TestMethod]
&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; AutoMocking()
{
    var mock = &lt;span class="kwrd"&gt;new&lt;/span&gt; Mock&amp;lt;IPersona&amp;gt;();

    &lt;span class="rem"&gt;//automáticamente se crea un mock object para la propiedad Dirección de modo lazy&lt;/span&gt;
    mock.Expect(persona =&amp;gt; persona.Direccion.Calle).Returns(&lt;span class="str"&gt;&amp;quot;Cucha Cucha&amp;quot;&lt;/span&gt;);

    Assert.AreEqual&amp;lt;&lt;span class="kwrd"&gt;string&lt;/span&gt;&amp;gt;(&lt;span class="str"&gt;&amp;quot;Cucha Cucha&amp;quot;&lt;/span&gt;, mock.Object.Direccion.Calle);
}&lt;/pre&gt;
        &lt;p&gt;
            No nos asustemos pensado que esto va a hacer que el automocking tome 40 segundos 
            en crear un objeto hasta que resuelve todos los objetos que tiene dentro, la 
            creación de los automocking es del tipo lazy, es decir, se crea sobre demanda, 
            mágico. Saludos.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;Leonardo Micheloni&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/148524916779753368-6319887821806062606?l=leomicheloni.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://leomicheloni.blogspot.com/feeds/6319887821806062606/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=148524916779753368&amp;postID=6319887821806062606' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default/6319887821806062606'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default/6319887821806062606'/><link rel='alternate' type='text/html' href='http://leomicheloni.blogspot.com/2008/10/moq-26-el-milagro-del-automocking.html' title='Moq 2.6: Mocks recursivos'/><author><name>Leonardo Micheloni</name><uri>http://www.blogger.com/profile/12085246040181097881</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='30' src='http://3.bp.blogspot.com/_t9Bh42Thfqo/S6TVOJqYWcI/AAAAAAAAANU/MlZc6HpYZis/S220/yo+laguito+en+col%C3%B3n.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-148524916779753368.post-8817560407329366417</id><published>2008-10-10T16:20:00.000-03:00</published><updated>2008-10-10T16:21:17.530-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='mock'/><category scheme='http://www.blogger.com/atom/ns#' term='MUG'/><category scheme='http://www.blogger.com/atom/ns#' term='rhino'/><category scheme='http://www.blogger.com/atom/ns#' term='moq'/><category scheme='http://www.blogger.com/atom/ns#' term='unit test'/><title type='text'>Charla en el Microsoft User Group de Argentina, sobre Mocking</title><content type='html'>&lt;p&gt;
        &lt;b&gt;Charla en el Microsoft User Group de Argentina&lt;/b&gt;&lt;/p&gt;
    &lt;p&gt;
        Finalmente llegó el día, el próximo 18 de Noviembre voy a estar dando una charla 
        en el MUG, el título será:&lt;/p&gt;
    &lt;p&gt;
        &lt;b&gt;Mock Objects como solución para pruebas en ambientes complejos. &lt;/b&gt;
    &lt;/p&gt;
    &lt;p&gt;
        La misma estará orientada a desarrolladores y equipos que utlizan pruebas de 
        unidad y son concientes de la problemática de probar componentes con depencias 
        de otros componentes que van más allá del ámbito de la prueba, como interfaces, 
        repositorios de datos, conexiones de red, etc.&lt;/p&gt;
    &lt;p&gt;
        La idea es hablar un poco del modelo de mocking basado en inyección de 
        dependencias, es decir, como
        &lt;a href="http://ayende.com/projects/rhino-mocks.aspx"&gt;Rhino Mocks&lt;/a&gt; y
        &lt;a href="http://code.google.com/p/moq/"&gt;Moq&lt;/a&gt;, y a lo sumo nombrar
        &lt;a href="http://www.typemock.com/"&gt;TypeMock Isolator&lt;/a&gt;, hacer unos ejemplos de 
        dependecias de componentes y ver cómo se pueden diseñar las aplicaciones para 
        disminuir el acoplamiento y poder utlizar mocking para crear pruebas unitarias 
        de calidad, vamos a ver un poco de Rhino y mucho de nuestro framework preferido 
        Moq, todo a través de ejemplos.&lt;/p&gt;
    &lt;p&gt;
        Tengo que agradecer por esta oportunidad a la gente del         &lt;a href="http://www.mug.org,ar"&gt;MUG&lt;/a&gt; por supuesto y especialmente a
        &lt;a href="http://www.vemn.com.ar/Staff.aspx"&gt;Daniel Laco&lt;/a&gt;.&lt;/p&gt;
    &lt;p&gt;
        El link de la charla es este&lt;/p&gt;
    &lt;p&gt;
        &lt;a href="http://www.mug.org.ar/Eventos/3125.aspx"&gt;
        http://www.mug.org.ar/Eventos/3125.aspx&lt;/a&gt;&lt;/p&gt;
    &lt;p&gt;
        Nos vemos en el MUG.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;Leonardo Micheloni&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/148524916779753368-8817560407329366417?l=leomicheloni.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://leomicheloni.blogspot.com/feeds/8817560407329366417/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=148524916779753368&amp;postID=8817560407329366417' title='2 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default/8817560407329366417'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default/8817560407329366417'/><link rel='alternate' type='text/html' href='http://leomicheloni.blogspot.com/2008/10/charla-en-el-microsoft-user-group-de.html' title='Charla en el Microsoft User Group de Argentina, sobre Mocking'/><author><name>Leonardo Micheloni</name><uri>http://www.blogger.com/profile/12085246040181097881</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='30' src='http://3.bp.blogspot.com/_t9Bh42Thfqo/S6TVOJqYWcI/AAAAAAAAANU/MlZc6HpYZis/S220/yo+laguito+en+col%C3%B3n.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-148524916779753368.post-3586597215860740288</id><published>2008-10-06T10:48:00.001-03:00</published><updated>2008-10-06T10:50:00.494-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='mock'/><category scheme='http://www.blogger.com/atom/ns#' term='moq'/><category scheme='http://www.blogger.com/atom/ns#' term='unit test'/><title type='text'>¿Cómo verificar la cantidad de llamadas a un miembro con Moq?</title><content type='html'>&lt;p&gt;
        &lt;b&gt;¿Cómo verificar la cantidad de llamadas a un miembro con Moq?&lt;/b&gt;&lt;/p&gt;
    &lt;p&gt;
        Si hay utlizado &lt;a href="http://code.google.com/p/moq/"&gt;Moq&lt;/a&gt; como yo también
        &lt;a href="http://ayende.com/projects/rhino-mocks.aspx"&gt;Rhino Mocks&lt;/a&gt; 
        seguramente se han encontrado con la ausencia de un modo de verificar la 
        cantidad de llamadas que se hacen sobre un miembre, digamos propiedad o método, 
        o sea, configuramos nuestras Expectations y de alguna manera queresmos 
        asegurarnos que tal miembro es llamado un número exácto de veces, es se hace en 
        Rhino más o menos así&lt;/p&gt;
&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
    &lt;pre class="csharpcode"&gt;[TestMethod]
&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; VerificarCantidadDeLlamadasConRhino()
{
    Rhino.Mocks.MockRepository mocker = &lt;span class="kwrd"&gt;new&lt;/span&gt; Rhino.Mocks.MockRepository();

    var mock = mocker.CreateMock&amp;lt;IFoo&amp;gt;();

    &lt;span class="kwrd"&gt;using&lt;/span&gt; (mocker.Record())
    {
        Rhino.Mocks.Expect.Call(mock.DoInt(2)).Return(22).Repeat.Times(3);
    }

    &lt;span class="rem"&gt;//Rhino hace la verificación al salir del bloque using&lt;/span&gt;
    &lt;span class="kwrd"&gt;using&lt;/span&gt; (mocker.Playback())
    {
        Assert.AreEqual&amp;lt;&lt;span class="kwrd"&gt;int&lt;/span&gt;&amp;gt;(22, mock.DoInt(2));
        Assert.AreEqual&amp;lt;&lt;span class="kwrd"&gt;int&lt;/span&gt;&amp;gt;(22, mock.DoInt(2));
        Assert.AreEqual&amp;lt;&lt;span class="kwrd"&gt;int&lt;/span&gt;&amp;gt;(22, mock.DoInt(2));
    }
}&lt;/pre&gt;
    &lt;p&gt;
        &amp;nbsp;&lt;/p&gt;
    &lt;p&gt;
        Ahora bien, nuestro querido &lt;a href="http://code.google.com/p/moq/"&gt;Moq&lt;/a&gt; no 
        dispones de esa característica,¿ por qué?, porque la idea de
        &lt;a href="http://www.clariusconsulting.net/blogs/kzu/"&gt;Kzu&lt;/a&gt; 
        es que &lt;a href="http://code.google.com/p/moq/"&gt;Moq&lt;/a&gt; sea muy sencillo (no 
        entremos en discusiones del tipo por qué se mezclan Stubs y Mocks porque no 
        tienen sentido) esto es muy bueno y la verdad es que me encanta, pero nos deja 
        con ese problema, cómo lo resolvemos?&lt;/p&gt;
    &lt;p&gt;
        &lt;b&gt;Callbacks, la solución&lt;/b&gt;&lt;/p&gt;
    &lt;p&gt;
        Los Callbacks son acciones que podemos indicar al
        &lt;a href="http://code.google.com/p/moq/"&gt;Moq&lt;/a&gt; que realize un Mock cuando se 
        invoca a uno de sus miembros, o sea, configuramos un Expectation a un miembro y 
        de paso le podemos decir a &lt;a href="http://code.google.com/p/moq/"&gt;Moq&lt;/a&gt; que 
        cuando este miembro sea invocado que haga algo más que puede no tener ninguna 
        relación con el Mock, entonces lo que tenemos que hacer para verificar que un 
        método es llamado un número exácto de veces (o mayor o menor, lo que sea) es 
        configurar un Callback en el miembro que incremente un contador y luego con un 
        Assert verificar el contador, y listo el pollo, de esta manera:&lt;/p&gt;
&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
    &lt;pre class="csharpcode"&gt;[TestMethod]
&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; VerificarCantidadDeLlamadasConMoq()
{
    var mock = &lt;span class="kwrd"&gt;new&lt;/span&gt; Mock&amp;lt;IFoo&amp;gt;();
    &lt;span class="kwrd"&gt;int&lt;/span&gt; contador = 0;

    &lt;span class="rem"&gt;//al configurar el Expectation agregamos un Callback que incrementa contador&lt;/span&gt;
    mock.Expect(x =&amp;gt; x.DoInt(2)).Returns(22).Callback(()=&amp;gt;contador++);

    Assert.AreEqual&amp;lt;&lt;span class="kwrd"&gt;int&lt;/span&gt;&amp;gt;(22, mock.Object.DoInt(2));
    Assert.AreEqual&amp;lt;&lt;span class="kwrd"&gt;int&lt;/span&gt;&amp;gt;(22, mock.Object.DoInt(2));
    Assert.AreEqual&amp;lt;&lt;span class="kwrd"&gt;int&lt;/span&gt;&amp;gt;(22, mock.Object.DoInt(2));

    &lt;span class="rem"&gt;//verificamos contador y listo&lt;/span&gt;
    Assert.AreEqual&amp;lt;&lt;span class="kwrd"&gt;int&lt;/span&gt;&amp;gt;(3,contador);
}&lt;/pre&gt;
    &lt;p&gt;
        &lt;b&gt;Conclusión&lt;/b&gt;&lt;/p&gt;
    &lt;p&gt;
        Personalmente me sigue pareciendo mucho más clara la sintáxis de
        &lt;a href="http://code.google.com/p/moq/"&gt;Moq&lt;/a&gt;, en definitiva puede ser que
        &lt;a href="http://code.google.com/p/moq/"&gt;Moq&lt;/a&gt; sea demasiado sencillo y&lt;a 
            href="http://www.ayende.com/Blog/archive/2007/12/19/Moq-Mocking-in-C-3.0.aspx"&gt; 
        mezcle conceptos de TDD para serlo&lt;/a&gt;, pero la realidad es que &lt;b&gt;es mejor ser 
        productivo que ortodoxo&lt;/b&gt;, no? hasta la próxima.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;Leonardo Micheloni&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/148524916779753368-3586597215860740288?l=leomicheloni.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://leomicheloni.blogspot.com/feeds/3586597215860740288/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=148524916779753368&amp;postID=3586597215860740288' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default/3586597215860740288'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default/3586597215860740288'/><link rel='alternate' type='text/html' href='http://leomicheloni.blogspot.com/2008/10/cmo-verificar-la-cantidad-de-llamadas.html' title='¿Cómo verificar la cantidad de llamadas a un miembro con Moq?'/><author><name>Leonardo Micheloni</name><uri>http://www.blogger.com/profile/12085246040181097881</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='30' src='http://3.bp.blogspot.com/_t9Bh42Thfqo/S6TVOJqYWcI/AAAAAAAAANU/MlZc6HpYZis/S220/yo+laguito+en+col%C3%B3n.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-148524916779753368.post-3239846268651750907</id><published>2008-09-28T19:57:00.001-03:00</published><updated>2008-09-28T20:03:10.969-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='WCF'/><title type='text'>Sindicar contenido con WCF y sobrecarga de métodos</title><content type='html'>&lt;p&gt;
            &lt;b&gt;Syndication con WCF, sobrecarga de métodos de paso.&lt;/b&gt;&lt;/p&gt;
        &lt;p&gt;
            Otra de las funcionalidades que se agregaron con el assemblie 
            System.ServiceModel.Web es la posibilidad de sindicar contenido al estilo .net o 
            sea, fácil y tipificado de verdad, es tán fácil que vamos a ir diréctamente al 
            ejemplo de código. Vamos a ver que en este caso definí una interface del 
            servicio con los atributos, esto es lo más natural y nos da un extra de 
            flexiblidad y un poco más de limpieza en el código que hacerlo como en los 
            ejemplos anteriores:&lt;/p&gt;
&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
        &lt;pre class="csharpcode"&gt;[ServiceContract]
[ServiceKnownType(&lt;span class="kwrd"&gt;typeof&lt;/span&gt;(Atom10FeedFormatter))] &lt;span 
            class="rem"&gt;//indica la forma de serializar los datos Atom&lt;/span&gt;
[ServiceKnownType(&lt;span class="kwrd"&gt;typeof&lt;/span&gt;(Rss20FeedFormatter))]
&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;interface&lt;/span&gt; IServicioPrueba
{
    [OperationContract]
    [WebGet] &lt;span class="rem"&gt;//se usa webget porque tanto RSS con Atom corren sobre HTTP y se invocan con verbos HTTP&lt;/span&gt;
    SyndicationFeedFormatter Feed(&lt;span class="kwrd"&gt;string&lt;/span&gt; tipo);

    [OperationContract]
    [WebGet]
    SyndicationFeedFormatter Feed();
}&lt;/pre&gt;
&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
        &lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; ServicioPrueba : IServicioPrueba
{
    &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;
    &lt;span class="rem"&gt;/// Este método nos permite elegir si queremos Atom, sino RSS&lt;/span&gt;
    &lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;
    &lt;span class="kwrd"&gt;public&lt;/span&gt; SyndicationFeedFormatter Feed(&lt;span class="kwrd"&gt;string&lt;/span&gt; tipo)
    {
        SyndicationFeed feed = GenerarFeed();

        &lt;span class="kwrd"&gt;if&lt;/span&gt; (tipo.Equals(&lt;span class="str"&gt;&amp;quot;atom&amp;quot;&lt;/span&gt;))
        {
            &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;new&lt;/span&gt; Atom10FeedFormatter(feed);
        }
        &lt;span class="kwrd"&gt;else&lt;/span&gt;
        {
            &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;new&lt;/span&gt; Rss20FeedFormatter(feed);
        }
    }

    &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;
    &lt;span class="rem"&gt;/// Genera un feed con dos entradas&lt;/span&gt;
    &lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;
    &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; SyndicationFeed GenerarFeed()
    {
        IList&amp;lt;SyndicationItem&amp;gt; items = &lt;span class="kwrd"&gt;new&lt;/span&gt; List&amp;lt;SyndicationItem&amp;gt;();

        items.Add(&lt;span class="kwrd"&gt;new&lt;/span&gt; SyndicationItem(&lt;span class="str"&gt;&amp;quot;primer noticia&amp;quot;&lt;/span&gt;, &lt;span 
            class="str"&gt;&amp;quot;extra extra cupido apesta!&amp;quot;&lt;/span&gt;, &lt;span class="kwrd"&gt;null&lt;/span&gt;));
        items.Add(&lt;span class="kwrd"&gt;new&lt;/span&gt; SyndicationItem(&lt;span class="str"&gt;&amp;quot;segunda noticia&amp;quot;&lt;/span&gt;, &lt;span 
            class="str"&gt;&amp;quot;Meteoro no seas tonto el enmascarado es tu hermano&amp;quot;&lt;/span&gt;, &lt;span 
            class="kwrd"&gt;null&lt;/span&gt;));

        SyndicationFeed feed = &lt;span class="kwrd"&gt;new&lt;/span&gt; SyndicationFeed(items);
        &lt;span class="kwrd"&gt;return&lt;/span&gt; feed;
    }

    &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;
    &lt;span class="rem"&gt;/// En este método lo publicamos como Rss las clases Rss20FeedFormatter y Atom10FeedFormatter heredas&lt;/span&gt;
    &lt;span class="rem"&gt;/// de SyndicationFeedFormatter por lo tanto se pueden intercambiar casi indistintamente (tiene su especialización)&lt;/span&gt;
    &lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;
    &lt;span class="rem"&gt;/// &amp;lt;returns&amp;gt;&amp;lt;/returns&amp;gt;&lt;/span&gt;
    &lt;span class="kwrd"&gt;public&lt;/span&gt; SyndicationFeedFormatter Feed()
    {
        &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;new&lt;/span&gt; Rss20FeedFormatter(GenerarFeed());
    }
}&lt;/pre&gt;
        &lt;p&gt;
            Por último el host&lt;/p&gt;
&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
        &lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Main(&lt;span 
            class="kwrd"&gt;string&lt;/span&gt;[] args)
{
    &lt;span class="kwrd"&gt;string&lt;/span&gt; address = &lt;span class="str"&gt;&amp;quot;http://localhost:8080/servicio/&amp;quot;&lt;/span&gt;;

    &lt;span class="kwrd"&gt;using&lt;/span&gt;(ServiceHost host = &lt;span class="kwrd"&gt;new&lt;/span&gt; ServiceHost(&lt;span 
            class="kwrd"&gt;typeof&lt;/span&gt;(ServicioPrueba)))
    {                            
        &lt;span class="rem"&gt;//Creamos un endpoint igual al de REST&lt;/span&gt;
        ServiceEndpoint endPoint = &lt;span class="kwrd"&gt;new&lt;/span&gt; ServiceEndpoint(ContractDescription.GetContract(&lt;span 
            class="kwrd"&gt;typeof&lt;/span&gt;(IServicioPrueba)), 
            &lt;span class="kwrd"&gt;new&lt;/span&gt; WebHttpBinding(), &lt;span class="kwrd"&gt;new&lt;/span&gt; EndpointAddress(address));

        endPoint.Behaviors.Add(&lt;span class="kwrd"&gt;new&lt;/span&gt; WebHttpBehavior());

        host.Description.Endpoints.Add(endPoint);

        Console.WriteLine(&lt;span class="str"&gt;&amp;quot;inicializando..&amp;quot;&lt;/span&gt;);
        host.Open();
        Console.WriteLine(&lt;span class="str"&gt;&amp;quot;iniciado..&amp;quot;&lt;/span&gt;);
        Console.ReadLine();
        Console.WriteLine(&lt;span class="str"&gt;&amp;quot;cerrando...&amp;quot;&lt;/span&gt;);
        host.Close();
        Console.WriteLine(&lt;span class="str"&gt;&amp;quot;listo&amp;quot;&lt;/span&gt;);
    }
}&lt;/pre&gt;
        &lt;p&gt;
            Lo que hice fue crear dos métodos, uno (Feed) que devuelve siempre el canal en 
            Rss y otro con un parámetro que nos permite elegir el formato. Si intentamos 
            correr esto vamos a recibir un error muy feo del tipo InvalidOperationException 
            y es porque estamos intentando sobrecargar métodos en WCF.&lt;/p&gt;
        &lt;p&gt;
            &lt;b&gt;Sobrecarga de método en WCF&lt;/b&gt;&lt;/p&gt;
        &lt;p&gt;
            Sí, se pueden sobrecargar métodos en WCF, de echo lo hacemos y al compilar todo 
            va bien, hasta que hacemos Open() del host y todo explota. ¿Qué ocurre? simple, 
            al hacer Open() WCF comieza a generar la metadata para el servicio, como siempre 
            utilizar WSDL y WSDL es SOAP (o naturalmente lo es), y a pesar que SOAP es 
            &amp;quot;Simple Object Access Protocol&amp;quot; (ya sé que desde la versión 1.2 no lo es), no soporta conceptos de orientación a objetos como la sobrecarga por 
            lo tanto BOOM, no funciona.&lt;/p&gt;
        &lt;p&gt;
            &lt;i&gt;La metadata generada para el servicio a pesar que el WebHttpBinding es WSDL&lt;/i&gt;&lt;/p&gt;
&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
        &lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;&amp;lt;?&lt;/span&gt;&lt;span class="html"&gt;xml&lt;/span&gt; &lt;span 
            class="attr"&gt;version&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;1.0&amp;quot;&lt;/span&gt; &lt;span 
            class="attr"&gt;encoding&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;utf8&amp;quot;&lt;/span&gt; ?&lt;span 
            class="kwrd"&gt;&amp;gt;&lt;/span&gt;
 &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;wsdl:definitions&lt;/span&gt; &lt;span 
            class="attr"&gt;name&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;ServicioPrueba&amp;quot;&lt;/span&gt; &lt;span 
            class="attr"&gt;targetNamespace&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;http://tempuri.org/&amp;quot;&lt;/span&gt; &lt;span 
            class="attr"&gt;xmlns:wsdl&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;http://schemas.xmlsoap.org/wsdl/&amp;quot;&lt;/span&gt; &lt;span 
            class="attr"&gt;xmlns:soap&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;http://schemas.xmlsoap.org/wsdl/soap/&amp;quot;&lt;/span&gt; &lt;span 
            class="attr"&gt;xmlns:wsu&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;http://docs.oasisopen.org/wss/2004/01/oasis200401wsswssecurityutility1.0.xsd&amp;quot;&lt;/span&gt; &lt;span 
            class="attr"&gt;xmlns:soapenc&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;http://schemas.xmlsoap.org/soap/encoding/&amp;quot;&lt;/span&gt; &lt;span 
            class="attr"&gt;xmlns:wsam&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;http://www.w3.org/2007/05/addressing/metadata&amp;quot;&lt;/span&gt; &lt;span 
            class="attr"&gt;xmlns:tns&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;http://tempuri.org/&amp;quot;&lt;/span&gt; &lt;span 
            class="attr"&gt;xmlns:wsa&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;http://schemas.xmlsoap.org/ws/2004/08/addressing&amp;quot;&lt;/span&gt; &lt;span 
            class="attr"&gt;xmlns:wsp&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;http://schemas.xmlsoap.org/ws/2004/09/policy&amp;quot;&lt;/span&gt; &lt;span 
            class="attr"&gt;xmlns:wsap&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;http://schemas.xmlsoap.org/ws/2004/08/addressing/policy&amp;quot;&lt;/span&gt; &lt;span 
            class="attr"&gt;xmlns:xsd&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;http://www.w3.org/2001/XMLSchema&amp;quot;&lt;/span&gt; &lt;span 
            class="attr"&gt;xmlns:msc&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;http://schemas.microsoft.com/ws/2005/12/wsdl/contract&amp;quot;&lt;/span&gt; &lt;span 
            class="attr"&gt;xmlns:wsaw&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;http://www.w3.org/2006/05/addressing/wsdl&amp;quot;&lt;/span&gt; &lt;span 
            class="attr"&gt;xmlns:soap12&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;http://schemas.xmlsoap.org/wsdl/soap12/&amp;quot;&lt;/span&gt; &lt;span 
            class="attr"&gt;xmlns:wsa10&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;http://www.w3.org/2005/08/addressing&amp;quot;&lt;/span&gt; &lt;span 
            class="attr"&gt;xmlns:wsx&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;http://schemas.xmlsoap.org/ws/2004/09/mex&amp;quot;&amp;gt;&lt;/span&gt;
   &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;wsdl:types&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
     &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;xsd:schema&lt;/span&gt; &lt;span class="attr"&gt;targetNamespace&lt;/span&gt;&lt;span 
            class="kwrd"&gt;=&amp;quot;http://tempuri.org/Imports&amp;quot;&amp;gt;&lt;/span&gt;
      &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;xsd:import&lt;/span&gt; &lt;span 
            class="attr"&gt;schemaLocation&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;http://localhost:8080/servicio/?xsd=xsd3&amp;quot;&lt;/span&gt; &lt;span 
            class="attr"&gt;namespace&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;http://tempuri.org/&amp;quot;&lt;/span&gt; &lt;span 
            class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;xsd:import&lt;/span&gt; &lt;span 
            class="attr"&gt;schemaLocation&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;http://localhost:8080/servicio/?xsd=xsd0&amp;quot;&lt;/span&gt; &lt;span 
            class="attr"&gt;namespace&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;http://schemas.microsoft.com/2003/10/Serialization/&amp;quot;&lt;/span&gt; &lt;span 
            class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;xsd:import&lt;/span&gt; &lt;span 
            class="attr"&gt;schemaLocation&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;http://localhost:8080/servicio/?xsd=xsd1&amp;quot;&lt;/span&gt; &lt;span 
            class="attr"&gt;namespace&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;http://schemas.datacontract.org/2004/07/System.ServiceModel.Syndication&amp;quot;&lt;/span&gt; &lt;span 
            class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;xsd:import&lt;/span&gt; &lt;span 
            class="attr"&gt;schemaLocation&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;http://localhost:8080/servicio/?xsd=xsd2&amp;quot;&lt;/span&gt; &lt;span 
            class="attr"&gt;namespace&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;http://www.w3.org/2005/Atom&amp;quot;&lt;/span&gt; &lt;span 
            class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;xsd:schema&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;wsdl:types&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
   &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;wsdl:message&lt;/span&gt; &lt;span class="attr"&gt;name&lt;/span&gt;&lt;span 
            class="kwrd"&gt;=&amp;quot;IServicioPrueba_Feed_InputMessage&amp;quot;&amp;gt;&lt;/span&gt;
    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;wsdl:part&lt;/span&gt; &lt;span class="attr"&gt;name&lt;/span&gt;&lt;span 
            class="kwrd"&gt;=&amp;quot;parameters&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;element&lt;/span&gt;&lt;span 
            class="kwrd"&gt;=&amp;quot;tns:Feed&amp;quot;&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;wsdl:message&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
   &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;wsdl:message&lt;/span&gt; &lt;span class="attr"&gt;name&lt;/span&gt;&lt;span 
            class="kwrd"&gt;=&amp;quot;IServicioPrueba_Feed_OutputMessage&amp;quot;&amp;gt;&lt;/span&gt;
    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;wsdl:part&lt;/span&gt; &lt;span class="attr"&gt;name&lt;/span&gt;&lt;span 
            class="kwrd"&gt;=&amp;quot;parameters&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;element&lt;/span&gt;&lt;span 
            class="kwrd"&gt;=&amp;quot;tns:FeedResponse&amp;quot;&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;wsdl:message&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
   &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;wsdl:portType&lt;/span&gt; &lt;span 
            class="attr"&gt;name&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;IServicioPrueba&amp;quot;&amp;gt;&lt;/span&gt;
     &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;wsdl:operation&lt;/span&gt; &lt;span 
            class="attr"&gt;name&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;Feed&amp;quot;&amp;gt;&lt;/span&gt;
      &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;wsdl:input&lt;/span&gt; &lt;span 
            class="attr"&gt;wsaw:Action&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;http://tempuri.org/IServicioPrueba/Feed&amp;quot;&lt;/span&gt; &lt;span 
            class="attr"&gt;message&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;tns:IServicioPrueba_Feed_InputMessage&amp;quot;&lt;/span&gt; &lt;span 
            class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;wsdl:output&lt;/span&gt; &lt;span 
            class="attr"&gt;wsaw:Action&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;http://tempuri.org/IServicioPrueba/FeedResponse&amp;quot;&lt;/span&gt; &lt;span 
            class="attr"&gt;message&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;tns:IServicioPrueba_Feed_OutputMessage&amp;quot;&lt;/span&gt; &lt;span 
            class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;wsdl:operation&lt;/span&gt;&lt;span 
            class="kwrd"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;wsdl:portType&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
   &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;wsdl:binding&lt;/span&gt; &lt;span class="attr"&gt;name&lt;/span&gt;&lt;span 
            class="kwrd"&gt;=&amp;quot;WebHttpBinding_IServicioPrueba&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;type&lt;/span&gt;&lt;span 
            class="kwrd"&gt;=&amp;quot;tns:IServicioPrueba&amp;quot;&amp;gt;&lt;/span&gt;
     &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;wsdl:operation&lt;/span&gt; &lt;span 
            class="attr"&gt;name&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;Feed&amp;quot;&amp;gt;&lt;/span&gt;
      &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;wsdl:input&lt;/span&gt; &lt;span 
            class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;wsdl:output&lt;/span&gt; &lt;span 
            class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;wsdl:operation&lt;/span&gt;&lt;span 
            class="kwrd"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;wsdl:binding&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
   &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;wsdl:service&lt;/span&gt; &lt;span class="attr"&gt;name&lt;/span&gt;&lt;span 
            class="kwrd"&gt;=&amp;quot;ServicioPrueba&amp;quot;&amp;gt;&lt;/span&gt;
    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;wsdl:port&lt;/span&gt; &lt;span class="attr"&gt;name&lt;/span&gt;&lt;span 
            class="kwrd"&gt;=&amp;quot;WebHttpBinding_IServicioPrueba&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;binding&lt;/span&gt;&lt;span 
            class="kwrd"&gt;=&amp;quot;tns:WebHttpBinding_IServicioPrueba&amp;quot;&lt;/span&gt; &lt;span 
            class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;wsdl:service&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;wsdl:definitions&lt;/span&gt;&lt;span 
            class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;
        &lt;p&gt;
            ¿Entonces cuál es la solución?&lt;/p&gt;
        &lt;p&gt;
            La solución es utilizar un alias para los métodos, ya sé que van a decir que 
            entonces es como si tuvieran otro nombre, y tienen razón, pero parcialmente, si 
            consumimos un servicio WCF desde WCF podemos llamar al mismo método en una u 
            otra sobrecarga (utilizando la interface cliente no el proxy svcutility.exe en 
            caso de usar el proxy se puede editar a mano)&lt;/p&gt;
        &lt;p&gt;
            Entonces el código de la interface queda así:&lt;/p&gt;
&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
        &lt;pre class="csharpcode"&gt;[ServiceContract]
[ServiceKnownType(&lt;span class="kwrd"&gt;typeof&lt;/span&gt;(Atom10FeedFormatter))] &lt;span 
            class="rem"&gt;//indica la forma de serializar los datos Atom&lt;/span&gt;
[ServiceKnownType(&lt;span class="kwrd"&gt;typeof&lt;/span&gt;(Rss20FeedFormatter))]
&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;interface&lt;/span&gt; IServicioPrueba
{
    [OperationContract(Name = &lt;span class="str"&gt;&amp;quot;default&amp;quot;&lt;/span&gt;)]&lt;span class="rem"&gt;//alias para esta operación&lt;/span&gt;
    [WebGet] &lt;span class="rem"&gt;//se usa webget porque tanto RSS con Atom corren sobre HTTP y se invocan con verbos HTTP&lt;/span&gt;
    SyndicationFeedFormatter Feed(&lt;span class="kwrd"&gt;string&lt;/span&gt; tipo);

    [OperationContract]
    [WebGet]
    SyndicationFeedFormatter Feed();
}&lt;/pre&gt;
        &lt;p&gt;
            &amp;nbsp;&lt;/p&gt;
        &lt;p&gt;
            Y listo, ahora funciona&lt;/p&gt;
        &lt;p&gt;
            &lt;a href="http://2.bp.blogspot.com/_t9Bh42Thfqo/SOAMGpT95dI/AAAAAAAAAHQ/4Jx1hTBpP9o/s1600-h/atom.png"&gt;
            &lt;img id="BLOGGER_PHOTO_ID_5251210473822348754" alt="" border="0" 
                src="http://2.bp.blogspot.com/_t9Bh42Thfqo/SOAMGpT95dI/AAAAAAAAAHQ/4Jx1hTBpP9o/s320/atom.png" 
                style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" /&gt;&lt;/a&gt;
            &lt;a href="http://1.bp.blogspot.com/_t9Bh42Thfqo/SOAMHDWuPZI/AAAAAAAAAHY/KAj4UDm-tKk/s1600-h/rss.png"&gt;
            &lt;img id="BLOGGER_PHOTO_ID_5251210480813227410" alt="" border="0" 
                src="http://1.bp.blogspot.com/_t9Bh42Thfqo/SOAMHDWuPZI/AAAAAAAAAHY/KAj4UDm-tKk/s320/rss.png" 
                style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" /&gt;&lt;/a&gt; &lt;/p&gt;
        &lt;p&gt;
            Mágico una vez más, hasta la próxima.&lt;/p&gt;
        &lt;p&gt;
            &lt;b&gt;Referencias&lt;/b&gt;&lt;/p&gt;
        &lt;p&gt;
            &lt;a href="http://www.w3.org/TR/soap/"&gt;SOAP W3C&lt;/a&gt;&lt;/p&gt;
        &lt;p&gt;
            &lt;a href="http://www.w3.org/TR/wsdl"&gt;WSDL W3C&lt;/a&gt;&lt;/p&gt;
        &lt;p&gt;
            &lt;a href="http://msdn.microsoft.com/en-us/magazine/cc135976.aspx"&gt;WCF Syndication 
            MDSN&lt;/a&gt;&lt;/p&gt;
        &lt;p&gt;
            &amp;nbsp;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;Leonardo Micheloni&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/148524916779753368-3239846268651750907?l=leomicheloni.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://leomicheloni.blogspot.com/feeds/3239846268651750907/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=148524916779753368&amp;postID=3239846268651750907' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default/3239846268651750907'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default/3239846268651750907'/><link rel='alternate' type='text/html' href='http://leomicheloni.blogspot.com/2008/09/sindicar-contenido-con-wcf-y-sobrecarga.html' title='Sindicar contenido con WCF y sobrecarga de métodos'/><author><name>Leonardo Micheloni</name><uri>http://www.blogger.com/profile/12085246040181097881</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='30' src='http://3.bp.blogspot.com/_t9Bh42Thfqo/S6TVOJqYWcI/AAAAAAAAANU/MlZc6HpYZis/S220/yo+laguito+en+col%C3%B3n.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_t9Bh42Thfqo/SOAMGpT95dI/AAAAAAAAAHQ/4Jx1hTBpP9o/s72-c/atom.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-148524916779753368.post-3765404443469581973</id><published>2008-09-21T18:46:00.003-03:00</published><updated>2010-06-27T21:46:36.576-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='REST'/><category scheme='http://www.blogger.com/atom/ns#' term='WCF'/><title type='text'>REST en WCF</title><content type='html'>&lt;p&gt;
&lt;b&gt;REST con WCF&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;
Siguiendo con el tema de WCF vamos a ver que fácil que es exponer un nuevo
endPoint para un servicio existente para publicarlo de otra manera, en el post
anterior vimos cómo crear un servicio y exponerlo "a la antigua" para que sea
compatible con ASMX, ahora vamos a ver que simple que es tomar el mismo código y
exponer el servicio como una api REST ya que está de moda.&lt;/p&gt;
&lt;p&gt;
&lt;b&gt;REST una arquitectura&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;
La idea de rest es aprovechar las capacidades del protocolo HTTP para utilizarlo
como arquitectura de servicios, es decir: ¿si ya tenemos un protocolo que todos
comprenden por qué no aprovecharlo para exponer servicios en lugar de ponerle
otros protocolos arribla, como SOAP? gran idea, además ahorramos overhead.
Tenemos los verbos necesarios para hacer las operaciones (GET, POST, DELETE y
PUT), las direcciones, el formato, todo universal, por lo tanto podemos
aprovecharlo.&lt;/p&gt;
&lt;p&gt;
&lt;b&gt;Framework 3.5&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;
Para poder utilizar REST sobre WCF es necesario instalar el Framework 3.5, el
assemblie que contiene la funcionalidad es System.ServiceModel.Web, así que hay
que referenciarlo, una vez que hacemos esto el código es éste:&lt;/p&gt;
&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;namespace&lt;/span&gt; PruebaWCF
{
    &lt;span class="kwrd"&gt;class&lt;/span&gt; Program
    {
        &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Main(&lt;span class="kwrd"&gt;string&lt;/span&gt;[] args)
        {
            &lt;span class="kwrd"&gt;string&lt;/span&gt; uriRest = &lt;span class="str"&gt;"http://localhost:8080/rest/"&lt;/span&gt;;

            &lt;span class="kwrd"&gt;using&lt;/span&gt; (ServiceHost host = &lt;span class="kwrd"&gt;new&lt;/span&gt; ServiceHost(&lt;span class="kwrd"&gt;typeof&lt;/span&gt;(MiServicio)))
            {
                ContractDescription description = ContractDescription.GetContract(&lt;span class="kwrd"&gt;typeof&lt;/span&gt;(MiServicio));

                &lt;span class="rem"&gt;//cambiamos el binding por WebHttpBinding&lt;/span&gt;
                ServiceEndpoint endPointREST = &lt;span class="kwrd"&gt;new&lt;/span&gt; ServiceEndpoint(description,
                    &lt;span class="kwrd"&gt;new&lt;/span&gt; WebHttpBinding(), &lt;span class="kwrd"&gt;new&lt;/span&gt; EndpointAddress(uriRest));

                &lt;span class="rem"&gt;//agregamos un comportamiento al endPoint del tipo WebHttpBehavior&lt;/span&gt;
                endPointREST.Behaviors.Add(&lt;span class="kwrd"&gt;new&lt;/span&gt; WebHttpBehavior());

                &lt;span class="rem"&gt;//agregamos el endPoint al servicio&lt;/span&gt;
                host.Description.Endpoints.Add(endPointREST);

                &lt;span class="rem"&gt;//por último abrimos el host&lt;/span&gt;
                host.Open();

                Console.WriteLine(&lt;span class="str"&gt;"iniciado.."&lt;/span&gt;);
                Console.ReadLine();
                &lt;span class="rem"&gt;//cuando se presiona enter ser cierra el servicio&lt;/span&gt;
                host.Close();
                Console.WriteLine(&lt;span class="str"&gt;"finalizado.."&lt;/span&gt;);
            }
        }
    }

    &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;
    &lt;span class="rem"&gt;/// Con ServiceContract indicamos que éste es un contrato de servicio&lt;/span&gt;
    &lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;
    [ServiceContract]
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; MiServicio
    {
        &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;
        &lt;span class="rem"&gt;/// Con OperationContract indicamos que esta operación es un operación del servicio&lt;/span&gt;
        &lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;
        [OperationContract]
        &lt;span class="rem"&gt;//sólo es necesario este atributo para permitir la invocación del tipo Http Get&lt;/span&gt;
        [WebGet]
        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; Saludo(&lt;span class="kwrd"&gt;string&lt;/span&gt; nombre)
        {
            &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt;.Concat(&lt;span class="str"&gt;"Hola "&lt;/span&gt;, nombre);
        }
    }

}&lt;/pre&gt;
&lt;p&gt;
&lt;a href="http://4.bp.blogspot.com/_t9Bh42Thfqo/SNbAt6icM2I/AAAAAAAAAHI/UG7rYzi4D48/s1600-h/invocando.png"&gt;
&lt;img style="TEXT-ALIGN: center; MARGIN: 0px auto 10px; DISPLAY: block; CURSOR: hand" id="BLOGGER_PHOTO_ID_5248594310787248994" border="0" alt="" src="http://4.bp.blogspot.com/_t9Bh42Thfqo/SNbAt6icM2I/AAAAAAAAAHI/UG7rYzi4D48/s320/invocando.png" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;
Super mágico, hasta la próxima.
&lt;/p&gt;
&lt;p&gt;
&lt;b&gt;Referencias&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://es.wikipedia.org/wiki/Representational_State_Transfer"&gt;REST&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://es.wikipedia.org/wiki/HTTP"&gt;HTTP&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://netfx3.com/content/WCFHome.aspx"&gt;Framework 3.5&lt;/a&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;Leonardo Micheloni&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/148524916779753368-3765404443469581973?l=leomicheloni.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://leomicheloni.blogspot.com/feeds/3765404443469581973/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=148524916779753368&amp;postID=3765404443469581973' title='1 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default/3765404443469581973'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default/3765404443469581973'/><link rel='alternate' type='text/html' href='http://leomicheloni.blogspot.com/2008/09/rest-en-wcf.html' title='REST en WCF'/><author><name>Leonardo Micheloni</name><uri>http://www.blogger.com/profile/12085246040181097881</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='30' src='http://3.bp.blogspot.com/_t9Bh42Thfqo/S6TVOJqYWcI/AAAAAAAAANU/MlZc6HpYZis/S220/yo+laguito+en+col%C3%B3n.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_t9Bh42Thfqo/SNbAt6icM2I/AAAAAAAAAHI/UG7rYzi4D48/s72-c/invocando.png' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-148524916779753368.post-6725955156543788618</id><published>2008-09-17T10:28:00.003-03:00</published><updated>2010-06-27T21:47:25.293-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='REST'/><category scheme='http://www.blogger.com/atom/ns#' term='VS2008'/><category scheme='http://www.blogger.com/atom/ns#' term='WCF'/><title type='text'>Introducción a WCF ABC, con cliente ASMX</title><content type='html'>&lt;p&gt;
&lt;b&gt;WCF&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;
Windows Comunication Foundation es un SDK para desarrollar servicio de
Microsoft, es parte del framework 3, necesita framework 2 y el framework 3.5
agrega algunas extensiones como el soporte para servicios REST.&lt;/p&gt;
&lt;p&gt;
La idea principal detrás de WCF es un modelo unificado de desarrollo de
servicios independiente de detalles de implementación como el protocolo de
transporte, la seguridad, etc&lt;/p&gt;
&lt;p&gt;
Entonces podemos tener un único servicio programado de una manera particular y
exponerlo de diferentes formas, cada punto de contacto con el exterior de un
servicio en WCF se conoce como Endpoint. Por lo tanto decimos que un servicio
WCF tiene un numero de Endpoints, cada cual diferenciado por dirección, puerto,
protocolo de transporte, etc.&lt;/p&gt;
&lt;p&gt;
&lt;b&gt;El ABC&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;
Cada vez que veamos una introducción a WCF vamos a ver que se habla del ABC,
esto es, &lt;/p&gt;
&lt;p&gt;
A: Address, la dirección del servicio. Está relacionado obviamente con el
protocolo, ya que si es http seguramente el address comenzará con http.&lt;/p&gt;
&lt;p&gt;
B: Binding, el protocolo de transporte o mejor dicho el esquema de transporte
porque es algo más que el protoloco, entre ellos HTTP, TCP, Named pipes, MSMQ,
etc.&lt;/p&gt;
&lt;p&gt;
C: Contract, el contrato, es decir las acciones y tipos que expone el servicio.&lt;/p&gt;
&lt;p&gt;
&lt;b&gt;Hosting&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;
Seguramente se están preguntando cómo "hostear" los servicio, bien, hay un par
de alternativas, IIS, en una aplicación .net cualquiera (un servicio de windows,
una aplicación de consola) o con WAS (Windows activation service), en estos
ejemplos vamos a utilizar una aplicación de consola .net.&lt;/p&gt;
&lt;p&gt;
Vamos a los bifes.&lt;/p&gt;
&lt;p&gt;
Como no me gusta dar vueltas, me parece que lo mejor es ver cómo hacemos para
crear un servicio y tener varios Endpoint (por ahora uno y lo vamos a ir
modificando en otros posts). Antes que nada necesitamos Visual
Studio 2005 + la extensiones para framework 3 o directamente cualquier versión
de Visual Studio 2008.&lt;/p&gt;
&lt;p&gt;
Agregamos el assemblie System.ServiceModel.dll y listo, veámos el código
auto-descriptivo.&lt;/p&gt;
&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; System;
&lt;span class="kwrd"&gt;using&lt;/span&gt; System.Collections.Generic;
&lt;span class="kwrd"&gt;using&lt;/span&gt; System.Linq;
&lt;span class="kwrd"&gt;using&lt;/span&gt; System.Text;
&lt;span class="kwrd"&gt;using&lt;/span&gt; System.ServiceModel;

&lt;span class="kwrd"&gt;namespace&lt;/span&gt; PruebaWCF
{
    &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;
    &lt;span class="rem"&gt;/// Con ServiceContract indicamos que éste es un contrato de servicio&lt;/span&gt;
    &lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;
    [ServiceContract]
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; MiServicio
    {
        &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;
        &lt;span class="rem"&gt;/// Con OperationContract indicamos que esta operación es un operación del servicio&lt;/span&gt;
        &lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;
        [OperationContract]
        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; Saludo(&lt;span class="kwrd"&gt;string&lt;/span&gt; nombre)
        {
            &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt;.Concat(&lt;span class="str"&gt;"Hola "&lt;/span&gt;, nombre);
        }
    }
}}&lt;/pre&gt;
&lt;p&gt;
Como vemos es una simple clase con un par de atributos para indicar algunas
cosas al WCF ( más adelante vamos a ver que es más interesante extraer la
interface con los atributos pero por ahora lo dejamos así para que se más
fácil).&lt;/p&gt;
&lt;p&gt;
Con esto tenemos el servicio terminado, sólo falta "hostearlo", vamos a ver cómo
se hace y cómo configuramos los bindings, behaviors, endpoints y etc./p&gt;
&lt;p&gt;
&lt;b&gt;Hosteando nuestro primer servicio WCF&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;
Para el primer ejemplo vamos a utilizar un Binding que nos permite utlizar este
servicio con un cliente .net 2.0 clásico, el binding que nos permite esto es el
BasicHttpBinding.&lt;/p&gt;
&lt;p&gt;
&lt;b&gt;La configuración&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;
La configuración es un tema medio pesado, ya que hay muchas cosas que configurar
(cuanto más flexible mas complejo), si bien se han agregado algunos "factories"
para facilitar la creación de servicios cuando se "hostean" en IIS, nosotros por
el momento vamos a ver alguinos ejemplos sencillos. La configuración puede
hacerce por código o por archivo de configuración, la segunda opción permite más
flexibilidad ya que podemos cambiar muchas cosas sin recompilar como agregar un
registro de sucesos, autenticación, endonints, etc. si bien no todo se puede
hacer por configuración es un poco pesado el tema, por lo tanto vamos a ver los
ejemplos haciéndolo por código que de paso quedan más claros los conceptos.&lt;/p&gt;
&lt;p&gt;
&lt;b&gt;Behaviors&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;
Lo último que voy a contar antes del código es sobre los behaviors o
comportamientos, hay de dos niveles, de nivel servicio (afectan a todos los
endpoints) y a nivel endpoint, qué permiten hacer? por ejemplo registrar los
mensajes, publicar la metadata, algo personalizado, etc.&lt;/p&gt;
&lt;p&gt;
Ahora sí, el código de nuestro host&lt;/p&gt;
&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;namespace&lt;/span&gt; PruebaWCF
{
    &lt;span class="kwrd"&gt;class&lt;/span&gt; Program
    {
        &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Main(&lt;span class="kwrd"&gt;string&lt;/span&gt;[] args)
        {
            &lt;span class="kwrd"&gt;string&lt;/span&gt; uri = &lt;span class="str"&gt;"http://localhost:8080/servicio/"&lt;/span&gt;;

            &lt;span class="kwrd"&gt;using&lt;/span&gt;(ServiceHost host = &lt;span class="kwrd"&gt;new&lt;/span&gt; ServiceHost(&lt;span class="kwrd"&gt;typeof&lt;/span&gt;(MiServicio)))
            {
                &lt;span class="rem"&gt;//definimos un endpoint para el servicio del tipo&lt;/span&gt;
                &lt;span class="rem"&gt;//basicHttpBinding que es compatible con servicios asmx&lt;/span&gt;
                &lt;span class="rem"&gt;//como vemos en la forma más sencilla sólo necesitamos 2 líneas&lt;/span&gt;
                &lt;span class="rem"&gt;//de código para configurar un servicio WCF&lt;/span&gt;
                ServiceEndpoint endPoint = &lt;span class="kwrd"&gt;new&lt;/span&gt; ServiceEndpoint(
                        ContractDescription.GetContract(&lt;span class="kwrd"&gt;typeof&lt;/span&gt;(MiServicio)),
                        &lt;span class="kwrd"&gt;new&lt;/span&gt; BasicHttpBinding(), &lt;span class="kwrd"&gt;new&lt;/span&gt; EndpointAddress(uri));

                host.Description.Endpoints.Add(endPoint);

                &lt;span class="rem"&gt;//este comportamiento indica que se va a publicar la metadata del servicio&lt;/span&gt;
                &lt;span class="rem"&gt;//para poder generar el proxy desde el lado del cliente más facilmente&lt;/span&gt;
                &lt;span class="rem"&gt;//una vez que tenemos el proxy generado no es necesario esto&lt;/span&gt;
                ServiceMetadataBehavior behavior = &lt;span class="kwrd"&gt;new&lt;/span&gt; ServiceMetadataBehavior();
                behavior.HttpGetEnabled = &lt;span class="kwrd"&gt;true&lt;/span&gt;;
                behavior.HttpGetUrl = &lt;span class="kwrd"&gt;new&lt;/span&gt; Uri(uri);

                host.Description.Behaviors.Add(behavior);

                &lt;span class="rem"&gt;//por último abrimos el host&lt;/span&gt;
                host.Open();

                Console.WriteLine(&lt;span class="str"&gt;"iniciado.."&lt;/span&gt;);
                Console.ReadLine();
                &lt;span class="rem"&gt;//cuando se presiona enter ser cierra el servicio&lt;/span&gt;
                host.Close();
                Console.WriteLine(&lt;span class="str"&gt;"finalizado.."&lt;/span&gt;);
            }
        }
    }
}
&lt;/pre&gt;
&lt;p&gt;
La clase ServiceHost se encarga de "hostear" nuestro servicio, entonces creamos
un Endpoint con:&lt;/p&gt;
&lt;p&gt;
&lt;b&gt;Contrato&lt;/b&gt;: &lt;i&gt;ContractDescription&lt;/i&gt;.&lt;i&gt;GetContract&lt;/i&gt;(&lt;i&gt;typeof&lt;/i&gt;(MiServicio))&lt;/p&gt;
&lt;p&gt;
&lt;b&gt;Binding&lt;/b&gt;: &lt;i&gt;BasicHttpBinding&lt;/i&gt; para que sea compatible con un cliente asmx&lt;/p&gt;
&lt;p&gt;
&lt;b&gt;Address&lt;/b&gt;: new &lt;i&gt;EndpointAddress&lt;/i&gt;(url)&lt;/p&gt;
&lt;p&gt;
Los agregadomos al host con host.Description.Endpoints.Add(endPoint)&lt;/p&gt;
&lt;p&gt;
y listo, ya funciona haciendo &lt;i&gt;host.Open()&lt;/i&gt;.&lt;/p&gt;
&lt;p&gt;
Le agregué el &lt;i&gt;ServiceMetadataBehavior&lt;/i&gt; para que se publique la metadata del
servicio apra poder generar el proxy desde Visual Studio 2005 con un cliente
asmx, después se puede quitar este behavior y diría que es casi recomendable, un
detalle es que puedo publicar la metadata en otra url, yo lo hice en la misma
por comodidad.&lt;/p&gt;
&lt;p&gt;
Consumiendo un servicio WCF desde ASMX&lt;/p&gt;
&lt;p&gt;
Y llegamos a la parte interesante, si tuvieramos un servicio publicado cuyos
clientes con asmx y se nos ocurre actulizarlo a WCF por motivos valederos (como
por ejemplo porque es más lindo) nada está perdido, el servicio que acabamos de
generar es compatible con asmx y lo vamos a demostrar.&lt;/p&gt;
&lt;p&gt;
Agregamos la referencia como simpre&lt;/p&gt;
&lt;p&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_t9Bh42Thfqo/SNEGMjrJCUI/AAAAAAAAAG4/gZBC7WOk_dQ/s1600-h/agregandoServicio.png"&gt;&lt;img style="TEXT-ALIGN: center; MARGIN: 0px auto 10px; DISPLAY: block; CURSOR: hand" id="BLOGGER_PHOTO_ID_5246981853667723586" border="0" alt="" src="http://3.bp.blogspot.com/_t9Bh42Thfqo/SNEGMjrJCUI/AAAAAAAAAG4/gZBC7WOk_dQ/s320/agregandoServicio.png" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;
Un poco de código del lado del cliente para invocar al servicio WCF&lt;/p&gt;
&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;class&lt;/span&gt; Program
{
    &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Main(&lt;span class="kwrd"&gt;string&lt;/span&gt;[] args)
    {
        WCFService.MiServicio servicio = &lt;span class="kwrd"&gt;new&lt;/span&gt; WCFService.MiServicio();
        Console.WriteLine(servicio.Saludo(&lt;span class="str"&gt;"leonardo"&lt;/span&gt;));

        Console.ReadLine();
    }
}&lt;/pre&gt;
&lt;p&gt;
 &lt;/p&gt;
&lt;p&gt;
Y listo, mágico.Hasta la próxima&lt;/p&gt;
&lt;p&gt;
&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_t9Bh42Thfqo/SNEGbjkOp1I/AAAAAAAAAHA/qXQZoV070sc/s1600-h/ejecucion.png"&gt;
&lt;img style="TEXT-ALIGN: center; MARGIN: 0px auto 10px; DISPLAY: block; CURSOR: hand" id="BLOGGER_PHOTO_ID_5246982111336769362" border="0" alt="" src="http://4.bp.blogspot.com/_t9Bh42Thfqo/SNEGbjkOp1I/AAAAAAAAAHA/qXQZoV070sc/s320/ejecucion.png" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;
Referencias:&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://www.microsoft.com/spanish/msdn/articulos/archivo/041206/voices/WindowsCommunicationFoundation.mspx"&gt;
Visión global de la arquitectura de WCF MSDN&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://www.microsoft.com/spanish/msdn/articulos/archivo/041206/voices/LearnTheABCsOfP.mspx"&gt;
ABC de la programación de WCF&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;
 &lt;/p&gt;&lt;div class="blogger-post-footer"&gt;Leonardo Micheloni&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/148524916779753368-6725955156543788618?l=leomicheloni.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://leomicheloni.blogspot.com/feeds/6725955156543788618/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=148524916779753368&amp;postID=6725955156543788618' title='3 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default/6725955156543788618'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default/6725955156543788618'/><link rel='alternate' type='text/html' href='http://leomicheloni.blogspot.com/2008/09/introduccin-wcf-abc-con-cliente-asmx.html' title='Introducción a WCF ABC, con cliente ASMX'/><author><name>Leonardo Micheloni</name><uri>http://www.blogger.com/profile/12085246040181097881</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='30' src='http://3.bp.blogspot.com/_t9Bh42Thfqo/S6TVOJqYWcI/AAAAAAAAANU/MlZc6HpYZis/S220/yo+laguito+en+col%C3%B3n.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_t9Bh42Thfqo/SNEGMjrJCUI/AAAAAAAAAG4/gZBC7WOk_dQ/s72-c/agregandoServicio.png' height='72' width='72'/><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-148524916779753368.post-9082610670160463245</id><published>2008-09-11T00:15:00.002-03:00</published><updated>2008-09-11T00:19:57.187-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='agiles2008'/><title type='text'>Ágiles 2008 - primera versión del programa</title><content type='html'>&lt;p&gt;Está disponible en &lt;a href="http://agiles2008.org/es/programa.php"&gt;http://agiles2008.org/es/programa.php&lt;/a&gt; la primera versión del programa de lo que serán la primeras jornadas de desarrollo ágil de Latinoamérica, para los que se anotaron ya pueden ir viendo cuales de las charlas simultáneas van a ver (no creo que haya muchos cambios con la versión final), lo que no se anotaron están a tiempo de hacerlo &lt;a href="http://agiles2008.org/es/contacto.php"&gt;Aquí&lt;/a&gt; asique nos vemos el 22 y 23 de Octubre en el Bauen.&lt;/p&gt;
&lt;p&gt;Saludos.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;Leonardo Micheloni&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/148524916779753368-9082610670160463245?l=leomicheloni.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://leomicheloni.blogspot.com/feeds/9082610670160463245/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=148524916779753368&amp;postID=9082610670160463245' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default/9082610670160463245'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default/9082610670160463245'/><link rel='alternate' type='text/html' href='http://leomicheloni.blogspot.com/2008/09/giles-2008-primera-versin-del-programa.html' title='Ágiles 2008 - primera versión del programa'/><author><name>Leonardo Micheloni</name><uri>http://www.blogger.com/profile/12085246040181097881</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='30' src='http://3.bp.blogspot.com/_t9Bh42Thfqo/S6TVOJqYWcI/AAAAAAAAANU/MlZc6HpYZis/S220/yo+laguito+en+col%C3%B3n.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-148524916779753368.post-8242864122870589718</id><published>2008-09-08T01:02:00.000-03:00</published><updated>2008-09-08T01:04:47.844-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='colecciones'/><category scheme='http://www.blogger.com/atom/ns#' term='c#'/><title type='text'>Hashtables, diccionarios e igualdad en las colecciones.</title><content type='html'>&lt;p&gt;
            &lt;b&gt;Hashtables, diccionarios e igualdad en las colecciones&lt;/b&gt;&lt;/p&gt;
        &lt;p&gt;
            Existen algunas colecciones que se utilizan para trabajar con elementos que 
            vamos considerar diferentes a partir de alguna característica que los 
            identifica, que los hace únicos, se llaman diccionarios, y justamente la 
            interface &lt;i&gt;IDictionary&lt;/i&gt; es la que nos permite implementar este tipo de 
            funcionalidad, veamos un poco cómo es:&lt;/p&gt;
&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
        &lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;interface&lt;/span&gt; IDictionary : ICollection, IEnumerable
{
    &lt;span class="rem"&gt;// Methods&lt;/span&gt;
    &lt;span class="kwrd"&gt;void&lt;/span&gt; Add(&lt;span class="kwrd"&gt;object&lt;/span&gt; key, &lt;span 
            class="kwrd"&gt;object&lt;/span&gt; &lt;span class="kwrd"&gt;value&lt;/span&gt;);
    &lt;span class="kwrd"&gt;void&lt;/span&gt; Clear();
    &lt;span class="kwrd"&gt;bool&lt;/span&gt; Contains(&lt;span class="kwrd"&gt;object&lt;/span&gt; key);
    IDictionaryEnumerator GetEnumerator();
    &lt;span class="kwrd"&gt;void&lt;/span&gt; Remove(&lt;span class="kwrd"&gt;object&lt;/span&gt; key);

    &lt;span class="rem"&gt;// Properties&lt;/span&gt;
    &lt;span class="kwrd"&gt;bool&lt;/span&gt; IsFixedSize { get; }
    &lt;span class="kwrd"&gt;bool&lt;/span&gt; IsReadOnly { get; }
    &lt;span class="kwrd"&gt;object&lt;/span&gt; &lt;span class="kwrd"&gt;this&lt;/span&gt;[&lt;span class="kwrd"&gt;object&lt;/span&gt; key] { get; set; }
    ICollection Keys { get; }
    ICollection Values { get; }
}
&lt;/pre&gt;
        &lt;p&gt;
            El método &lt;i&gt;Add&lt;/i&gt; nos permite agregar un elemento indicando dos cosas, &amp;quot;key&amp;quot; 
            la clave que nosotros consideramos el atributo que identifica a nuestro elemento 
            frente a otros y &amp;quot;value&amp;quot; el objeto en sí, como vemos en esta implementación 
            ambos parámetros son del tipo &lt;b&gt;object&lt;/b&gt;, dentro de &lt;i&gt;Generics &lt;/i&gt;tenemos 
            una implementación de &lt;b&gt;IDictionary &lt;/b&gt;tipificada.&lt;/p&gt;
        &lt;p&gt;
            Entonces podemos llamar al método &lt;i&gt;Contains&lt;/i&gt; y preguntar por una &amp;quot;key&amp;quot; en 
            particular y la colección nos debería contestar si existe dentro de la 
            colección.&lt;/p&gt;
        &lt;p&gt;
            &lt;b&gt;Implementación del método &lt;i&gt;GetEnumerator&lt;/i&gt;&lt;/b&gt;&lt;/p&gt;
        &lt;p&gt;
            El método GetEnumerator como vimos antes se encuentra dentro de la interface &lt;i&gt;
            IEnumerable&lt;/i&gt;, pero no en este caso, porque la interface &lt;i&gt;IDictionary&lt;/i&gt; 
            define su propio método &lt;i&gt;GetEnumerator&lt;/i&gt;, por lo tanto oculta la definición 
            de IEnumerable, ok, ¿por qué &lt;i&gt;IDictionary&lt;/i&gt; tiene su propia versión de &lt;i&gt;
            GetEnumerator&lt;/i&gt;? porque &lt;i&gt;IEnumerable&lt;/i&gt;.&lt;i&gt;GetEnumerator&lt;/i&gt; devuelve una 
            interface &lt;i&gt;IEnumerator&lt;/i&gt; que es así&lt;/p&gt;
&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
        &lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;interface&lt;/span&gt; IEnumerator
{
    &lt;span class="kwrd"&gt;bool&lt;/span&gt; MoveNext();
    &lt;span class="kwrd"&gt;object&lt;/span&gt; Current { get; }
    &lt;span class="kwrd"&gt;void&lt;/span&gt; Reset();
}&lt;/pre&gt;
        &lt;p&gt;
            El problema es que en &lt;i&gt;IDictionary &lt;/i&gt;trabajamos con objetos + un elemento 
            que los identifica (la &amp;quot;key&amp;quot;) y el método &lt;i&gt;Current &lt;/i&gt;de &lt;i&gt;IEnumerator &lt;/i&gt;
            devuelve un object, por lo tanto no nos alcanza para saber la &amp;quot;key&amp;quot; y el &amp;quot;value&amp;quot; 
            por separado (como lo ingresamos a través del método &lt;i&gt;Add&lt;/i&gt;), entonces 
            veamos qué nos devuelve la implementación de &lt;i&gt;GetEnumerator &lt;/i&gt;de &lt;i&gt;
            IDictionary&lt;/i&gt;&lt;/p&gt;
&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
        &lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;interface&lt;/span&gt; IDictionaryEnumerator : IEnumerator
{
    DictionaryEntry Entry { get; }
    &lt;span class="kwrd"&gt;object&lt;/span&gt; Key { get; }
    &lt;span class="kwrd"&gt;object&lt;/span&gt; Value { get; }
}
&lt;/pre&gt;
        &lt;p&gt;
            Vemos que hereda de &lt;i&gt;IEnumerator&lt;/i&gt; y además agrega algunas propiedades para 
            trabajar con &amp;quot;key&amp;quot; y &amp;quot;value&amp;quot; y con un tipo &lt;i&gt;DictionaryEntry&lt;/i&gt;&lt;/p&gt;
&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
        &lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;struct&lt;/span&gt; DictionaryEntry
{
    &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;object&lt;/span&gt; _key;
    &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;object&lt;/span&gt; _value;
    &lt;span class="kwrd"&gt;public&lt;/span&gt; DictionaryEntry(&lt;span class="kwrd"&gt;object&lt;/span&gt; key, &lt;span 
            class="kwrd"&gt;object&lt;/span&gt; &lt;span class="kwrd"&gt;value&lt;/span&gt;);
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;object&lt;/span&gt; Key { get; set; }
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;object&lt;/span&gt; Value { get; set; }
}

&lt;/pre&gt;
        &lt;p&gt;
            Lo mismo, &amp;quot;value&amp;quot; y &amp;quot;key&amp;quot; por separado, ahora todo cierra, bien, explicado esto 
            nos damos cuenta que podemos iterar sobre un &lt;i&gt;IDictionary&lt;/i&gt; y además 
            recuperar información de clave-valor del elemento actual así.&lt;/p&gt;
&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
        &lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;foreach&lt;/span&gt; (DictionaryEntry item &lt;span 
            class="kwrd"&gt;in&lt;/span&gt; hashTable)
{
    Console.WriteLine(item.Key);
    Console.WriteLine(item.Value);
}
&lt;/pre&gt;
        &lt;p&gt;
            &lt;b&gt;Igualdad en los diccionarios&lt;/b&gt;&lt;/p&gt;
        &lt;p&gt;
            Como dije antes los diccionarios nos aseguran tener sólo elementos diferentes 
            dentro de ella basandose para determinar qué es diferente en la &amp;quot;key&amp;quot;, bien, 
            pero esto tiene algunos detalles a tener un cuenta siempre que se trabaje con 
            diccionarios.&lt;/p&gt;
        &lt;p&gt;
            Imaginemos que tenemos esta clase&lt;/p&gt;
&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
        &lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; Persona
{
    &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; _nombre;
    &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;int&lt;/span&gt; _dni;

    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;int&lt;/span&gt; Dni
    {
        get { &lt;span class="kwrd"&gt;return&lt;/span&gt; _dni; }
        set { _dni = &lt;span class="kwrd"&gt;value&lt;/span&gt;; }
    }

    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; Nombre
    {
      get { &lt;span class="kwrd"&gt;return&lt;/span&gt; _nombre; }
      set { _nombre = &lt;span class="kwrd"&gt;value&lt;/span&gt;; }
    }
}&lt;/pre&gt;
&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
        &lt;p&gt;
            Sencilla, bien, y creamos una Hashtable y hacemos esto&lt;/p&gt;
&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
        &lt;pre class="csharpcode"&gt;Hashtable hashTable = &lt;span class="kwrd"&gt;new&lt;/span&gt; Hashtable();

Persona persona1 = &lt;span class="kwrd"&gt;new&lt;/span&gt; Persona() { Nombre = &lt;span class="str"&gt;&amp;quot;Leonardo&amp;quot;&lt;/span&gt;, Dni=123};
Persona persona2 = &lt;span class="kwrd"&gt;new&lt;/span&gt; Persona() { Nombre = &lt;span class="str"&gt;&amp;quot;Leonardo&amp;quot;&lt;/span&gt;, Dni=123};

hashTable[persona1] = persona1;
hashTable[persona2] = persona2;

Console.WriteLine(hashTable.Count);&lt;/pre&gt;
&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
        &lt;p&gt;
            Muy bien, creamos dos objetos iguales (al menos desde nuestro punto de vista) y 
            le decimos en dos ocaciones a la &lt;i&gt;Hashtable&lt;/i&gt; su valor (el mismo) sin embargo 
            cuando corremos la aplicación vemos que tenemos dos elementos dentro de la &lt;i&gt;Hashtable&lt;/i&gt;, ¿por qué?&lt;/p&gt;
        &lt;p&gt;
            &lt;b&gt;¿GetHashCode y Equals cómo funcionan en los diccionarios?&lt;/b&gt;&lt;/p&gt;
        &lt;p&gt;
            Bueno, lo que pasa es que primeramente &lt;i&gt;Hashtable &lt;/i&gt;se fija en el resultado 
            del método &lt;i&gt;GetHashCode&lt;/i&gt; de cada objeto para saber si es igual a otro, bien, 
            nosotros no dijimos cómo debe comportarse este método, pero como todos los 
            objetos (o sea todo) en .NET hereda de object éste tiene su implementación de &lt;i&gt;
            GetHashCode&lt;/i&gt; que devuelve un Hash diferente para cada instancia de object, 
            como resultado podemos crer n instancias de Personas iguales y todas van a 
            retornar un hash diferente.&lt;/p&gt;
        &lt;p&gt;
            Entonces para implementar correctamente &lt;i&gt;GetHashCode&lt;/i&gt; tenemos que pensar 
            bien, en función de nuestro dominio cuándo dos objetos de la misma clase se 
            consideran diferentes, en el caso de Persona el nombre no hace diferentes a dos 
            personas (puede haber muchos habitantes con el mismo nombre) sin embargo el Dni 
            (en Argentina es el nro de documento único) sí hace únicas a las personas, 
            entonces es un buen candidato para determinar cuándo dos objetos de la clase 
            Persona son diferentes o no.&lt;/p&gt;
&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
        &lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; Persona
{
    &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; _nombre;
    &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;int&lt;/span&gt; _dni;

    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;int&lt;/span&gt; Dni
    {
        get { &lt;span class="kwrd"&gt;return&lt;/span&gt; _dni; }
        set { _dni = &lt;span class="kwrd"&gt;value&lt;/span&gt;; }
    }

    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; Nombre
    {
        get { &lt;span class="kwrd"&gt;return&lt;/span&gt; _nombre; }
        set { _nombre = &lt;span class="kwrd"&gt;value&lt;/span&gt;; }
    }

    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;override&lt;/span&gt; &lt;span 
            class="kwrd"&gt;int&lt;/span&gt; GetHashCode()
    {
        &lt;span class="kwrd"&gt;return&lt;/span&gt; _dni.GetHashCode();
    }
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;override&lt;/span&gt; &lt;span 
            class="kwrd"&gt;bool&lt;/span&gt; Equals(&lt;span class="kwrd"&gt;object&lt;/span&gt; obj)
    {
        &lt;span class="kwrd"&gt;return&lt;/span&gt; ((Persona)obj).Dni.Equals(_dni);
    }
}&lt;/pre&gt;
        &lt;p&gt;
            Perfecto, ahora sí funciona, ya que para nosotros el Dni es la propiedad que 
            determina si dos Persona son iguales utilizamos el hash del mismo (la clase int 
            devuelve el mismo hash para dos números con el mismo valor), prestemos atención 
            que también he sobre-escrito el método Equals porque la Hashtable lo consulta en 
            caso de que el resultado de GetHashCode sea igual, por lo tanto, sino lo 
            sobre-escribimos tampoco va a considerar ambos elementos iguales.&lt;/p&gt;
        &lt;p&gt;
            &lt;b&gt;La interfece IEqualityComparer&lt;/b&gt;&lt;/p&gt;
        &lt;p&gt;
            Hay otra forma de indicar a la &lt;i&gt;Hashtable&lt;/i&gt; cómo determinar si dos elementos 
            son iguales, esto es especialmente útil si nos encontramos con una condición de 
            igualdad particular (ya que si suministramos &lt;i&gt;IEqualityComparer&lt;/i&gt; la &lt;i&gt;
            Hashtable&lt;/i&gt; no va&amp;nbsp; a llamar a los métodos &lt;i&gt;GetHashCode&lt;/i&gt; y &lt;i&gt;Equals&lt;/i&gt; 
            de los objetos) o si no queremos o podemos implementar &lt;i&gt;GetHashCode&lt;/i&gt; y &lt;i&gt;
            Equals&lt;/i&gt; en la clase, veamos su firma.&lt;/p&gt;
&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
        &lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;interface&lt;/span&gt; IEqualityComparer
{
    &lt;span class="kwrd"&gt;bool&lt;/span&gt; Equals(&lt;span class="kwrd"&gt;object&lt;/span&gt; x, &lt;span 
            class="kwrd"&gt;object&lt;/span&gt; y);
    &lt;span class="kwrd"&gt;int&lt;/span&gt; GetHashCode(&lt;span class="kwrd"&gt;object&lt;/span&gt; obj);
}
&lt;/pre&gt;
        &lt;p&gt;
            La idea es como vemos hacer lo mismo (definir GetHashCode y Equals) pero en otra 
            clase y pasársela a la Hashtable, entonces para el ejemplo anterior la cosa 
            sería así&lt;/p&gt;
&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
        &lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; ComparadorPersonas : IEqualityComparer
{
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;int&lt;/span&gt; GetHashCode(&lt;span 
            class="kwrd"&gt;object&lt;/span&gt; obj)
    {
        &lt;span class="kwrd"&gt;return&lt;/span&gt; ((Persona)obj).Dni.GetHashCode();
    }

    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;new&lt;/span&gt; &lt;span class="kwrd"&gt;bool&lt;/span&gt; Equals(&lt;span 
            class="kwrd"&gt;object&lt;/span&gt; x, &lt;span class="kwrd"&gt;object&lt;/span&gt; y)
    {
        &lt;span class="kwrd"&gt;return&lt;/span&gt; ((Persona)x).Dni.Equals(((Persona)y).Dni);
    }
}
&lt;/pre&gt;
        &lt;p&gt;
            Y se utiliza así&lt;/p&gt;
&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
        &lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Test()
{
    Hashtable hashTable = &lt;span class="kwrd"&gt;new&lt;/span&gt; Hashtable(&lt;span class="kwrd"&gt;new&lt;/span&gt; ComparadorPersonas());

    Persona persona1 = &lt;span class="kwrd"&gt;new&lt;/span&gt; Persona() { Nombre = &lt;span 
            class="str"&gt;&amp;quot;Leonardo&amp;quot;&lt;/span&gt;, Dni = 123 };
    Persona persona2 = &lt;span class="kwrd"&gt;new&lt;/span&gt; Persona() { Nombre = &lt;span 
            class="str"&gt;&amp;quot;Leonardo&amp;quot;&lt;/span&gt;, Dni = 123 };

    hashTable[persona1] = persona1;
    hashTable[persona2] = persona2;

    Console.WriteLine(hashTable.Count);
}&lt;/pre&gt;
        &lt;p&gt;
            Y listo, funciona.&lt;/p&gt;
        &lt;p&gt;
            &lt;b&gt;Conclusión&lt;/b&gt;&lt;/p&gt;
        &lt;p&gt;
            Los diccionarios nos permite manipular una lista de elementos únicos, utiliza 
            una propiedad &amp;quot;key&amp;quot; para identificar los elementos. Es muy importante 
            implementar correctamente los métodos &lt;i&gt;GetHashCode&lt;/i&gt; y &lt;i&gt;Equals&lt;/i&gt; para 
            que la &lt;i&gt;Hashtable&lt;/i&gt; pueda controlar la repetición de los elementos. Podemos 
            utilizar la interface IEqualityComparer para realizar comparaciones 
            personalizadas o por fuera de la clase. Hasta la próxima.&lt;/p&gt;
        &lt;p&gt;
            &lt;b&gt;Referencias&lt;/b&gt;&lt;/p&gt;
        &lt;p&gt;
            &lt;a href="http://msdn.microsoft.com/es-es/library/system.collections.idictionary(VS.80).aspx"&gt;
            Interface IDictionary (MSDN)&lt;/a&gt;&lt;/p&gt;
        &lt;p&gt;
            &lt;a href="http://msdn.microsoft.com/es-es/library/system.collections.hashtable(VS.80).aspx"&gt;
            Hashtabls (MSDN)&lt;/a&gt;&lt;/p&gt;
        &lt;p&gt;
            &amp;nbsp;&lt;/p&gt;
        &lt;p&gt;
            &amp;nbsp;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;Leonardo Micheloni&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/148524916779753368-8242864122870589718?l=leomicheloni.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://leomicheloni.blogspot.com/feeds/8242864122870589718/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=148524916779753368&amp;postID=8242864122870589718' title='2 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default/8242864122870589718'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default/8242864122870589718'/><link rel='alternate' type='text/html' href='http://leomicheloni.blogspot.com/2008/09/hashtables-diccionarios-e-igualdad-en.html' title='Hashtables, diccionarios e igualdad en las colecciones.'/><author><name>Leonardo Micheloni</name><uri>http://www.blogger.com/profile/12085246040181097881</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='30' src='http://3.bp.blogspot.com/_t9Bh42Thfqo/S6TVOJqYWcI/AAAAAAAAANU/MlZc6HpYZis/S220/yo+laguito+en+col%C3%B3n.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-148524916779753368.post-5834669626218375777</id><published>2008-09-06T17:05:00.001-03:00</published><updated>2008-09-06T17:09:56.443-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='agiles2008'/><title type='text'>Jornadas Ágiles 2008 - Inscríbase ahora!</title><content type='html'>&lt;p&gt;
&amp;nbsp;Está abierta la inscripción a las Jornadas Ágiles 2008, a realizarse los días 22 y 
        23 de Octubre de 2008 en el Hotel Bauen, Buenos Aires, Argentina. Ágiles 2008 es 
        una excelente oportunidad para encontrarse con profesionales de IT de la región, 
        interesados en compartir sus experiencias, debatir y capacitarse en temas 
        relacionados con el desarrollo de software a través del uso de metodologías 
        ágiles.&lt;/p&gt;
    &lt;p&gt;
&amp;nbsp;Entre los invitados internacionales que participarán en Ágiles 2008 se encuentran 
        Matt Gelbwaks, Tobias Mayer, Dave Nicolette y los keynote speakers del evento, 
        Mary y Tom Poppendieck.&lt;/p&gt;
    &lt;p&gt;
&amp;nbsp;El programa incluirá distintos tipos de actividades: presentaciones, sesiones 
        interactivas, talleres y espacios abiertos de debate. Las jornadas son gratuitas 
        pero es necesario registrarse para reservar un lugar.&lt;/p&gt;
    &lt;p&gt;
&amp;nbsp;El formulario de inscripción está en
        &lt;a href="http://www.agiles2008.org/es/registracion.php"&gt;
        http://www.agiles2008.org/es/registracion.php&lt;/a&gt;&lt;/p&gt;
    &lt;p&gt;
&amp;nbsp;Más información relacionada con el evento, el hotel y el programa en
        &lt;a href="http://www.agiles2008.org"&gt;www.agiles2008.org&lt;/a&gt;&lt;/p&gt;
    &lt;p&gt;
&amp;nbsp;Cualquier inquietud, envíenos un mail a &lt;a href="mailto:info@agiles2008.org"&gt;
        info@agiles2008.org&lt;/a&gt;&lt;/p&gt;
    &lt;p&gt;
&amp;nbsp;Comité Organizador Ágiles 2008 &lt;a href="http://www.agiles2008.org"&gt;
        www.agiles2008.org&lt;/a&gt;&lt;/p&gt;
    &lt;p&gt;
&amp;nbsp;[Platinum Sponsors] Intel, Sabre Holding
    &lt;/p&gt;
    &lt;p&gt;
        [Gold Sponsors] Three Melons, VersionOne, Microsoft
    &lt;/p&gt;
    &lt;p&gt;
        [Silver Sponsor] Baufest, Hexacta, Liveware
    &lt;/p&gt;
    &lt;p&gt;
        [Institucionales] Scrum Alliance, IEEE, SADIO, Agile Alliance, Polo Tecnológico 
        Rosario, Córdoba Technology, Cessi Argentina&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;Leonardo Micheloni&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/148524916779753368-5834669626218375777?l=leomicheloni.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://leomicheloni.blogspot.com/feeds/5834669626218375777/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=148524916779753368&amp;postID=5834669626218375777' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default/5834669626218375777'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default/5834669626218375777'/><link rel='alternate' type='text/html' href='http://leomicheloni.blogspot.com/2008/09/jornadas-giles-2008-inscrbase-ahora.html' title='Jornadas Ágiles 2008 - Inscríbase ahora!'/><author><name>Leonardo Micheloni</name><uri>http://www.blogger.com/profile/12085246040181097881</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='30' src='http://3.bp.blogspot.com/_t9Bh42Thfqo/S6TVOJqYWcI/AAAAAAAAANU/MlZc6HpYZis/S220/yo+laguito+en+col%C3%B3n.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-148524916779753368.post-1332292136801314277</id><published>2008-08-28T21:52:00.000-03:00</published><updated>2008-08-28T21:53:01.049-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='colecciones'/><category scheme='http://www.blogger.com/atom/ns#' term='c#'/><title type='text'>IList la interface de escritura</title><content type='html'>&lt;p&gt;
            &lt;b&gt;IList la interface de escritura&lt;/b&gt;&lt;/p&gt;
        &lt;p&gt;
            En el post anterior hablé acerca de IEnumerable, una linda interface que está en 
            toda colección que se precie de serlo posee, pero que no nos deja más que leer, 
            si lo que necesitamos es poder escribir la interface es IList, vamos a ver su 
            firma&lt;/p&gt;
&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
        &lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;interface&lt;/span&gt; IList : ICollection, IEnumerable
{
    &lt;span class="kwrd"&gt;int&lt;/span&gt; Add(&lt;span class="kwrd"&gt;object&lt;/span&gt; &lt;span 
            class="kwrd"&gt;value&lt;/span&gt;);
    &lt;span class="kwrd"&gt;void&lt;/span&gt; Clear();
    &lt;span class="kwrd"&gt;bool&lt;/span&gt; Contains(&lt;span class="kwrd"&gt;object&lt;/span&gt; &lt;span 
            class="kwrd"&gt;value&lt;/span&gt;);
    &lt;span class="kwrd"&gt;int&lt;/span&gt; IndexOf(&lt;span class="kwrd"&gt;object&lt;/span&gt; &lt;span 
            class="kwrd"&gt;value&lt;/span&gt;);
    &lt;span class="kwrd"&gt;void&lt;/span&gt; Insert(&lt;span class="kwrd"&gt;int&lt;/span&gt; index, &lt;span 
            class="kwrd"&gt;object&lt;/span&gt; &lt;span class="kwrd"&gt;value&lt;/span&gt;);
    &lt;span class="kwrd"&gt;void&lt;/span&gt; Remove(&lt;span class="kwrd"&gt;object&lt;/span&gt; &lt;span 
            class="kwrd"&gt;value&lt;/span&gt;);
    &lt;span class="kwrd"&gt;void&lt;/span&gt; RemoveAt(&lt;span class="kwrd"&gt;int&lt;/span&gt; index);

    &lt;span class="kwrd"&gt;bool&lt;/span&gt; IsFixedSize { get; }
    &lt;span class="kwrd"&gt;bool&lt;/span&gt; IsReadOnly { get; }
    &lt;span class="kwrd"&gt;object&lt;/span&gt; &lt;span class="kwrd"&gt;this&lt;/span&gt;[&lt;span class="kwrd"&gt;int&lt;/span&gt; index] { get; set; }
}&lt;/pre&gt;
        &lt;p&gt;
            Como vemos IList implementa IEnumerable o sea que la podemos iterar con foreach, 
            y también implementa ICollection, veámos de qué se trata:&lt;/p&gt;
&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
        &lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;interface&lt;/span&gt; ICollection : IEnumerable
{
    &lt;span class="kwrd"&gt;void&lt;/span&gt; CopyTo(Array array, &lt;span class="kwrd"&gt;int&lt;/span&gt; index);

    &lt;span class="kwrd"&gt;int&lt;/span&gt; Count { get; }
    &lt;span class="kwrd"&gt;bool&lt;/span&gt; IsSynchronized { get; }
    &lt;span class="kwrd"&gt;object&lt;/span&gt; SyncRoot { get; }
}&lt;/pre&gt;
        &lt;p&gt;
            &lt;b&gt;ICollection para qué sirve?&lt;/b&gt;&lt;/p&gt;
        &lt;p&gt;
            Esta interface tiene métodos para iterar y sincronizar, los métodos para iterar 
            los hereda de IEnumerable y ya los conocemos, vamos a detenernos en los otros&lt;/p&gt;
        &lt;p&gt;
            &lt;b&gt;CopyTo: &lt;/b&gt;sirve para copiar el contenido de la clase que implementa ICollection al 
            Array que se pasa como parámetro a partir de la posición del Array que se indica 
            en index&lt;/p&gt;
        &lt;p&gt;
            &lt;b&gt;IsSynchonized:&lt;/b&gt; indica si la colección se encuentra implementado &amp;quot;Threat safe&amp;quot;&lt;/p&gt;
        &lt;p&gt;
            &lt;b&gt;SyncRoot:&lt;/b&gt; devuelve un objeto para sincronizar la colección en un ambiente multi 
            hilo, para hacer un lock&lt;/p&gt;
        &lt;p&gt;
            Ahora sí, IList&lt;/p&gt;
        &lt;p&gt;
            IList tiene los métodos necesarios para poder agregar elementos, verificar que 
            existan, la posición de un elemento determinado, etc.&lt;/p&gt;
        &lt;p&gt;
            &lt;b&gt;Dónde encontramos IList?&lt;/b&gt;&lt;/p&gt;
        &lt;p&gt;
            La implementación más sencilla de IList se encuentra en la clase ArrayList, por 
            lo tanto podemos concluir que ArrayList es la colección más sencilla que podemos 
            utilizar y que seguramente vamos a utilizar con mayor frecuencia (esto es un 
            poco mentira por generics pero eso lo vamos a ver más adelante)&lt;/p&gt;
        &lt;p&gt;
            ArrayList también implementa mucho métodos que no pertenecen a ninguna 
            interface, algunos muy interesantes son&lt;/p&gt;
        &lt;p&gt;
            &lt;b&gt;Sort:&lt;/b&gt; para ordenar la lista, con un IComparer por defecto y una sobrecarga para 
            suministrarle uno propio.&lt;/p&gt;
        &lt;p&gt;
            &lt;b&gt;BinarySearch:&lt;/b&gt; para búsqueda binaria, es decir, busca de a mitades.&lt;/p&gt;
            
 
     &lt;p&gt;
            &lt;b&gt;ConvertAll:&lt;/b&gt; permite convertir todos los elemento de un tipo a otro, el 
            converter se lo suministramos nosotros&lt;/p&gt;
        &lt;p&gt;
            El resto de los métodos son bastante autodescriptivos, hasta la próxima.&lt;/p&gt;
        &lt;p&gt;
            &amp;nbsp;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;Leonardo Micheloni&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/148524916779753368-1332292136801314277?l=leomicheloni.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://leomicheloni.blogspot.com/feeds/1332292136801314277/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=148524916779753368&amp;postID=1332292136801314277' title='2 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default/1332292136801314277'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default/1332292136801314277'/><link rel='alternate' type='text/html' href='http://leomicheloni.blogspot.com/2008/08/ilist-la-interface-de-escritura.html' title='IList la interface de escritura'/><author><name>Leonardo Micheloni</name><uri>http://www.blogger.com/profile/12085246040181097881</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='30' src='http://3.bp.blogspot.com/_t9Bh42Thfqo/S6TVOJqYWcI/AAAAAAAAANU/MlZc6HpYZis/S220/yo+laguito+en+col%C3%B3n.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-148524916779753368.post-8980865110464351273</id><published>2008-08-28T19:51:00.000-03:00</published><updated>2008-08-28T19:52:21.642-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Visual Studio'/><title type='text'>Error 1935.An error occurred during the installation of assembly - HRESULT: 0x80070020</title><content type='html'>&lt;p&gt;
            Error 1935.An error occurred during the installation of assembly&lt;/p&gt;
        &lt;p&gt;
            Estaba yo intentando instalar el Visual Studio 2008 porque lo había quitado de 
            mí máquina por motivos que no vienen al caso y me encontré con el siguiente 
            error &amp;quot;Error 1935.An error occurred during the installation of assembly....&amp;quot; y 
            el nombre de un aseembly y a continuación &amp;quot;HRESULT: 0x80070020&amp;quot;, esto no hubiera 
            sido tan grave sino fuera porque me apareción casi al final de la instalación 
            que no es de las más cortas que he visto, y además a continuación le llevó más 
            tiempo hacer el rollback, pero bueno, el mayor problema es que no tenía idea de 
            qué pasaba, luego de &amp;quot;bucear&amp;quot; por Intenet llegué a la conclusión que se trataba 
            de un error al intentar registrar una DLL (porque por supuesto intenté otra vez 
            y pasó lo mismo con otro nombre de DLL) entre muchos consejos se encontraban 
            desactivar los AdAware, los Antivirus, etc. eso no hubiera sido raro sino fuera 
            porque no tengo nada de eso en la máquina, en fin, seguí buscando y encontré la 
            solución....desactivar todos los servicios que no sean de Microsoft, entonces 
            fui a ejecutar &amp;quot;msconfig&amp;quot; desactivé Procesar Archivo SYSTEM.INI y CARGAR 
            ELEMENTO DE INICIO, luego fui a la solapa de servicio y seleccioné &amp;quot;Ocultar 
            todos los servicios de Microsoft&amp;quot;, desactivé todo lo que quedó, reinicié la 
            máquina y santo remedio, pude instalar, pero no sin quedarme con la duda de qué 
            pasaba.&lt;/p&gt;
        &lt;p&gt;
            Lo importante es el HRESULT&lt;/p&gt;
        &lt;p&gt;
            Lo importante para encontrar la solución fue el HRESULT del error, por supuesto 
            que no lo anoté, para encontrarlo fui al directoril temporal de mi usuario 
            &amp;quot;ejecutar-&amp;gt;%temp%&amp;quot; y busqué un archivo txt con un nombre del estilo err_vs_algo 
            y ahí estaba la información, porque el error 1935 es muy genérico en realidad, 
            lo que importa, como dije antes es el HRESULT.         &lt;/p&gt;
        &lt;p&gt;
            Saludos.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;Leonardo Micheloni&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/148524916779753368-8980865110464351273?l=leomicheloni.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://leomicheloni.blogspot.com/feeds/8980865110464351273/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=148524916779753368&amp;postID=8980865110464351273' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default/8980865110464351273'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default/8980865110464351273'/><link rel='alternate' type='text/html' href='http://leomicheloni.blogspot.com/2008/08/error-1935an-error-occurred-during.html' title='Error 1935.An error occurred during the installation of assembly - HRESULT: 0x80070020'/><author><name>Leonardo Micheloni</name><uri>http://www.blogger.com/profile/12085246040181097881</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='30' src='http://3.bp.blogspot.com/_t9Bh42Thfqo/S6TVOJqYWcI/AAAAAAAAANU/MlZc6HpYZis/S220/yo+laguito+en+col%C3%B3n.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-148524916779753368.post-1987778056579691258</id><published>2008-08-28T16:51:00.003-03:00</published><updated>2008-08-28T21:53:37.314-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='colecciones'/><category scheme='http://www.blogger.com/atom/ns#' term='c#'/><title type='text'>Colecciones en .NET, IEnumerator, IEnumerable.</title><content type='html'>&lt;p&gt;
            &lt;a href="http://2.bp.blogspot.com/_t9Bh42Thfqo/SLcB55gR5-I/AAAAAAAAAGw/rIjl7gqyXrw/s1600-h/Collectionsinvertida.png" 
                onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"&gt;
            &lt;img id="BLOGGER_PHOTO_ID_5239658785669244898" alt="" border="0" 
                src="http://2.bp.blogspot.com/_t9Bh42Thfqo/SLcB55gR5-I/AAAAAAAAAGw/rIjl7gqyXrw/s320/Collectionsinvertida.png" 
                style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" /&gt;&lt;/a&gt;&lt;/p&gt;
        &lt;p&gt;
            &amp;nbsp;&lt;/p&gt;
        &lt;p&gt;
            Las colecciones son uno de los recursos más utilizados (sino el más) dentro del 
            mundo de .net, es importante comprender bien su funcionamiento y su potencial, 
            ya que una decisión correcta nos puede facilitar mucho el trabajo y hasta tener 
            impácto en el rendimiento de nuestra aplicación.&lt;/p&gt;
    &lt;p&gt;
        En .net 2.0 existen tres tipos de colecciones:&lt;/p&gt;
    &lt;ul&gt;
        &lt;li&gt;Colecciones normales     &lt;/li&gt;
        &lt;li&gt;Colecciones especializadas
    &lt;/li&gt;
        &lt;li&gt;Coleccioner genéricas
    &lt;/li&gt;
&lt;/ul&gt;
    &lt;p&gt;
        Vamos a comenzar por el principio, por las colecciones normales, y para ser más 
        básico aún vamos a ver la interface que todos usan.&lt;/p&gt;
    &lt;p&gt;
        &lt;b&gt;Con ustedes IEnumerator&lt;/b&gt;&lt;/p&gt;
    &lt;p&gt;
&amp;nbsp;Esta interface está hasta en la sopa, todas las colecciones de .net la utilizan y 
        es importante comprender cómo funciona, el bucle foreach (uno de los más grandes 
        inventos de la época) también y la interface IEnumerable&lt;T&gt;  la base de Linq, 
        entonces vamos a analizarla
    &lt;/p&gt;
    &lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
&lt;pre class="csharpcode"&gt;
&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;interface&lt;/span&gt; IEnumerator
{
    &lt;span class="kwrd"&gt;object&lt;/span&gt; Current { get; }
    &lt;span class="kwrd"&gt;bool&lt;/span&gt; MoveNext();
    &lt;span class="kwrd"&gt;void&lt;/span&gt; Reset();
}&lt;/pre&gt;
    &lt;p&gt;
        La idea es que la clase que implemente IEnumerator posee una conjunto de 
        elemento de un tipo (una lista, un array, un vector) y los métodos de 
        IEnumerator me permite acceder a esta lista de una manera estándar.     &lt;/p&gt;
    &lt;ul&gt;
        &lt;li&gt;&lt;b&gt;Current:&lt;/b&gt; esta propiedad devuelve el elemento actual donde se encuentra 
        apuntada la lista, es decir, sila lista tiene 10 elemento por convensión el 
        método Current nos devuelve el primer elemento.&lt;/li&gt;
        &lt;li&gt;&amp;nbsp;&lt;b&gt;MoveNext:&lt;/b&gt; Con este método le decimos a la clase que lo implementa que mueva su 
        posición al siguiente elemento en su lista, es decir, si actualmente está en el 
        elemento 5 luego de ejecutar MoveNext deberá pasar al 6 y devolverá true, siempre 
        y cuando el 6 exista, en caso de no existir el elemento 6 no se moverá y 
        devolverá false, en lugar de true. Con este método podemos poner un bucle while 
        por ejemplo y movernos por toda la lista.&lt;/li&gt;
        &lt;li&gt;&amp;nbsp;&lt;b&gt;Reset:&lt;/b&gt; pone al principio la posición actual de la lista. &lt;/li&gt;
        &lt;/ul&gt;
        
        &lt;p&gt;Se va la segunda 
        IEnumerable &lt;/p&gt;
&lt;p&gt;IEnumerator no sirve de mucho sin su fiel aliado, IEnumerable, esta 
        interface es muy sencilla y no hace más que devolver en su único método la 
        interface IEnumerator, veamos su firma&lt;/p&gt;
    

    
&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
    &lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;interface&lt;/span&gt; IEnumerable 
{ 
    IEnumerator GetEnumerator(); 
}
&lt;/pre&gt;
    &lt;p&gt;
&amp;nbsp;Exáctamente esto es lo que tenemos que implementar si queremos que una clase 
        nuestra se pueda iterar con un bucle foreach, vamos a ver un pequeño ejemplo.&lt;/p&gt;
&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
    &lt;pre class="csharpcode"&gt;[TestFixture]
&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; Class1
{
    [Test]
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; ProbarLista()
    {
        ContenedorLista lista = &lt;span class="kwrd"&gt;new&lt;/span&gt; ContenedorLista(&lt;span 
        class="kwrd"&gt;new&lt;/span&gt; &lt;span class="kwrd"&gt;object&lt;/span&gt;[]{1,2,3,4,5,6,7,8,9,0});

        &lt;span class="kwrd"&gt;foreach&lt;/span&gt; (&lt;span class="kwrd"&gt;int&lt;/span&gt; nro &lt;span 
        class="kwrd"&gt;in&lt;/span&gt; lista)
        {
            NUnit.Core.TestContext.Out.WriteLine(nro);
        }

        Console.ReadLine();
    }
}
&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; ContenedorLista: IEnumerable
{
    IEnumerator _istaPropia;

    &lt;span class="kwrd"&gt;public&lt;/span&gt; ContenedorLista(&lt;span class="kwrd"&gt;object&lt;/span&gt;[] lista)
    {
        _istaPropia = &lt;span class="kwrd"&gt;new&lt;/span&gt; ListaPropia(lista);
    }

    &lt;span class="kwrd"&gt;public&lt;/span&gt; IEnumerator GetEnumerator()
    {
        &lt;span class="kwrd"&gt;return&lt;/span&gt; _istaPropia;
    }
}

&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; ListaPropia : IEnumerator
{
    &lt;span class="kwrd"&gt;object&lt;/span&gt;[] _lista;
    &lt;span class="kwrd"&gt;int&lt;/span&gt; _posicion;

    &lt;span class="kwrd"&gt;public&lt;/span&gt; ListaPropia(&lt;span class="kwrd"&gt;object&lt;/span&gt;[] lista)
    {
        _lista = lista;
        &lt;span class="kwrd"&gt;this&lt;/span&gt;.Reset();
    }

    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;object&lt;/span&gt; Current 
    {
        get 
        {
            &lt;span class="kwrd"&gt;return&lt;/span&gt; _lista[_posicion];
        }
    }

    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;bool&lt;/span&gt; MoveNext()
    {
        &lt;span class="kwrd"&gt;if&lt;/span&gt; (++_posicion &amp;lt; _lista.Length)
        {
            &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;true&lt;/span&gt;;
        }
        &lt;span class="kwrd"&gt;else&lt;/span&gt;
        {
            &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;false&lt;/span&gt;;
        }
    }

    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Reset()
    {
        _posicion = -1;
    }
}&lt;/pre&gt;
    &lt;p&gt;
        Mágico sin duda, bueno por ahora esta primer entrega sobre colecciones termina, 
        la próxima vamos a ver otras interfaces, saludos.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;Leonardo Micheloni&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/148524916779753368-1987778056579691258?l=leomicheloni.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://leomicheloni.blogspot.com/feeds/1987778056579691258/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=148524916779753368&amp;postID=1987778056579691258' title='10 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default/1987778056579691258'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default/1987778056579691258'/><link rel='alternate' type='text/html' href='http://leomicheloni.blogspot.com/2008/08/colecciones-en-net-ienumerator.html' title='Colecciones en .NET, IEnumerator, IEnumerable.'/><author><name>Leonardo Micheloni</name><uri>http://www.blogger.com/profile/12085246040181097881</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='30' src='http://3.bp.blogspot.com/_t9Bh42Thfqo/S6TVOJqYWcI/AAAAAAAAANU/MlZc6HpYZis/S220/yo+laguito+en+col%C3%B3n.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_t9Bh42Thfqo/SLcB55gR5-I/AAAAAAAAAGw/rIjl7gqyXrw/s72-c/Collectionsinvertida.png' height='72' width='72'/><thr:total>10</thr:total></entry><entry><id>tag:blogger.com,1999:blog-148524916779753368.post-4133823894743465944</id><published>2008-08-25T12:55:00.000-03:00</published><updated>2008-08-25T12:56:31.146-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='mock'/><category scheme='http://www.blogger.com/atom/ns#' term='unit test'/><title type='text'>¿Cuándo utilizar MockObjects?</title><content type='html'>&lt;strong&gt;
    ¿Cuándo utilizar MockObjects?&lt;/strong&gt;&lt;br /&gt;
    &lt;br /&gt;
    Los mock objects con mágicos, nos permiten evitar un montón de problemas en nuestras
    pruebas y mejorar mucho su calidad, pero no hay que usarlos siempre, leyendo un
    libro me encontré con algunos tips sobre cuándo utlizarlos:&lt;br /&gt;
    &lt;br /&gt;
    &lt;br /&gt;
    &lt;ul&gt;
    &lt;li&gt;El objeto real tiene un comportamiento no-determinístico (produce resultados impredecibles).&lt;/li&gt;
    &lt;li&gt;El objeto real es difícil de configurar, como el sistema de archivos, la base de datos o una red&lt;/li&gt;    
    &lt;li&gt;El objeto real tiene un comportamiento que es difícil de disparar (por ejemplo un error de red).&lt;/li&gt;
    &lt;li&gt;El objeto real el lento.&lt;/li&gt;
    &lt;li&gt;El objeto real tiene (o es) una interfaz de usuario.&lt;/li&gt;
    &lt;li&gt;La prueba necesita saber cómo son utilizados los objetos (por ejemplo se necesita saber si una función callback ha sido llamada).&lt;/li&gt;
    &lt;li&gt;El objeto real no existe aún (un problema común cuando se interactúa con otros equipos o con nuevos sistema de hardware).&lt;/li&gt;
        &lt;/ul&gt;
        &lt;br /&gt;
    Referncia: Tim Mackinnon, Steve Freeman, and Philip Craig. Endo-testing: Unit testing
    with mock objects.&lt;br /&gt;
    &lt;br /&gt;
    Hasta la próxima.&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;Leonardo Micheloni&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/148524916779753368-4133823894743465944?l=leomicheloni.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://leomicheloni.blogspot.com/feeds/4133823894743465944/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=148524916779753368&amp;postID=4133823894743465944' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default/4133823894743465944'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default/4133823894743465944'/><link rel='alternate' type='text/html' href='http://leomicheloni.blogspot.com/2008/08/cundo-utilizar-mockobjects.html' title='¿Cuándo utilizar MockObjects?'/><author><name>Leonardo Micheloni</name><uri>http://www.blogger.com/profile/12085246040181097881</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='30' src='http://3.bp.blogspot.com/_t9Bh42Thfqo/S6TVOJqYWcI/AAAAAAAAANU/MlZc6HpYZis/S220/yo+laguito+en+col%C3%B3n.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-148524916779753368.post-7591681648561910782</id><published>2008-08-22T21:20:00.003-03:00</published><updated>2008-08-22T21:24:23.715-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='dce'/><title type='text'>Soy desarrollador Gold</title><content type='html'>&lt;p&gt;Desarrollador Gold&lt;/p&gt;
&lt;p&gt;Sí, después de tener un poco abandonado el tema del &lt;a href="http://www.dce2005.com"&gt;DCE&lt;/a&gt; me puse las pilas como se dice en Argentina y rendí los exámenes que me faltaban para ser &lt;b&gt;desarrollador gold&lt;/b&gt;, ahora a ver qué pasa con la estrella platinium.&lt;/p&gt;
&lt;a href="http://4.bp.blogspot.com/_t9Bh42Thfqo/SK9YaQJFY9I/AAAAAAAAAGo/F9tah5ZBHb8/s1600-h/gold1.gif"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://4.bp.blogspot.com/_t9Bh42Thfqo/SK9YaQJFY9I/AAAAAAAAAGo/F9tah5ZBHb8/s320/gold1.gif" border="0" alt=""id="BLOGGER_PHOTO_ID_5237502099688088530" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;Leonardo Micheloni&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/148524916779753368-7591681648561910782?l=leomicheloni.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://leomicheloni.blogspot.com/feeds/7591681648561910782/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=148524916779753368&amp;postID=7591681648561910782' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default/7591681648561910782'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default/7591681648561910782'/><link rel='alternate' type='text/html' href='http://leomicheloni.blogspot.com/2008/08/desarrollador-gold-s-despus-de-tener-un.html' title='Soy desarrollador Gold'/><author><name>Leonardo Micheloni</name><uri>http://www.blogger.com/profile/12085246040181097881</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='30' src='http://3.bp.blogspot.com/_t9Bh42Thfqo/S6TVOJqYWcI/AAAAAAAAANU/MlZc6HpYZis/S220/yo+laguito+en+col%C3%B3n.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_t9Bh42Thfqo/SK9YaQJFY9I/AAAAAAAAAGo/F9tah5ZBHb8/s72-c/gold1.gif' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-148524916779753368.post-3565430761500380109</id><published>2008-08-15T20:49:00.005-03:00</published><updated>2008-08-15T21:00:35.649-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='sharepoint'/><title type='text'>Nuevo Blog sobre Sharepoint Services desde cero</title><content type='html'>&lt;table cellpading="10" border="0"&gt;
&lt;tr&gt;
&lt;td&gt;Recién salido del horno, un nuevo blog sobre sharepoint en donde la autora irá compartiendo sus experiencias (el camino hacia la certificación) con los lectores, el tema, obviamente
    Sharepoint services 3, en el primer post &lt;a href="http://sharepoint-puntodeencuentro.blogspot.com/2008/08/instalando-windows-sharepoint-services.html"&gt;
        Paula nos muestra cómo instalar WSS3&lt;/a&gt; desde cero y crear nuestro primer site collection. Disfrútenlo.&amp;nbsp;&lt;br /&gt;
    &lt;br /&gt;
    Blog: &lt;a href="http://sharepoint-puntodeencuentro.blogspot.com/"&gt;Punto de encuentro&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;&lt;div class="blogger-post-footer"&gt;Leonardo Micheloni&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/148524916779753368-3565430761500380109?l=leomicheloni.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://leomicheloni.blogspot.com/feeds/3565430761500380109/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=148524916779753368&amp;postID=3565430761500380109' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default/3565430761500380109'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default/3565430761500380109'/><link rel='alternate' type='text/html' href='http://leomicheloni.blogspot.com/2008/08/nuevo-blog-sobre-sharepoint-services.html' title='Nuevo Blog sobre Sharepoint Services desde cero'/><author><name>Leonardo Micheloni</name><uri>http://www.blogger.com/profile/12085246040181097881</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='30' src='http://3.bp.blogspot.com/_t9Bh42Thfqo/S6TVOJqYWcI/AAAAAAAAANU/MlZc6HpYZis/S220/yo+laguito+en+col%C3%B3n.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-148524916779753368.post-7772251064740977755</id><published>2008-08-11T12:59:00.001-03:00</published><updated>2008-08-11T13:00:32.780-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='expresiones lambda'/><category scheme='http://www.blogger.com/atom/ns#' term='C# 3.0'/><category scheme='http://www.blogger.com/atom/ns#' term='LINQ'/><title type='text'>Utilizando expresiones Lambda para facilitar la creación de métodos anónimos</title><content type='html'>&lt;p&gt;
        Utilizando las expresiones lambda para facilitar algunos trabajos molestos&lt;/p&gt;
    &lt;p&gt;
        Más de una vez nos encontramos con la necesidad de ordenar una lista tipada (o 
        sea una lista generica) y es necesario implementar IComparer&amp;lt;T&amp;gt;, no es que sea 
        para mucho, es sólo un método como vemos en su definición&lt;/p&gt;
    &lt;p&gt;
        &amp;nbsp;&lt;/p&gt;
        &lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
&lt;pre class="csharpcode"&gt;
&lt;span class="kwrd"&gt;using&lt;/span&gt; System;

&lt;span class="kwrd"&gt;namespace&lt;/span&gt; System.Collections.Generic
{
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;interface&lt;/span&gt; IComparer&amp;lt;T&amp;gt;
    {
        &lt;span class="kwrd"&gt;int&lt;/span&gt; Compare(T x, T y);
    }
}&lt;/pre&gt;



&lt;p&gt;
    pero más de una vez no tenemos ganas de crear una clase para esto o 
    implementarla en una existente, bueno, para evitar hacer esto podemos utilizar 
    un delegado y valernos de la inferencia de tipos de C# del siguiente modo&lt;/p&gt;
&lt;p&gt;
    &amp;nbsp;&lt;/p&gt;

&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
&lt;pre class="csharpcode"&gt;
&lt;span class="kwrd"&gt;using&lt;/span&gt; System;
&lt;span class="kwrd"&gt;using&lt;/span&gt; System.Collections.Generic;
&lt;span class="kwrd"&gt;using&lt;/span&gt; System.Linq;
&lt;span class="kwrd"&gt;using&lt;/span&gt; System.Text;

&lt;span class="kwrd"&gt;namespace&lt;/span&gt; ConsoleApplication10
{
    &lt;span class="kwrd"&gt;class&lt;/span&gt; Program
    {
        &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Main(&lt;span class="kwrd"&gt;string&lt;/span&gt;[] args)
        {
            &lt;span class="kwrd"&gt;new&lt;/span&gt; Program().Prueba();
            Console.ReadLine();
        }

        &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Prueba()
        {
            List&amp;lt;Persona&amp;gt; personas = &lt;span class="kwrd"&gt;new&lt;/span&gt; List&amp;lt;Persona&amp;gt;()
            {
                &lt;span class="kwrd"&gt;new&lt;/span&gt; Persona() { Nombre = &lt;span class="str"&gt;"Hernán"&lt;/span&gt;, Apellido = &lt;span class="str"&gt;"Crespo"&lt;/span&gt; },
                &lt;span class="kwrd"&gt;new&lt;/span&gt; Persona() { Nombre = &lt;span class="str"&gt;"Leonardo"&lt;/span&gt;, Apellido = &lt;span class="str"&gt;"Micheloni"&lt;/span&gt; },
                &lt;span class="kwrd"&gt;new&lt;/span&gt; Persona() { Nombre = &lt;span class="str"&gt;"Enzo"&lt;/span&gt;, Apellido = &lt;span class="str"&gt;"Francescoli"&lt;/span&gt; },
                &lt;span class="kwrd"&gt;new&lt;/span&gt; Persona() { Nombre = &lt;span class="str"&gt;"Ariel"&lt;/span&gt;, Apellido = &lt;span class="str"&gt;"Ortega"&lt;/span&gt; }
            };

            personas.Sort(&lt;span class="kwrd"&gt;delegate&lt;/span&gt;(Persona x, Persona y)
            {
                &lt;span class="kwrd"&gt;return&lt;/span&gt; x.Apellido.CompareTo(y.Apellido);
            });

            personas.ForEach(Console.WriteLine);         
        }
    }

    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; Persona
    {
        &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; _nombre;

        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; Nombre
        {
            get { &lt;span class="kwrd"&gt;return&lt;/span&gt; _nombre; }
            set { _nombre = &lt;span class="kwrd"&gt;value&lt;/span&gt;; }
        }
        &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; _apellido;

        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; Apellido
        {
            get { &lt;span class="kwrd"&gt;return&lt;/span&gt; _apellido; }
            set { _apellido = &lt;span class="kwrd"&gt;value&lt;/span&gt;; }
        }

        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;override&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; ToString()
        {
            &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt;.Format(&lt;span class="str"&gt;"{0} {1}"&lt;/span&gt;, &lt;span class="kwrd"&gt;this&lt;/span&gt;.Apellido, &lt;span class="kwrd"&gt;this&lt;/span&gt;.Nombre);
        }
    }
}
&lt;/pre&gt;

&lt;p&gt;
    Y esto funciona muy bien, simplemente creamos un delegado que represente al 
    método Compare&amp;lt;Persona&amp;gt; y la inferencia de tipos hacer el resto, lee el método 
    anónimo se fija los parámetros, el valor de retorno, en cuál de las sobrecargas 
    del método Sort encaja y listo, mágico y muy bonito, pero vamos a ir un paso más 
    allá.&lt;/p&gt;
&lt;p&gt;
    &lt;b&gt;Facilitando la creación de métodos anónimos con expresiones Lambda&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;
    Por definición las expresiones Lambda son funciones anónimas que pueden contener 
    expresiones o declaraciones y pueden ser utilizadas para crear delegados o 
    árboles de expresión, entonces podemos reemplazar el delegado con una bonita 
    expresión Lambda, sí, de este modo:&lt;/p&gt;
&lt;p&gt;
    &amp;nbsp;&lt;/p&gt;
&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
&lt;pre class="csharpcode"&gt;
&lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Prueba()
{
    List&amp;lt;Persona&amp;gt; personas = &lt;span class="kwrd"&gt;new&lt;/span&gt; List&amp;lt;Persona&amp;gt;()
    {
        &lt;span class="kwrd"&gt;new&lt;/span&gt; Persona() { Nombre = &lt;span class="str"&gt;"Hernán"&lt;/span&gt;, Apellido = &lt;span class="str"&gt;"Crespo"&lt;/span&gt; },
        &lt;span class="kwrd"&gt;new&lt;/span&gt; Persona() { Nombre = &lt;span class="str"&gt;"Leonardo"&lt;/span&gt;, Apellido = &lt;span class="str"&gt;"Micheloni"&lt;/span&gt; },
        &lt;span class="kwrd"&gt;new&lt;/span&gt; Persona() { Nombre = &lt;span class="str"&gt;"Enzo"&lt;/span&gt;, Apellido = &lt;span class="str"&gt;"Francescoli"&lt;/span&gt; },
        &lt;span class="kwrd"&gt;new&lt;/span&gt; Persona() { Nombre = &lt;span class="str"&gt;"Ariel"&lt;/span&gt;, Apellido = &lt;span class="str"&gt;"Ortega"&lt;/span&gt; }
    };

    personas.Sort((x, y) =&amp;gt; x.Apellido.CompareTo(y.Apellido));

    personas.ForEach(Console.WriteLine);         
}&lt;/pre&gt;


&lt;p&gt;
    &amp;nbsp;&lt;/p&gt;
&lt;p&gt;
    Hermoso, con una linda línea podemos ordenar el listado de ídolos de River Plate 
    (en el cual me incluyu :-P ) y si descompilamos con Reflector vemos lo que pasó&lt;/p&gt;
&lt;p&gt;
    &amp;nbsp;&lt;/p&gt;
    &lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
&lt;pre class="csharpcode"&gt;
&lt;span class="kwrd"&gt;internal&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; Program
{
    &lt;span class="rem"&gt;// Methods&lt;/span&gt;
    &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Main(&lt;span class="kwrd"&gt;string&lt;/span&gt;[] args)
    {
        &lt;span class="kwrd"&gt;new&lt;/span&gt; Program().Prueba();
        Console.ReadLine();
    }

    &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Prueba()
    {
        List&amp;lt;Persona&amp;gt; &amp;lt;&amp;gt;g__initLocal0 = &lt;span class="kwrd"&gt;new&lt;/span&gt; List&amp;lt;Persona&amp;gt;();
        Persona &amp;lt;&amp;gt;g__initLocal1 = &lt;span class="kwrd"&gt;new&lt;/span&gt; Persona();
        &amp;lt;&amp;gt;g__initLocal1.Nombre = &lt;span class="str"&gt;"Hern\x00e1n"&lt;/span&gt;;
        &amp;lt;&amp;gt;g__initLocal1.Apellido = &lt;span class="str"&gt;"Crespo"&lt;/span&gt;;
        &amp;lt;&amp;gt;g__initLocal0.Add(&amp;lt;&amp;gt;g__initLocal1);
        Persona &amp;lt;&amp;gt;g__initLocal2 = &lt;span class="kwrd"&gt;new&lt;/span&gt; Persona();
        &amp;lt;&amp;gt;g__initLocal2.Nombre = &lt;span class="str"&gt;"Leonardo"&lt;/span&gt;;
        &amp;lt;&amp;gt;g__initLocal2.Apellido = &lt;span class="str"&gt;"Micheloni"&lt;/span&gt;;
        &amp;lt;&amp;gt;g__initLocal0.Add(&amp;lt;&amp;gt;g__initLocal2);
        Persona &amp;lt;&amp;gt;g__initLocal3 = &lt;span class="kwrd"&gt;new&lt;/span&gt; Persona();
        &amp;lt;&amp;gt;g__initLocal3.Nombre = &lt;span class="str"&gt;"Enzo"&lt;/span&gt;;
        &amp;lt;&amp;gt;g__initLocal3.Apellido = &lt;span class="str"&gt;"Francescoli"&lt;/span&gt;;
        &amp;lt;&amp;gt;g__initLocal0.Add(&amp;lt;&amp;gt;g__initLocal3);
        Persona &amp;lt;&amp;gt;g__initLocal4 = &lt;span class="kwrd"&gt;new&lt;/span&gt; Persona();
        &amp;lt;&amp;gt;g__initLocal4.Nombre = &lt;span class="str"&gt;"Ariel"&lt;/span&gt;;
        &amp;lt;&amp;gt;g__initLocal4.Apellido = &lt;span class="str"&gt;"Ortega"&lt;/span&gt;;
        &amp;lt;&amp;gt;g__initLocal0.Add(&amp;lt;&amp;gt;g__initLocal4);
        List&amp;lt;Persona&amp;gt; personas = &amp;lt;&amp;gt;g__initLocal0;
&lt;b&gt;        personas.Sort(&lt;/b&gt;&lt;span class="style1"&gt;delegate&lt;/span&gt;&lt;b&gt; (Persona x, Persona y) {
            &lt;/b&gt;&lt;span class="style1"&gt;return&lt;/span&gt;&lt;b&gt; x.Apellido.CompareTo(y.Apellido);
        });
&lt;/b&gt;        personas.ForEach(&lt;span class="kwrd"&gt;new&lt;/span&gt; Action&amp;lt;Persona&amp;gt;(Console.WriteLine));
    }
}&lt;/pre&gt;
&lt;pre class="csharpcode"&gt;
En las líneas remarcadas vemos que efectivamente el compilador creó el mismo delegado que habíamos definido en el primer ejemplo, sólo que nuestro código quedó mucho mas bonito y compacto gracias a las expresiones Lambda.&lt;/pre&gt;
&lt;pre class="csharpcode"&gt;
Hasta la próxima.&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;Leonardo Micheloni&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/148524916779753368-7772251064740977755?l=leomicheloni.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://leomicheloni.blogspot.com/feeds/7772251064740977755/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=148524916779753368&amp;postID=7772251064740977755' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default/7772251064740977755'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default/7772251064740977755'/><link rel='alternate' type='text/html' href='http://leomicheloni.blogspot.com/2008/08/utilizando-expresiones-lambda-para.html' title='Utilizando expresiones Lambda para facilitar la creación de métodos anónimos'/><author><name>Leonardo Micheloni</name><uri>http://www.blogger.com/profile/12085246040181097881</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='30' src='http://3.bp.blogspot.com/_t9Bh42Thfqo/S6TVOJqYWcI/AAAAAAAAANU/MlZc6HpYZis/S220/yo+laguito+en+col%C3%B3n.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-148524916779753368.post-6935584161661889669</id><published>2008-08-08T09:33:00.004-03:00</published><updated>2008-08-08T10:03:31.718-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Visual Studio'/><title type='text'>Cómo iniciar varios proyectos a la vez con Visual Studio</title><content type='html'>&lt;p&gt;
        &lt;b&gt;Cómo correr dos aplicaciones a la vez desde Visual Studio&lt;/b&gt;&lt;/p&gt;
    &lt;p&gt;
        Una vez más algo que surge de mis experiencias diarias, esto viene a cuenta de 
        tener una aplicación cliente y otra servidor que por motivos de prolijidad están 
        dentro de la misma solución, el problema es que para depurar ambas de modo 
        simultáneo se hacian cosas poco felices como abrir dos Visual Studio, bueno, hay 
        una forma de hacerlo bien.&lt;/p&gt;
    &lt;p&gt;
        &lt;b&gt;Cómo indica a Visual Studio que ejecute varias aplicaciones de modo simultáneo&lt;/b&gt;&lt;/p&gt;
    &lt;p&gt;
        El truco (o la forma correcta de hacerlo) es más que sencilla, vamos a ver.&lt;/p&gt;
    &lt;p&gt;
        Primero que nada vamos a pararnos en el explorador de soluciones y hacer botón 
        derecho sobre el nodo de la solución, es ese momento vemos la siguiente pantalla&lt;/p&gt;
        
        &lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_t9Bh42Thfqo/SJw9ft0NedI/AAAAAAAAAFo/Ob2D6rx8Ixg/s1600-h/propiedades+del+proyecto.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://2.bp.blogspot.com/_t9Bh42Thfqo/SJw9ft0NedI/AAAAAAAAAFo/Ob2D6rx8Ixg/s320/propiedades+del+proyecto.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5232124482181495250" /&gt;&lt;/a&gt;
&lt;p&gt;
    Al ir a la propiedades vamos a ver esto&lt;/p&gt;
&lt;p&gt;
    &amp;nbsp;&lt;/p&gt;
&lt;p&gt;
    &lt;a href="http://2.bp.blogspot.com/_t9Bh42Thfqo/SJw9xWDyX1I/AAAAAAAAAFw/kSYhDF0miAU/s1600-h/prppiedades+lanzar+varios.png" 
        onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"&gt;
    &lt;img id="BLOGGER_PHOTO_ID_5232124785042022226" alt="" border="0" 
        src="http://2.bp.blogspot.com/_t9Bh42Thfqo/SJw9xWDyX1I/AAAAAAAAAFw/kSYhDF0miAU/s320/prppiedades+lanzar+varios.png" 
        style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;
    Justamente en la opción starup project hay una opción que dice &amp;quot;multiple starup 
    project&amp;quot; y para los que no saben Inglés es algo como &amp;quot;inicio de múltiples 
    proyectos....con un poco de astucia sabemos que estamos ante la solución.&lt;/p&gt;
&lt;p&gt;
    Dentro de las opciones de &amp;quot;iniciar múltiples proyectos&amp;quot; Dentro de las opciones de &amp;quot;iniciar múltiples proyectos&amp;quot; podemos indicarle a 
        Visual Studio cómo iniciar los proyectos, con las siguientes acciones&lt;/p&gt;
    &lt;p&gt;
        &lt;a href="http://4.bp.blogspot.com/_t9Bh42Thfqo/SJxCyQSA_aI/AAAAAAAAAF4/qVhzAt3yHrY/s1600-h/propiedaes+cambiando+modo+de+ejecucion.png" 
            onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"&gt;
        &lt;img id="BLOGGER_PHOTO_ID_5232130298229095842" alt="" border="0" 
            src="http://4.bp.blogspot.com/_t9Bh42Thfqo/SJxCyQSA_aI/AAAAAAAAAF4/qVhzAt3yHrY/s320/propiedaes+cambiando+modo+de+ejecucion.png" 
            style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" /&gt;&lt;/a&gt;&lt;/p&gt;
    &lt;p&gt;
        None: No hace nada&lt;/p&gt;
    &lt;p&gt;
        &amp;nbsp;Start: Inicia en modo debug&lt;/p&gt;
    &lt;p&gt;
        Start without debugging: Inicia pero sin la posiblidad de depurar.
    &lt;a href="http://4.bp.blogspot.com/_t9Bh42Thfqo/SJxDbtxrPbI/AAAAAAAAAGA/JENijgE7mzo/s1600-h/salidaDoble.png" 
        onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"&gt;
    &lt;img id="BLOGGER_PHOTO_ID_5232131010521152946" alt="" border="0" 
        src="http://4.bp.blogspot.com/_t9Bh42Thfqo/SJxDbtxrPbI/AAAAAAAAAGA/JENijgE7mzo/s320/salidaDoble.png" 
        style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;
    Mágico, y simple, hasta la próxima.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;Leonardo Micheloni&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/148524916779753368-6935584161661889669?l=leomicheloni.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://leomicheloni.blogspot.com/feeds/6935584161661889669/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=148524916779753368&amp;postID=6935584161661889669' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default/6935584161661889669'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default/6935584161661889669'/><link rel='alternate' type='text/html' href='http://leomicheloni.blogspot.com/2008/08/cmo-iniciar-varios-proyectos-la-vez-con.html' title='Cómo iniciar varios proyectos a la vez con Visual Studio'/><author><name>Leonardo Micheloni</name><uri>http://www.blogger.com/profile/12085246040181097881</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='30' src='http://3.bp.blogspot.com/_t9Bh42Thfqo/S6TVOJqYWcI/AAAAAAAAANU/MlZc6HpYZis/S220/yo+laguito+en+col%C3%B3n.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_t9Bh42Thfqo/SJw9ft0NedI/AAAAAAAAAFo/Ob2D6rx8Ixg/s72-c/propiedades+del+proyecto.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-148524916779753368.post-5388567183608960838</id><published>2008-07-21T09:14:00.001-03:00</published><updated>2008-07-21T09:16:07.456-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='agiles2008'/><title type='text'>[VIDEOS] Introducción a SCRUM</title><content type='html'>&lt;p&gt;De la mano del gran Juán Gabardini les dejo estos dos videos introducción a SCRUM, muy interesantes y simples para que no digan que no tienen idea de lo que es, saludos&lt;/p&gt;

&lt;a href="http://www.arquitectum.org/portal/Publicaciones/Videos/Scrum/tabid/79/Default.aspx"&gt;Introducción de SCRUM en 15 minutos &lt;/a&gt;&lt;div class="blogger-post-footer"&gt;Leonardo Micheloni&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/148524916779753368-5388567183608960838?l=leomicheloni.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://leomicheloni.blogspot.com/feeds/5388567183608960838/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=148524916779753368&amp;postID=5388567183608960838' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default/5388567183608960838'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default/5388567183608960838'/><link rel='alternate' type='text/html' href='http://leomicheloni.blogspot.com/2008/07/videos-introduccin-scrum.html' title='[VIDEOS] Introducción a SCRUM'/><author><name>Leonardo Micheloni</name><uri>http://www.blogger.com/profile/12085246040181097881</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='30' src='http://3.bp.blogspot.com/_t9Bh42Thfqo/S6TVOJqYWcI/AAAAAAAAANU/MlZc6HpYZis/S220/yo+laguito+en+col%C3%B3n.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-148524916779753368.post-6914644989045543060</id><published>2008-07-16T20:05:00.006-03:00</published><updated>2008-07-21T09:12:55.142-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='NHibernate'/><title type='text'>[VIDEO] Introducción muy introducción a NHibernate</title><content type='html'>Este es el primero de espero muchos videos acerca de NHibernate, celebrando la beta1 de la versión 2 del framework.&lt;BR&gt;En este caso tenemos un video más que introductorio como para "ver" qué onda, vamos a ir agregando conceptos con otros post y con teoría, mientras tanto dejor el video y algunos links interesantes&lt;BR&gt;

&lt;p&gt;El video en Youtube&lt;/p&gt;
&lt;object width="425" height="350"&gt; &lt;param name="movie" value="http://www.youtube.com/v/PKHIO-tvYiM"&gt; &lt;/param&gt; &lt;embed src="http://www.youtube.com/v/PKHIO-tvYiM" type="application/x-shockwave-flash" width="425" height="350"&gt; &lt;/embed&gt; &lt;/object&gt;
&lt;br /&gt;


&lt;BR&gt;&lt;A href="http://www.blogger.com/www.nhibernate.org"&gt;Sitio de NHibernate&lt;/A&gt;&lt;BR&gt;&lt;A href="http://groups.google.com.ar/group/NHibernate-Hispano"&gt;NHibernate Hispano&lt;/A&gt;&lt;BR&gt;&lt;A href="http://blog.darioquintana.com.ar/"&gt;Blog de Darío Quintana&lt;/A&gt;&lt;BR&gt;&lt;A href="http://w15.easy-share.com/1700929136.html"&gt;Link para bajar el video (27608KB) &lt;BR&gt;&lt;/A&gt;&lt;div class="blogger-post-footer"&gt;Leonardo Micheloni&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/148524916779753368-6914644989045543060?l=leomicheloni.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='enclosure' type='video/mp4' href='http://www.blogger.com/video-play.mp4?contentId=fc5f0fa8b4782b38&amp;type=video%2Fmp4' length='0'/><link rel='replies' type='application/atom+xml' href='http://leomicheloni.blogspot.com/feeds/6914644989045543060/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=148524916779753368&amp;postID=6914644989045543060' title='4 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default/6914644989045543060'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default/6914644989045543060'/><link rel='alternate' type='text/html' href='http://leomicheloni.blogspot.com/2008/07/video-introduccin-muy-introduccin.html' title='[VIDEO] Introducción muy introducción a NHibernate'/><author><name>Leonardo Micheloni</name><uri>http://www.blogger.com/profile/12085246040181097881</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='30' src='http://3.bp.blogspot.com/_t9Bh42Thfqo/S6TVOJqYWcI/AAAAAAAAANU/MlZc6HpYZis/S220/yo+laguito+en+col%C3%B3n.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-148524916779753368.post-2858122701244277791</id><published>2008-07-15T10:36:00.000-03:00</published><updated>2008-07-15T10:37:41.970-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='IoC'/><category scheme='http://www.blogger.com/atom/ns#' term='c#'/><category scheme='http://www.blogger.com/atom/ns#' term='patrones'/><title type='text'>Introducción a Unity, o inyección de dependencias parte dos</title><content type='html'>&lt;p&gt;
        &lt;b&gt;Cómo utilizar Unity?&lt;/b&gt;&lt;/p&gt;
    &lt;p&gt;
        A pesar que tenía en mente seguir el tema de IoC/ Inyección de dependencias con 
        Microkernel a pedido del público voy a mostrar cómo lograr lo mismo que con 
        Windsor pero con Unity, la ventaja de Unity es que podemos lograr todo lo que se 
        logra por configuración programáticamente (es decir por código), pero como a 
        veces son mejores los ejemplos y no tengo ganas de escribir dejo el famoso 
        código autodescriptivo.&lt;/p&gt;
    &lt;p&gt;
        &amp;nbsp;&lt;/p&gt;
        &lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
&lt;pre class="csharpcode"&gt;
&lt;span class="kwrd"&gt;namespace&lt;/span&gt; PruebaUnity
{
    [TestFixture]
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; UnityTestFixture
    {
        Microsoft.Practices.Unity.UnityContainer container = &lt;span class="kwrd"&gt;new&lt;/span&gt; Microsoft.Practices.Unity.UnityContainer();

        &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;
        &lt;span class="rem"&gt;/// Una diferencia entre Unity y otros framewoks (Windsor, Springs) es que puede resolver tipos&lt;/span&gt;
        &lt;span class="rem"&gt;/// que no se encuentren registrados&lt;/span&gt;
        &lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;
        [Test]
        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; ResolverTipo()
        {
            &lt;span class="rem"&gt;//FakeDbConnection no se encuentra registrada, sin embargo Unity intenta resolverla&lt;/span&gt;
            &lt;span class="rem"&gt;//y lo loga sin necesidad de hacer nada&lt;/span&gt;
            IDbConnection conneccionNoRegistrada = container.Resolve&amp;lt;FakeDbConnection&amp;gt;();
            Assert.IsNotNull(conneccionNoRegistrada);
        }

        [Test]
        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; CrearObjeto()
        {
            container.RegisterType&amp;lt;IDbConnection, FakeDbConnection&amp;gt;();

            IDbConnection connection = container.Resolve&amp;lt;IDbConnection&amp;gt;();
            Assert.IsNotNull(connection);
        }

        [Test]
        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; ResolverTipoConDependencias()
        {
            container.RegisterType&amp;lt;IDbConnection, FakeDbConnection&amp;gt;();

            &lt;span class="rem"&gt;//cuando intente crear un objeto ProcessorImp va a encontrar que depende de algún&lt;/span&gt;
            &lt;span class="rem"&gt;//tipo que implemente IDbConnection y va a intentar resolverlo, como ya hemos &lt;/span&gt;
            &lt;span class="rem"&gt;//registrado FakeDbConnection que implementa IDbConnection se lo inyectará&lt;/span&gt;
            IProcessor processor= container.Resolve&amp;lt;ProcessorImp&amp;gt;();

            Assert.IsInstanceOfType(&lt;span class="kwrd"&gt;typeof&lt;/span&gt;(FakeDbConnection),processor.Connection);            
        }

        [Test]
        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; RegistrarSingleton()
        {
            container.RegisterType&amp;lt;IDbConnection, FakeDbConnection&amp;gt;(
                &lt;span class="kwrd"&gt;new&lt;/span&gt; Microsoft.Practices.Unity.ContainerControlledLifetimeManager());

            IDbConnection connection = container.Resolve&amp;lt;IDbConnection&amp;gt;();

            IDbConnection connection2 = container.Resolve&amp;lt;IDbConnection&amp;gt;();

            &lt;span class="rem"&gt;//verificamos que se trate del mismo objeto en memoria&lt;/span&gt;
            Assert.AreSame(connection, connection2);
        }

        [Test]
        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; InyectarDependencias()
        {
            &lt;span class="kwrd"&gt;string&lt;/span&gt; connectionString = &lt;span class="str"&gt;@"Data Source=.\SQL2005;Initial Catalog=KK;User ID=sa"&lt;/span&gt;;

            container.RegisterType&amp;lt;IDbConnection, FakeDbConnection&amp;gt;();

            &lt;span class="rem"&gt;//indicamos que cuando se intente resolver un tipo ProcessorImp&lt;/span&gt;
            &lt;span class="rem"&gt;//se debe inyectar un valor en la propiedad ConnectionString&lt;/span&gt;

            container.Configure&amp;lt;Microsoft.Practices.Unity.InjectedMembers&amp;gt;()
                .ConfigureInjectionFor&amp;lt;ProcessorImp&amp;gt;(
                &lt;span class="kwrd"&gt;new&lt;/span&gt; Microsoft.Practices.Unity.InjectionProperty(&lt;span class="str"&gt;"ConnectionString"&lt;/span&gt;, connectionString));

            IProcessor processor = container.Resolve&amp;lt;ProcessorImp&amp;gt;();

            Assert.IsInstanceOfType(&lt;span class="kwrd"&gt;typeof&lt;/span&gt;(FakeDbConnection), processor.Connection);
            Assert.AreEqual(processor.Connection.ConnectionString, connectionString);
        }
    }

    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; FakeDbConnection : IDbConnection
    {
        &lt;span class="kwrd"&gt;public&lt;/span&gt; IDbTransaction BeginTransaction(IsolationLevel il)
        {
            &lt;span class="kwrd"&gt;throw&lt;/span&gt; &lt;span class="kwrd"&gt;new&lt;/span&gt; NotImplementedException();
        }

        &lt;span class="kwrd"&gt;public&lt;/span&gt; IDbTransaction BeginTransaction()
        {
            &lt;span class="kwrd"&gt;throw&lt;/span&gt; &lt;span class="kwrd"&gt;new&lt;/span&gt; NotImplementedException();
        }

        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; ChangeDatabase(&lt;span class="kwrd"&gt;string&lt;/span&gt; databaseName)
        {
            &lt;span class="kwrd"&gt;throw&lt;/span&gt; &lt;span class="kwrd"&gt;new&lt;/span&gt; NotImplementedException();
        }

        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Close()
        {
            &lt;span class="kwrd"&gt;throw&lt;/span&gt; &lt;span class="kwrd"&gt;new&lt;/span&gt; NotImplementedException();
        }

        &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; _connectionString;

        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; ConnectionString
        {
            get
            {
                &lt;span class="kwrd"&gt;return&lt;/span&gt; _connectionString;
            }
            set
            {
                _connectionString = &lt;span class="kwrd"&gt;value&lt;/span&gt;;
            }
        }

        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;int&lt;/span&gt; ConnectionTimeout
        {
            get { &lt;span class="kwrd"&gt;throw&lt;/span&gt; &lt;span class="kwrd"&gt;new&lt;/span&gt; NotImplementedException(); }
        }

        &lt;span class="kwrd"&gt;public&lt;/span&gt; IDbCommand CreateCommand()
        {
            &lt;span class="kwrd"&gt;throw&lt;/span&gt; &lt;span class="kwrd"&gt;new&lt;/span&gt; NotImplementedException();
        }

        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; Database
        {
            get { &lt;span class="kwrd"&gt;throw&lt;/span&gt; &lt;span class="kwrd"&gt;new&lt;/span&gt; NotImplementedException(); }
        }

        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Open()
        {
            &lt;span class="kwrd"&gt;throw&lt;/span&gt; &lt;span class="kwrd"&gt;new&lt;/span&gt; NotImplementedException();
        }

        &lt;span class="kwrd"&gt;public&lt;/span&gt; ConnectionState State
        {
            get { &lt;span class="kwrd"&gt;throw&lt;/span&gt; &lt;span class="kwrd"&gt;new&lt;/span&gt; NotImplementedException(); }
        }

        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Dispose()
        {
            &lt;span class="kwrd"&gt;throw&lt;/span&gt; &lt;span class="kwrd"&gt;new&lt;/span&gt; NotImplementedException();
        }
    }

    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; ProcessorImp : IProcessor
    {
        IDbConnection _connection;

        &lt;span class="kwrd"&gt;public&lt;/span&gt; ProcessorImp(IDbConnection connection)
        {
            _connection = connection;
        }
        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Process()
        {
            &lt;span class="rem"&gt;//llama a _connection y hace algo... &lt;/span&gt;
        }

        &lt;span class="kwrd"&gt;public&lt;/span&gt; IDbConnection Connection
        {
            get { &lt;span class="kwrd"&gt;return&lt;/span&gt; _connection; }
        }

        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; ConnectionString
        {
            get
            {
                &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;this&lt;/span&gt;.Connection.ConnectionString;
            }

            set
            {
                &lt;span class="kwrd"&gt;this&lt;/span&gt;.Connection.ConnectionString = &lt;span class="kwrd"&gt;value&lt;/span&gt;;
            }
        }
    }

    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;interface&lt;/span&gt; IProcessor
    {
        &lt;span class="kwrd"&gt;void&lt;/span&gt; Process();

        IDbConnection Connection
        {
            get;
        }
    }

}&lt;/pre&gt;

&lt;br /&gt;
&lt;p&gt;Sencillo y claro, hasta la próxima.&lt;/p&gt;
&lt;a href="http://www.codeplex.com/unity"&gt;Home page de Unity&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;Leonardo Micheloni&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/148524916779753368-2858122701244277791?l=leomicheloni.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://leomicheloni.blogspot.com/feeds/2858122701244277791/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=148524916779753368&amp;postID=2858122701244277791' title='4 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default/2858122701244277791'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default/2858122701244277791'/><link rel='alternate' type='text/html' href='http://leomicheloni.blogspot.com/2008/07/introduccin-unity-o-inyeccin-de.html' title='Introducción a Unity, o inyección de dependencias parte dos'/><author><name>Leonardo Micheloni</name><uri>http://www.blogger.com/profile/12085246040181097881</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='30' src='http://3.bp.blogspot.com/_t9Bh42Thfqo/S6TVOJqYWcI/AAAAAAAAANU/MlZc6HpYZis/S220/yo+laguito+en+col%C3%B3n.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-148524916779753368.post-7866504063945981200</id><published>2008-07-08T15:44:00.004-03:00</published><updated>2008-07-08T16:01:32.434-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='c#'/><title type='text'>Depurando servicios de Windows del modo fácil</title><content type='html'>&lt;strong&gt;
    ¿Cómo puedo "atachar" facilmente un servicio de windows para depurarlo?&lt;/strong&gt;&lt;br /&gt;
    &lt;br /&gt;
    La forma clásica es tener el servicio corriendo y presionando Ctrl + Alt + P buscar
    el proceso en la ventanita y asociarlo con el código, esto es especialemente molesto
    en caso de neceistar que el servicio no haga nada antes de encontrarse "atachado"
    y sobre todo para encontrar un buen lugar donde poner el punto de interrupción,
    bien , hay una forma más sencilla.&lt;br /&gt;
    &lt;br /&gt;
    &lt;strong&gt;
    System.Diagnostic. Debugger un amigo&lt;/strong&gt;&lt;br /&gt;
    &lt;br /&gt;
    Dentro de las muchas clases que hay dentro de este espacio de nombre se encuentra
    la buena de Debugger, si somos un poco avispados nos podemos dar cuenta de su fución:
    es para depurar, dentro de sus métodos hay uno que nos va a ayudar en este caso,
    Launch(), este método va a lanzar el "debugger" de .net inmediatamente, fantástico,
    ahora el tema es cómo hacer para lanzarlo en el servicio y no siempre, bueno, veamos.&lt;br /&gt;
    &lt;br /&gt;
    &lt;strong&gt;
    ¿Cómo leer los parámetros de línea de comando de un servicio de Windows?&lt;br /&gt;
    &lt;/strong&gt;
    &lt;br /&gt;
    Fácil, dentro del método Start del servicio llegan los parámetros, o sea, lo único
    que deberíamos hacer es leer un parámetro que lo podemos llamar "DEBUG" para ser
    astudos y en caso de llegar llamar a Debugger.Lanuch() y listo, vamos a ver cómo&lt;br /&gt;
    &lt;br /&gt;
    
    &lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;namespace&lt;/span&gt; MiServicioLoco
{
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;partial&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; ServicioLoco : ServiceBase
    {
        &lt;span class="kwrd"&gt;public&lt;/span&gt; ServicioLoco()
        {
            InitializeComponent();
        }

        &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;
        &lt;span class="rem"&gt;/// Este método se ejecuta cuando se inicia el servicio&lt;/span&gt;
        &lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;
        &lt;span class="rem"&gt;/// &amp;lt;param name="args"&amp;gt;&amp;lt;/param&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;protected&lt;/span&gt; &lt;span class="kwrd"&gt;override&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; OnStart(&lt;span class="kwrd"&gt;string&lt;/span&gt;[] args)
        {
            &lt;span class="rem"&gt;//los parámetros que se envían desde la ventana de propiedades del servicio&lt;/span&gt;
            &lt;span class="rem"&gt;//entren por acá&lt;/span&gt;

            &lt;span class="rem"&gt;//en caso de que el primer parámetro de línea de comando sea igual a DEBUG&lt;/span&gt;
            &lt;span class="rem"&gt;//se lanza el debugger&lt;/span&gt;
            &lt;span class="kwrd"&gt;if&lt;/span&gt; (args.GetLength(0) &amp;gt; 0 &amp;amp;&amp;amp; args[0].Equals(&lt;span class="str"&gt;"DEBUG"&lt;/span&gt;))
                System.Diagnostics.Debugger.Launch();
                
            &lt;span class="rem"&gt;//ahora podemos continuar con el proceso atachado&lt;/span&gt;

        }

        &lt;span class="kwrd"&gt;protected&lt;/span&gt; &lt;span class="kwrd"&gt;override&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; OnStop()
        {
            &lt;span class="rem"&gt;// TODO: Add code here to perform any tear-down necessary to stop your service.&lt;/span&gt;
        }
    }
}

&lt;/pre&gt;
    Grandioso, ahora lo único que debemos hacer es&lt;br /&gt;
    &lt;br /&gt;
    &lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_t9Bh42Thfqo/SHO4wS_l7hI/AAAAAAAAAFY/Ro-sUIdFHQI/s1600-h/parametros.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://4.bp.blogspot.com/_t9Bh42Thfqo/SHO4wS_l7hI/AAAAAAAAAFY/Ro-sUIdFHQI/s320/parametros.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5220719532924333586" /&gt;&lt;/a&gt;
    &lt;br /&gt;
    para pasar el parámetro al serivico y mágicamente se lanzará la ventana&lt;br /&gt;
    &lt;br /&gt;
&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_t9Bh42Thfqo/SHO5CmS4TxI/AAAAAAAAAFg/F_Gj6oAHIiA/s1600-h/lanunch.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://4.bp.blogspot.com/_t9Bh42Thfqo/SHO5CmS4TxI/AAAAAAAAAFg/F_Gj6oAHIiA/s320/lanunch.png" border="0" alt=""id="Img1" /&gt;&lt;/a&gt;
    &lt;br /&gt;
    Mágico, seleccionamos el debugger (el VS) y listo, que mejore vuestra depuración....saludos.&lt;div class="blogger-post-footer"&gt;Leonardo Micheloni&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/148524916779753368-7866504063945981200?l=leomicheloni.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://leomicheloni.blogspot.com/feeds/7866504063945981200/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=148524916779753368&amp;postID=7866504063945981200' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default/7866504063945981200'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default/7866504063945981200'/><link rel='alternate' type='text/html' href='http://leomicheloni.blogspot.com/2008/07/depurando-servicios-de-windows-del-modo.html' title='Depurando servicios de Windows del modo fácil'/><author><name>Leonardo Micheloni</name><uri>http://www.blogger.com/profile/12085246040181097881</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='30' src='http://3.bp.blogspot.com/_t9Bh42Thfqo/S6TVOJqYWcI/AAAAAAAAANU/MlZc6HpYZis/S220/yo+laguito+en+col%C3%B3n.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_t9Bh42Thfqo/SHO4wS_l7hI/AAAAAAAAAFY/Ro-sUIdFHQI/s72-c/parametros.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-148524916779753368.post-24840782940512258</id><published>2008-07-03T12:34:00.002-03:00</published><updated>2008-11-19T14:58:36.997-02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='mock'/><category scheme='http://www.blogger.com/atom/ns#' term='IoC'/><category scheme='http://www.blogger.com/atom/ns#' term='C# 3.0'/><category scheme='http://www.blogger.com/atom/ns#' term='patrones'/><category scheme='http://www.blogger.com/atom/ns#' term='unit test'/><title type='text'>Qué es la inversión de control / inyección de dependencias e intruducción a Windsor Container</title><content type='html'>&lt;p&gt;
    &lt;strong&gt;
            Inyección de dependencias.&lt;/strong&gt;
       
    &lt;/p&gt;
    &lt;p&gt;
        Vamos a introducirnos en un algo importante y además muy interesante,
            la inyección de dependencias y la inversión de control. 
    &lt;/p&gt;
    &lt;p&gt;
Ambos patrones se encuentran muy asociados, tanto que es normal confundirlos, para hacerlo claro, inversión de control es el modo en que funcionan generalmente los frameworks, en lugar de nosotros instanciar un objeto Database en el data access application block de Enterprise Library le decimos a la clase DatabaseFactory que lo haga por nosotros, es es inversión de control, en lugar de tener nosotros el control sobre la creación de objetos le pedimos alguien más que lo haga. Inyección de dependencias es cuando un objeto A depende de uno B, esta dependencia es inyectada al objeto A por el constructor por ejemplo, es decir, el objeto A tiene un constructor que acepta un parámetro del tipo objeto B, esto es inyectar una dependencia.&lt;/p&gt;
    &lt;p&gt;
        Para poder entender
            el por qué de todo esto vamos a remitirnos a un ejemplo: 
    &lt;/p&gt;
    &lt;p&gt;
        &lt;strong&gt;El problema: &lt;/strong&gt;
    &lt;/p&gt;
&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;interface&lt;/span&gt; IProcessor
{ 
    &lt;span class="kwrd"&gt;void&lt;/span&gt; Process(); 
}

&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; ProcessorImp : IProcessor
{
    IDbConnection _connection;
    &lt;span class="kwrd"&gt;public&lt;/span&gt; ProcessorImp()
    {
        _connection = &lt;span class="kwrd"&gt;new&lt;/span&gt; System.Data.OleDb.OleDbConnection();
    }
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Process()
    {
        &lt;span class="rem"&gt;//llama a _connection y hace algo... &lt;/span&gt;
        _connection.Open();
    }
} 
&lt;/pre&gt;
    &lt;p&gt;
        Si miramos con detenimiento el método Process vemos algo interesante,
            imaginemos que queremos probar nuestro ProcessorImp y nos encontramos que en el constructor se instancia _connection, por lo
            tanto, para correr una prueba vamos a necesitar acceder a la base de datos, eso
            definitivamente no es deseable y mucho menos práctico
        para una prueba unitaria, pero ¿cuál es la solución? 
    &lt;/p&gt;
    &lt;p&gt;
        &lt;strong&gt;
        La solución, inyectar dependencias:&lt;/strong&gt;&lt;/p&gt;
    &lt;p&gt;
        La forma de solucionar esto es de alguna manera evitar que se instancie
            _connection dentro de ProcessorImp y utilizarlo en forma transparente de modo que
            podamos, en caso de probarlo, utilizar una implementación de _connection que no
            acceda a la base de datos, o sea, un Stub o por qué no un Mock.&lt;/p&gt;
    &lt;p&gt;
        &lt;strong&gt;Primera aproximación, desacoplar con interfaces&lt;/strong&gt;&lt;/p&gt;
    &lt;p&gt;
        La inyección de dependencias es algo tan simple como evitar que nuestros
            objetos de negocios creen objetos que necesitan utilizar, proveyéndoselos ya listos
            para operar. ¿Y cómo hacemos esto?
            Inyectándolos. 
    &lt;/p&gt;
    &lt;p&gt;
        Hay un par de formas de inyectar dependencias, pero nosotros vamos
            a elegir la inyección de dependencias por constructor (ya que no tiene sentido que
            exista la clase Processor sin un IDbConnection), que no es más que pasarle a nuestro
            objeto de negocios ese objeto que necesita ya listo a través de su constructor,
            más aún, vamos a pasarle una interfaz lo cual nos va a traer otras ventajas adicionales,
            vamos a ver cómo queda el código con esta modificación: 
    &lt;/p&gt;
&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; ProcessorImp : IProcessor
{
    IDbConnection _connection;
    &lt;span class="kwrd"&gt;public&lt;/span&gt; ProcessorImp(IDbConnection connection)
    {
        _connection = connection;
    }
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Process()
    {
        &lt;span class="rem"&gt;//llama a _connection y hace algo... &lt;/span&gt;
    }
}&lt;/pre&gt;
    &lt;p&gt;
        Un poco mejor, vemos que estamos pasando el IDbConnection en el constructor,
            lo cual es bueno porque nos va permitir pasarle cualquier cosa que implemente esta
            interfaz y simule el comportamiento de la capa de datos en caso de querer probarlo
            en una prueba unitaria. Ahora bien, para construir un objeto IProcessor antes hacíamos:&lt;/p&gt;
&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
&lt;pre class="csharpcode"&gt;IProcessor processor = &lt;span class="kwrd"&gt;new&lt;/span&gt; ProcessorImp();&lt;/pre&gt;
    &lt;p&gt;
        Pero ahora no podemos porque el constructor de ProcessorImp (la única
            clase que tenemos que implementa IProcessor) en su lugar tenemos que hacer esto:&lt;/p&gt;
&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
&lt;pre class="csharpcode"&gt;IDbConnection connection = &lt;span class="kwrd"&gt;new&lt;/span&gt; SqlConnection(ConfigurationManager.ConnectionStrings[&lt;span class="str"&gt;"default"&lt;/span&gt;] .ConnectionString); 
IProcessor processor = &lt;span class="kwrd"&gt;new&lt;/span&gt; ProcessorImp(connection); 
&lt;/pre&gt;
    &lt;p&gt;
        Para simplemente después hacer&lt;/p&gt;
&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
&lt;pre class="csharpcode"&gt;processor.Process();&lt;/pre&gt;
    &lt;p&gt;
        O sea, 1 línea útil y 2 inútiles (para la finalidad de la lógica
            de negocios), esto puede agravarse en caso de tener más de una dependencia de inyectar
            o que la dependencia que inyectamos a su vez tenga otras dependencias.&lt;/p&gt;
    &lt;p&gt;
        Entonces,
            ¿cómo se resuelve?, fácil, echando mano de otro patrón de diseño Factory para realizar
            la inversión de control.&lt;/p&gt;
    &lt;p&gt;
        &lt;strong&gt;El patrón Factory&lt;/strong&gt;&lt;/p&gt;
    &lt;p&gt;
        Nos va a permitir recuperar objetos listos para ser utilizados, sin
            necesidad de saber nada de ellos, ni de qué dependen, si necesitan información de
            configuración, etc.&lt;/p&gt;
    &lt;p&gt;
        Mágico, si pero ¿cómo hacemos?, veamos un poco de código:&lt;/p&gt;
&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; ProcessorFactory
{
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; IProcessor BuildProcessor() 
    { 
        &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;new&lt;/span&gt; ProcessorImp(
            &lt;span class="kwrd"&gt;new&lt;/span&gt; System.Data.SqlClient.SqlConnection( ConfigurationManager.ConnectionStrings[&lt;span class="str"&gt;"default"&lt;/span&gt;] .ConnectionString); 
    }
}&lt;/pre&gt;
    &lt;p&gt;
        A esto le llamamos inversión de control (IoC) y es justamente eso,
            en lugar de decidir nosotros cómo crear un objeto hacemos que alguien más decida
            por nosotros, o sea, invertimos el control, se usa así:&lt;/p&gt;
&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
&lt;pre class="csharpcode"&gt;IProcessor processor = ProcessorFactory.BuildProcessor(); 
processor.Process();
&lt;/pre&gt;
    &lt;p&gt;
        Lindo, ahora la creación del objeto no interfiere con la lógica de
            negocios y no necesitamos saber nada del objeto que vamos a utilizar, no limitamos
            a saber de la interfaz. Mejorando las pruebas unitarias Esta forma de hacer las cosas nos permite mejorar las pruebas unitarias
            ya que para probar el ProcessorImp, simplemente creamos un Factory que nos dé un
            ProcessorImp y le inyecte por constructor una IDbConnection que no haga nada o que
            haga lo que necesitamos para la prueba más o menos así:&lt;/p&gt;
&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; ProcessorFakeFactory
{
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; IProcessor BuildProcessor()
    {
        &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;new&lt;/span&gt; ProcessorImp(&lt;span class="kwrd"&gt;new&lt;/span&gt; FakeDbConnection());
    }
}
&lt;/pre&gt;
    &lt;p&gt;
        Algo mejor sería hacerlo con un framework de Mock como &lt;a href="http://www.ayende.com/projects/rhino-mocks.aspx"&gt;
            RhinoMocks&lt;/a&gt;
            o el increíble &lt;a href="http://code.google.com/p/moq/"&gt;Moq&lt;/a&gt;
        del amigo &lt;a href="http://www.clariusconsulting.net/blogs/kzu/"&gt;Kzu&lt;/a&gt;.&lt;/p&gt;
    &lt;p&gt;
        &lt;strong&gt;Otras ventajas de la inversión de control&lt;/strong&gt;&lt;/p&gt;
    &lt;p&gt;
        Otra de las ventajas que tenemos utilizando este diseño es que podemos
            obtener diferentes implementaciones de IProcessor sin hacer mucho y lo más importante,
            sin impactar en el código de lógica de negocios. Si recuerdan algo que dije antes,
            en la interfaz no se encuentra el constructor y esto nos permite con la misma interfaz
            utilizar indistintamente diferentes implementaciones de IProcessor que pueden tener
            otras dependencias, por ejemplo:&lt;/p&gt;
    &lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; ProcessorFakeFactory
{
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; IProcessor BuildProcessor()
    {
        &lt;span class="kwrd"&gt;return&lt;/span&gt; BuildProcessor(ProcessorType.Sql);
    }
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; IProcessor BuildProcessor(ProcessorType type)
    {
        &lt;span class="kwrd"&gt;switch&lt;/span&gt; (type)
        {
            &lt;span class="kwrd"&gt;case&lt;/span&gt; ProcessorType.Sql:
                &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;new&lt;/span&gt; ProcessorImp(
                    &lt;span class="kwrd"&gt;new&lt;/span&gt; System.Data.SqlClient.SqlConnection(
                    ConfigurationManager.ConnectionStrings[&lt;span class="str"&gt;"default"&lt;/span&gt;].ConnectionString));
                &lt;span class="kwrd"&gt;break&lt;/span&gt;;
            &lt;span class="kwrd"&gt;case&lt;/span&gt; ProcessorType.OleDb:
                &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;new&lt;/span&gt; ProcessorImp(
                    &lt;span class="kwrd"&gt;new&lt;/span&gt; System.Data.OleDb.OleDbConnection(
                    ConfigurationManager.ConnectionStrings[&lt;span class="str"&gt;"oledb"&lt;/span&gt;].ConnectionString));
                &lt;span class="kwrd"&gt;break&lt;/span&gt;;
            &lt;span class="kwrd"&gt;default&lt;/span&gt;:
                &lt;span class="kwrd"&gt;throw&lt;/span&gt; &lt;span class="kwrd"&gt;new&lt;/span&gt; ArgumentException(&lt;span class="str"&gt;"type"&lt;/span&gt;); &lt;span class="kwrd"&gt;break&lt;/span&gt;;
        }
    }
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;enum&lt;/span&gt; ProcessorType
    {
        Sql,
        OleDb
    }
}
&lt;/pre&gt;
    &lt;p&gt;
        Esta implementación es más o menos lo que hace &lt;a href="http://www.codeplex.com/entlib"&gt;
            DataAccess Application Block &lt;/a&gt;cuando hacemos DataBaseFactory.CreateDataBase() con una agregado que veremos
            más adelante. 
    &lt;/p&gt;
    &lt;p&gt;
        Se ve claramente las ventajas de éste modelo, disminuimos el acoplamiento,
            mejoramos las pruebas unitarias, obtenemos mayor flexibilidad y queda lindo.&lt;/p&gt;
    &lt;p&gt;
        &lt;strong&gt;
        Ahora si, framework de inversión de control&lt;/strong&gt;&lt;/p&gt;
    &lt;p&gt;
        El siguiente paso en todo esto es utilizar un framework de inyección
            de dependencias que haga la inversión de control, y en el mundo de .net hay para
            todos los gustos, vamos a enumerarlos:&lt;/p&gt;
            &lt;ul&gt;
            &lt;li&gt;Spring.net: es un port del famoso framework de Java&lt;/li&gt;
            &lt;li&gt;Windsor container: parte del proyecto Castle, muy extendido&lt;/li&gt;
            &lt;li&gt;Unity: de patterns &amp;amp; practices de Microsoft, basado en ObjectBuilder
            que es lo que utiliza internamente DataAccess Application Block&lt;/li&gt;
            &lt;li&gt; Ninject: Este es nuevito, la principal característica es que se basa
            en atributos para saber qué y cómo inyectar.&lt;/li&gt;
            &lt;/ul&gt;    
    &lt;p&gt;
        &lt;strong&gt;¿Cómo funcionan los frameworks de IoC?&lt;/strong&gt;&lt;/p&gt;
    &lt;p&gt;
        Los framework de IoC nos permite tener un repositorio (en realidad es transparente
        el repositorio lo maneja el framework, de echo vamos a utilizar el término repositorio
        para referirnos a él) donde tenemos
            nuestros objetos e ir pidiéndoselos, algunas ventajas adicionales, como controlar
            el ciclo de vida de los objetos, crearlos tipo singleton, reutilizar instancias,
            y resolver dependencias anidadas, como tener un objeto A configurado y pedirle un
            B y que sólo se dé cuenta que necesita A y crearlos según lo configurado.&lt;/p&gt;
    &lt;p&gt;
        &lt;em&gt;
        Basados en archivos de configuración&lt;/em&gt;&lt;/p&gt;
    &lt;p&gt;
        Hay variantes entre estos que enumeramos, la más utilizada es basarse
            en un archivo de configuración para saber cómo crear los objetos, a mí, personalmente
            no me gusta porque cuando tenemos una aplicación con varios (no digo mucho, 30 nomás)
            objetos se pone bastante molesto el archivo de configuración, a esto hay que sumarle
            que en caso de necesitar comprender algunas cosas sobre estos objetos tenemos que
            “bucear” el archivo de configuración, y no anda el intellisense ;-).&lt;/p&gt;
    &lt;p&gt;
        &lt;em&gt;
        Basados en declaración programática&lt;/em&gt;&lt;/p&gt;
    &lt;p&gt;
            Casi todos, los frameworks soportan definir los objetos por medio
            de código, esto puede parece poco ventajoso, en lugar de escribir una sintaxis especial
            para instanciar los objetos escribo todo de forma normal y listo, pero nos perdemos
            el manejo del ciclo de vida que hace el framework.&lt;/p&gt;
    &lt;p&gt;
        &lt;em&gt;Basados en atributos&lt;/em&gt;&lt;/p&gt;
    &lt;p&gt;
        El chico nuevo de la cuadra es Ninject que se basa en atributos para
            la definición de las dependencias, cero configuración, simplemente agregamos atributos
            a nuestras clases y listo, mágico, la idea es muy interesante aunque no me gusta
            mucho la implementación por motivos que vienen al caso.&lt;/p&gt;
    &lt;p&gt;
        &lt;strong&gt;Ahora sí, un ejemplo con un framework de IoC&lt;/strong&gt;&lt;/p&gt;
    &lt;p&gt;
        Dentro de los frameworks que he nombrado los que más me agradan son
            Unity y Windsor
        (ya sé que me contradigo), vamos a ver unos ejemplos introductorios con Windsor ya que es
            simple y es bueno conocerlo.&lt;/p&gt;
    &lt;p&gt;
        &lt;strong&gt;Windsor container&lt;/strong&gt;&lt;/p&gt;
    &lt;p&gt;
            También conocido como microkernel porque en realidad se basa en él
            y lo extiende, es parte del proyecto castle que si no lo conocen les recomiendo
            una vuelta. En él se basan muchos otros proyectos, como NHibernate, Moq, Rhino,
            etc. Diría sin temor a equivocarme que es el más extendido en la comunidad .net.&lt;/p&gt;
    &lt;p&gt;
        Antes que nada vamos a necesitar descargarlos &lt;a href="http://castleproject.org/castle/download.html"&gt;
            desde acá&lt;/a&gt; .Y referenciar estos assemblies&lt;/p&gt;
    &lt;ul&gt;
    &lt;li&gt;Castle.Core.dll&lt;/li&gt;
    &lt;li&gt;Castle.MicroKernel.dll&lt;/li&gt;
    &lt;li&gt;Castle.Windsor.dll&lt;/li&gt;
    &lt;li&gt;Castle.DynamicProxy.dll&lt;/li&gt;
    &lt;/ul&gt;
    &lt;p&gt;
        El código para configurar el contenedor es éste&lt;/p&gt;
&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
&lt;pre class="csharpcode"&gt;IWindsorContainer container = new WindsorContainer(); 
container.AddComponent("Sql", typeof(IDbConnection), typeof(System.Data.SqlClient.SqlConnection)); 
container.AddComponent("Processor", typeof(IProcessor), typeof(ProcessorImp)); 
&lt;/pre&gt;
    &lt;p&gt;
        Y
            para utilizarlo 
    &lt;/p&gt;
&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
&lt;pre class="csharpcode"&gt;IProcessor processor = container.Resolve&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;IProcessor&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;();&lt;/pre&gt;
    &lt;p&gt;
            La idea es poner todo esto dentro del Factory o en alguna inicialización
            de nuestro objeto aplicación o no, es una discusión de arquitectura que no viene
            al caso.&lt;/p&gt;
    &lt;p&gt;
        &lt;strong&gt;Más flexibilidad con Windsor&lt;/strong&gt;&lt;/p&gt;
    &lt;p&gt;
        Seguramente se están preguntando dos cosas:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Cómo le paso el parámetro del connectionString a SqlConnection&lt;/li&gt;
&lt;li&gt;Cómo hago en caso de tener más de una implementación de IDbConnection para indicarle al contenedor cuál utilizar para crear el IProcessor
&lt;/li&gt;
&lt;/ol&gt;
    &lt;p&gt;
        Excelentes preguntas, la respuesta para todas es: no se puede por
            código, esta flexibilidad sólo está disponible si configuramos el contenedor por
            archivo de configuración. De la siguiente forma:&lt;/p&gt;
    &lt;p&gt;
        &lt;strong&gt;Utilizando Windsor desde archivo de configuración&lt;/strong&gt;&lt;/p&gt;
    &lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
&lt;pre class="csharpcode"&gt;IWindsorContainer container = &lt;span class="kwrd"&gt;new&lt;/span&gt; WindsorContainer( 
    &lt;span class="kwrd"&gt;new&lt;/span&gt; XmlInterpreter(&lt;span class="kwrd"&gt;new&lt;/span&gt; ConfigResource(&lt;span class="str"&gt;"castle"&lt;/span&gt;)));
IProcessor processor = container.Resolve();
&lt;/pre&gt;
    &lt;p&gt;
            Esto con relación al código, le indicamos al contenedor que obtenga
            la configuración desde la sección “castle” del archivo de configuración. El archivo de configuración
            queda así:&lt;/p&gt;
&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;&amp;lt;?&lt;/span&gt;&lt;span class="html"&gt;xml&lt;/span&gt; &lt;span class="attr"&gt;version&lt;/span&gt;&lt;span class="kwrd"&gt;="1.0"&lt;/span&gt; &lt;span class="attr"&gt;encoding&lt;/span&gt;&lt;span class="kwrd"&gt;="utf-8"&lt;/span&gt;?&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;configuration&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;configSections&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;section&lt;/span&gt; &lt;span class="attr"&gt;name&lt;/span&gt;&lt;span class="kwrd"&gt;="dataConfiguration"&lt;/span&gt; &lt;span class="attr"&gt;type&lt;/span&gt;&lt;span class="kwrd"&gt;="Microsoft.Practices.EnterpriseLibrary.Data.Configuration.DatabaseSettings, Microsoft.Practices.EnterpriseLibrary.Data, Version=3.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="rem"&gt;&amp;lt;!--de esta manera le indicamos al motor de configuración que vamos a utilizar una sección llamanda castle&lt;/span&gt;
&lt;span class="rem"&gt;        que se parsea a partir del tipo CastleSectionHandler que se encuentra en el assemblie Castle.Windsor--&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;section&lt;/span&gt; 
           &lt;span class="attr"&gt;name&lt;/span&gt;&lt;span class="kwrd"&gt;="castle"&lt;/span&gt;
           &lt;span class="attr"&gt;type&lt;/span&gt;&lt;span class="kwrd"&gt;="Castle.Windsor.Configuration.AppDomain.CastleSectionHandler, Castle.Windsor"&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;configSections&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="rem"&gt;&amp;lt;!--y esta es la sección de configuración de castle--&amp;gt;&lt;/span&gt;
    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;castle&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;components&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="rem"&gt;&amp;lt;!--cada elemento que queremos registrar en el contenedor se define dentro de un tag component--&amp;gt;&lt;/span&gt;
            &lt;span class="rem"&gt;&amp;lt;!--en el tag id se coloca el nombre con el que queremos identificar este componente particular--&amp;gt;&lt;/span&gt;
            &lt;span class="rem"&gt;&amp;lt;!--en el tag service la interface--&amp;gt;&lt;/span&gt;
            &lt;span class="rem"&gt;&amp;lt;!--en el tag type el tipo concreto que querems que el contenedor devuelva--&amp;gt;&lt;/span&gt;
            &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;component&lt;/span&gt; 
                &lt;span class="attr"&gt;id&lt;/span&gt;&lt;span class="kwrd"&gt;="Sql"&lt;/span&gt; 
                &lt;span class="attr"&gt;service&lt;/span&gt;&lt;span class="kwrd"&gt;="System.Data.IDbConnection, System.Data, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"&lt;/span&gt; 
                &lt;span class="attr"&gt;type&lt;/span&gt;&lt;span class="kwrd"&gt;="System.Data.SqlClient.SqlConnection, System.Data, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;parameters&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
                    &lt;span class="rem"&gt;&amp;lt;!--Windsor busca el constructor que tenga este parámetro y se lo inyecta--&amp;gt;&lt;/span&gt;
                    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;connectionString&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;Database=Database;Server=(local)\SQLEXPRESS;Integrated Security=SSPI&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;connectionString&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;parameters&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;component&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;component&lt;/span&gt; 
                &lt;span class="attr"&gt;id&lt;/span&gt;&lt;span class="kwrd"&gt;="OleDb"&lt;/span&gt; 
                &lt;span class="attr"&gt;service&lt;/span&gt;&lt;span class="kwrd"&gt;="System.Data.IDbConnection, System.Data, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"&lt;/span&gt; 
                &lt;span class="attr"&gt;type&lt;/span&gt;&lt;span class="kwrd"&gt;="System.Data.OleDb.OleDbConnection, System.Data, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;component&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;component&lt;/span&gt; 
                &lt;span class="attr"&gt;id&lt;/span&gt;&lt;span class="kwrd"&gt;="Processor"&lt;/span&gt; 
                &lt;span class="attr"&gt;service&lt;/span&gt;&lt;span class="kwrd"&gt;="Tipos.IProcessor, Tipos"&lt;/span&gt; 
                &lt;span class="attr"&gt;type&lt;/span&gt;&lt;span class="kwrd"&gt;="Tipos.ProcessorImp, Tipos"&lt;/span&gt; &lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;parameters&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
                    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;connection&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;${Sql}&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;connection&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;parameters&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;component&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;components&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;castle&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;connectionStrings&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;add&lt;/span&gt; &lt;span class="attr"&gt;name&lt;/span&gt;&lt;span class="kwrd"&gt;="Sql"&lt;/span&gt; &lt;span class="attr"&gt;connectionString&lt;/span&gt;&lt;span class="kwrd"&gt;="Database=Database;Server=(local)\SQLEXPRESS;Integrated Security=SSPI"&lt;/span&gt;
            &lt;span class="attr"&gt;providerName&lt;/span&gt;&lt;span class="kwrd"&gt;="System.Data.SqlClient"&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;connectionStrings&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;configuration&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;
    &lt;p&gt;
        Como vemos en la sección “components” definimos nuestros componentes,
            dentro de cada elemento “component” tres atributos:&lt;/p&gt;
    &lt;ul&gt;
    &lt;li&gt;Id: El nombre con el que identificamos unívocamente ese componente.&lt;/li&gt;
    &lt;li&gt;service: El servicio, o sea la interfaz o el tipo con el que vamos a invocar nuestro componente, es decir, cuando le digamos dame un IAlgo ese es el servicio.&lt;/li&gt;
    &lt;li&gt;type: El tipo concreto que queremos que devuelva cuando se solicite un servicio&lt;/li&gt;
    &lt;/ul&gt;        
    &lt;p&gt;
        Con esto es suficiente, ahora para poder inyectarle parámetros en
            los constructores tenemos el elemento “parameters” dentro de él colocamos un elemento
            por cada parámetro del constructor que queremos que el contener invoque, él sólito
            se va a dar cuenta qué constructor llamar.&lt;/p&gt;
    &lt;p&gt;
        &lt;em&gt;
        ¿Cómo se decide qué implementación de un servicio quiero?&lt;/em&gt;&lt;/p&gt;
    &lt;p&gt;
        Utilizando el tag “parameters” ponemos el nombre del parámetro y
            luego con un poco de sintaxis “castle” le indicamos qué implementación queremos
            que le inyecte por el “id” como en el ejemplo, diciendo algo como: cuando te pida IProcessor dame el
        tipo IProcessorImp y a su constructor que pide un IDbConnection pasale la implementación
        que tiene el "id" Sql.&lt;/p&gt;
    &lt;p&gt;
        &lt;strong&gt;Conclusión:&lt;/strong&gt;&lt;/p&gt;
    &lt;p&gt;
        En una palabra, mágico, la inversión de control + inyección de dependencias
            + factory + frameworks de inversión de control nos permiten crear aplicaciones menos
            acopladas, más fáciles de probar, de cambiar, de mantener, definitivamente muy interesante.
        Hasta la próxima. 
    &lt;/p&gt;    
    &lt;ul&gt;
    &lt;li&gt;&lt;a href="http://castleproject.org/index.html"&gt;Castle Project&lt;/a&gt; &lt;/li&gt;
    &lt;li&gt;&lt;a href="http://www.codeplex.com/unity"&gt;Unity Container&lt;/a&gt; &lt;/li&gt;
    &lt;li&gt;&lt;a href="http://www.springframework.net/"&gt;Spring.net&lt;/a&gt; &lt;/li&gt;
    &lt;li&gt;&lt;a href="http://ninject.org/"&gt;Ninject&lt;/a&gt; &lt;/li&gt;
    &lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;Leonardo Micheloni&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/148524916779753368-24840782940512258?l=leomicheloni.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://leomicheloni.blogspot.com/feeds/24840782940512258/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=148524916779753368&amp;postID=24840782940512258' title='8 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default/24840782940512258'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default/24840782940512258'/><link rel='alternate' type='text/html' href='http://leomicheloni.blogspot.com/2008/07/qu-es-la-inversin-de-control-inyeccin.html' title='Qué es la inversión de control / inyección de dependencias e intruducción a Windsor Container'/><author><name>Leonardo Micheloni</name><uri>http://www.blogger.com/profile/12085246040181097881</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='30' src='http://3.bp.blogspot.com/_t9Bh42Thfqo/S6TVOJqYWcI/AAAAAAAAANU/MlZc6HpYZis/S220/yo+laguito+en+col%C3%B3n.jpg'/></author><thr:total>8</thr:total></entry><entry><id>tag:blogger.com,1999:blog-148524916779753368.post-8596076691350780476</id><published>2008-06-18T14:35:00.002-03:00</published><updated>2008-07-16T11:46:45.973-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='mock'/><category scheme='http://www.blogger.com/atom/ns#' term='c#'/><category scheme='http://www.blogger.com/atom/ns#' term='rhino'/><category scheme='http://www.blogger.com/atom/ns#' term='unit test'/><title type='text'>Restricciones sobre parámetros objetos con Rhino Mocks</title><content type='html'>&lt;strong&gt;Restricciones sobre parámetros objetos con Rhino Mocks&lt;/strong&gt;&lt;br /&gt;
    &lt;br /&gt;
    Entre las restricciones que nombré en el post anterior se encuentra Property, la
    misma posee algunos métodos estáticos que nos permiten colocar restricciones a los
    parámetros de nuestros métodos "moquedos" en caso que sean tipos de referencia (objetos)
    y quisieramos verificar una condición para una de sus propiedades. Por ejemplo que
    quisieramos que la propiedad "nombre" del objeto "persona" que es parámetro del
    método "GuardarPersona" en una clase "moqueada" sea exáctamente "Leonardo" o contenga
    el texto "Lalo Landa", o incluso que contenga otras restriccions formadas por las
    otras clases para restricción como Is, Text, etc. vamos diréctamente al código para
    ver su utilización:&lt;br /&gt;
    &lt;br /&gt;
    &lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
&lt;pre class="csharpcode"&gt;
[TestClass]
&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; RhinoMocksPropertyConstraint
{
    &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;
    &lt;span class="rem"&gt;/// Property.Value("nombrePropiedad", "valor")&lt;/span&gt;
    &lt;span class="rem"&gt;/// quiere decir que el valor de la propiedad nombrePropiedad debe&lt;/span&gt;
    &lt;span class="rem"&gt;/// ser valor cuando se utiliza como parámetro de un método "moquedo"&lt;/span&gt;
    &lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;
    [TestMethod]
    [ExpectedException(&lt;span class="kwrd"&gt;typeof&lt;/span&gt;(ExpectationViolationException))]
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; PropertyValueConstraint()
    {
        MockRepository mocker = &lt;span class="kwrd"&gt;new&lt;/span&gt; MockRepository();

        IProcessor mockProcessor = mocker.CreateMock&amp;lt;IProcessor&amp;gt;();

        &lt;span class="kwrd"&gt;using&lt;/span&gt; (mocker.Record())
        {
            &lt;span class="rem"&gt;//le decimos al Rhino que la llamada al método debe hacerce&lt;/span&gt;
            &lt;span class="rem"&gt;//con un objeto ClaseParametro cuya propiedad ValorTexto&lt;/span&gt;
            &lt;span class="rem"&gt;//debe tener valor "HOLA"&lt;/span&gt;
            Expect.Call(
                mockProcessor.TestMethod(&lt;span class="kwrd"&gt;null&lt;/span&gt;))
                .IgnoreArguments()
                .Return(&lt;span class="str"&gt;""&lt;/span&gt;)
                .Constraints(Property.Value(&lt;span class="str"&gt;"ValorTexto"&lt;/span&gt;, &lt;span class="str"&gt;"HOLA"&lt;/span&gt;))
                .Repeat.Any();
        }
        &lt;span class="rem"&gt;//Este assert es correcto, el valor de la propiedad ValorTexto es HOLA&lt;/span&gt;
        Assert.IsTrue(mockProcessor.TestMethod(&lt;span class="kwrd"&gt;new&lt;/span&gt; ClaseParametro(0, &lt;span class="str"&gt;"HOLA"&lt;/span&gt;)).Length == 0);

        &lt;span class="rem"&gt;//Lanza una ExpectationViolationExpcetion porque el valor de la propiedad&lt;/span&gt;
        &lt;span class="rem"&gt;//ValorTexto no es "HOLA"&lt;/span&gt;
        Assert.IsTrue(mockProcessor.TestMethod(&lt;span class="kwrd"&gt;new&lt;/span&gt; ClaseParametro(0, &lt;span class="str"&gt;"CHAU"&lt;/span&gt;)).Length == 0);

        mocker.VerifyAll();
    }
    
    &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;
    &lt;span class="rem"&gt;/// PropertyValueConstraint permite poner cualquier tipo de constraint&lt;/span&gt;
    &lt;span class="rem"&gt;/// en una propiedad de un objeto que es parámetro de un método "moquedo"&lt;/span&gt;
    &lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;
    [TestMethod]
    [ExpectedException(&lt;span class="kwrd"&gt;typeof&lt;/span&gt;(ExpectationViolationException))]
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; PropertyConstraintValueConstraint()
    {
        MockRepository mocker = &lt;span class="kwrd"&gt;new&lt;/span&gt; MockRepository();

        IProcessor mockProcessor = mocker.CreateMock&amp;lt;IProcessor&amp;gt;();

        &lt;span class="kwrd"&gt;using&lt;/span&gt; (mocker.Record())
        {
            &lt;span class="rem"&gt;//le decimos al Rhino que la llamada al método debe hacerce&lt;/span&gt;
            &lt;span class="rem"&gt;//con un objeto ClaseParametro cuya propiedad ValorTexto&lt;/span&gt;
            &lt;span class="rem"&gt;//debe tener contener en su valor ek texto "HOLA"&lt;/span&gt;
            Expect.Call(
                mockProcessor.TestMethod(&lt;span class="kwrd"&gt;null&lt;/span&gt;))
                .IgnoreArguments()
                .Return(&lt;span class="str"&gt;""&lt;/span&gt;)
                .Constraints(Property.ValueConstraint(&lt;span class="str"&gt;"ValorTexto"&lt;/span&gt;, Text.Contains(&lt;span class="str"&gt;"HOLA"&lt;/span&gt;)))
                .Repeat.Any();
        }
        &lt;span class="rem"&gt;//Este assert es correcto, el valor de la propiedad ValorTexto contiene la palabra HOLA&lt;/span&gt;
        Assert.IsTrue(mockProcessor.TestMethod(&lt;span class="kwrd"&gt;new&lt;/span&gt; ClaseParametro(0, &lt;span class="str"&gt;"HOLA MUNDO"&lt;/span&gt;)).Length == 0);

        &lt;span class="rem"&gt;//Lanza una ExpectationViolationExpcetion porque el valor de la propiedad&lt;/span&gt;
        &lt;span class="rem"&gt;//ValorTexto no contiene "HOLA"&lt;/span&gt;
        Assert.IsTrue(mockProcessor.TestMethod(&lt;span class="kwrd"&gt;new&lt;/span&gt; ClaseParametro(0, &lt;span class="str"&gt;"CHAU"&lt;/span&gt;)).Length == 0);

        mocker.VerifyAll();
    }

    &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;
    &lt;span class="rem"&gt;/// IsNull, el objeto parámetro del método "moquedo" deber ser null&lt;/span&gt;
    &lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;
    [TestMethod]
    [ExpectedException(&lt;span class="kwrd"&gt;typeof&lt;/span&gt;(ExpectationViolationException))]
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; PropertyConstraintIsNullConstraint()
    {
        MockRepository mocker = &lt;span class="kwrd"&gt;new&lt;/span&gt; MockRepository();

        IProcessor mockProcessor = mocker.CreateMock&amp;lt;IProcessor&amp;gt;();

        &lt;span class="kwrd"&gt;using&lt;/span&gt; (mocker.Record())
        {
            &lt;span class="rem"&gt;//le decimos al Rhino que la llamada al método debe hacerce&lt;/span&gt;
            &lt;span class="rem"&gt;//con un parámetro null&lt;/span&gt;
            Expect.Call(
                mockProcessor.TestMethod(&lt;span class="kwrd"&gt;null&lt;/span&gt;))
                .IgnoreArguments()
                .Return(&lt;span class="str"&gt;""&lt;/span&gt;)
                .Constraints(Property.IsNull(&lt;span class="str"&gt;"ValorTexto"&lt;/span&gt;))
                .Repeat.Any();
        }
        &lt;span class="rem"&gt;//Este assert es correcto, el parámetro es null&lt;/span&gt;
        Assert.IsTrue(mockProcessor.TestMethod(&lt;span class="kwrd"&gt;new&lt;/span&gt; ClaseParametro(0,&lt;span class="kwrd"&gt;null&lt;/span&gt;)).Length==0);

        &lt;span class="rem"&gt;//Lanza una ExpectationViolationExpcetion porque el valor de la propiedad&lt;/span&gt;
        &lt;span class="rem"&gt;//no es null&lt;/span&gt;
        Assert.IsTrue(mockProcessor.TestMethod(&lt;span class="kwrd"&gt;new&lt;/span&gt; ClaseParametro(0, &lt;span class="str"&gt;""&lt;/span&gt;)).Length == 0);

        mocker.VerifyAll();
    }
}



&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;interface&lt;/span&gt; IProcessor
{
    &lt;span class="kwrd"&gt;string&lt;/span&gt; TestMethod(ClaseParametro parametro);
}

&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; ClaseParametro
{
    &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;int&lt;/span&gt; _valorEntero;
    &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; _valorTexto;

    &lt;span class="kwrd"&gt;public&lt;/span&gt; ClaseParametro(&lt;span class="kwrd"&gt;int&lt;/span&gt; valorEntero, &lt;span class="kwrd"&gt;string&lt;/span&gt; valorTexto)
    {
        &lt;span class="kwrd"&gt;this&lt;/span&gt;.ValorEntero = valorEntero;
        &lt;span class="kwrd"&gt;this&lt;/span&gt;.ValorTexto = valorTexto;
    }

    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; ValorTexto
    {
        get { &lt;span class="kwrd"&gt;return&lt;/span&gt; _valorTexto; }
        set { _valorTexto = &lt;span class="kwrd"&gt;value&lt;/span&gt;; }
    }


    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;int&lt;/span&gt; ValorEntero
    {
        get { &lt;span class="kwrd"&gt;return&lt;/span&gt; _valorEntero; }
        set { _valorEntero = &lt;span class="kwrd"&gt;value&lt;/span&gt;; }
    }

}&lt;/pre&gt;
&lt;p&gt;Simple, hay algunos métodos más en esta clase pero creo que no vale la pena explicarlos ya que son muy intuítivos, saludos.&lt;div class="blogger-post-footer"&gt;Leonardo Micheloni&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/148524916779753368-8596076691350780476?l=leomicheloni.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://leomicheloni.blogspot.com/feeds/8596076691350780476/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=148524916779753368&amp;postID=8596076691350780476' title='1 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default/8596076691350780476'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default/8596076691350780476'/><link rel='alternate' type='text/html' href='http://leomicheloni.blogspot.com/2008/06/restricciones-sobre-parmetros-objetos.html' title='Restricciones sobre parámetros objetos con Rhino Mocks'/><author><name>Leonardo Micheloni</name><uri>http://www.blogger.com/profile/12085246040181097881</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='30' src='http://3.bp.blogspot.com/_t9Bh42Thfqo/S6TVOJqYWcI/AAAAAAAAANU/MlZc6HpYZis/S220/yo+laguito+en+col%C3%B3n.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-148524916779753368.post-7071766290677411589</id><published>2008-06-16T23:01:00.002-03:00</published><updated>2008-07-16T11:42:03.813-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='c#'/><category scheme='http://www.blogger.com/atom/ns#' term='rhino'/><category scheme='http://www.blogger.com/atom/ns#' term='unit test'/><title type='text'>Restricciones con Rhino Mock 3.4 o Constraints en Rhino Mocks, o cómo limitar los valores de los parámetros con mock objects</title><content type='html'>&lt;strong&gt;
    Rhino Mocks Constraints o restricciones en Rhino Mocks 3.4&lt;/strong&gt;
    &lt;br /&gt;
    Otra de las características interesantes de un framework de mock es la posiblidad
    de poner restricciones a los valores que pueden recibir los parámetros de un objeto
    que estamos "moqueando", esto es, que nuestra Expectation permite definir que el
    método sólo pueda ser llamado con ciertos valores en sus parámetros, por ejemplo
    que un parámetros sea exáctamente 2 o mayor de 5 y mucho más.&lt;br /&gt;
    &lt;br /&gt;
    &lt;strong&gt;
    Tipos de restricciones en Rhino Mocks&lt;br /&gt;
    &lt;/strong&gt;
    &lt;br /&gt;
    Básicamente tenemos cuatro clases con métodos estáticos para trabajar con restricciones:
    &lt;br /&gt;
    &lt;br /&gt;
    Is : permite establecer restricciones del tipo "igual a" "mayor que"&lt;br /&gt;
    Property: para trabajar con propiedades, por ejemplo propiedad tal debe tener tal
    valor&lt;br /&gt;
    List: para las listas, se pueden poner restricciones a la cantidad de elementos,
    etc.&lt;br /&gt;
    Text: para trabajar con texto, por ejemplo poner una validación basada en una expresión
    regular&lt;br /&gt;
    &lt;br /&gt;
    En caso de no cumplir con una restricción para un parámetro Rhino nos lanza una
    bonita ExpectationViolationException, veámos un ejemplo:&lt;br /&gt;
    &lt;br /&gt;
    &lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
&lt;pre class="csharpcode"&gt;[TestClass]
&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; UnitTest1
{

    MockRepository _mocker;

    &lt;span class="kwrd"&gt;public&lt;/span&gt; MockRepository Mocker
    {
        get
        {
            &lt;span class="kwrd"&gt;if&lt;/span&gt; (_mocker == &lt;span class="kwrd"&gt;null&lt;/span&gt;)
                _mocker = &lt;span class="kwrd"&gt;new&lt;/span&gt; MockRepository();
            &lt;span class="kwrd"&gt;return&lt;/span&gt; _mocker;
        }
    }

    [TestMethod]
    [ExpectedException(&lt;span class="kwrd"&gt;typeof&lt;/span&gt;(ExpectationViolationException))]
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; ViolacionDeConstraint()
    {
        IProcessor mockProcessor = Mocker.CreateMock&amp;lt;IProcessor&amp;gt;();
        
        &lt;span class="kwrd"&gt;using&lt;/span&gt; (Mocker.Record())
        {
            &lt;span class="rem"&gt;//grabamos un comportamiento que dice que se espera&lt;/span&gt;
            &lt;span class="rem"&gt;//una llamada el método Test en la cual el argumento&lt;/span&gt;
            &lt;span class="rem"&gt;//debe ser mayor a 3&lt;/span&gt;
            Expect.Call(mockProcessor.Test(0)).
                Return(&lt;span class="kwrd"&gt;true&lt;/span&gt;).
                Constraints(Is.GreaterThan(3));
        }

        &lt;span class="kwrd"&gt;using&lt;/span&gt; (Mocker.Playback())
        {
            &lt;span class="rem"&gt;//funciona porque devuelve true en caso de llamar al métod&lt;/span&gt;
            &lt;span class="rem"&gt;//con un parámetro mayor que 3&lt;/span&gt;
            Assert.IsTrue(mockProcessor.Test(4));
            &lt;span class="rem"&gt;//Lanza una ExpectationViolationException porque el parámetro&lt;/span&gt;
            &lt;span class="rem"&gt;//viola el constraint&lt;/span&gt;
            Assert.IsTrue(mockProcessor.Test(2));            
        }
    }
}

&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;interface&lt;/span&gt; IProcessor
{
    &lt;span class="kwrd"&gt;bool&lt;/span&gt; Test(&lt;span class="kwrd"&gt;int&lt;/span&gt; &lt;span class="kwrd"&gt;value&lt;/span&gt;);
}&lt;/pre&gt;
    &lt;br /&gt;
    Para terminar, los remito a la &lt;a href="http://www.ayende.com/wiki/Rhino+Mocks+Constraints.ashx"&gt;
        documentación&lt;/a&gt; para conocer todas las restricciones, saludos.&lt;br /&gt;
    &lt;br /&gt;&lt;div class="blogger-post-footer"&gt;Leonardo Micheloni&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/148524916779753368-7071766290677411589?l=leomicheloni.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://leomicheloni.blogspot.com/feeds/7071766290677411589/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=148524916779753368&amp;postID=7071766290677411589' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default/7071766290677411589'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default/7071766290677411589'/><link rel='alternate' type='text/html' href='http://leomicheloni.blogspot.com/2008/06/restricciones-con-rhino-mock-34-o.html' title='Restricciones con Rhino Mock 3.4 o Constraints en Rhino Mocks, o cómo limitar los valores de los parámetros con mock objects'/><author><name>Leonardo Micheloni</name><uri>http://www.blogger.com/profile/12085246040181097881</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='30' src='http://3.bp.blogspot.com/_t9Bh42Thfqo/S6TVOJqYWcI/AAAAAAAAANU/MlZc6HpYZis/S220/yo+laguito+en+col%C3%B3n.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-148524916779753368.post-6809996490152192012</id><published>2008-06-09T16:43:00.003-03:00</published><updated>2008-06-09T16:48:51.621-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='mock'/><category scheme='http://www.blogger.com/atom/ns#' term='c#'/><category scheme='http://www.blogger.com/atom/ns#' term='rhino'/><category scheme='http://www.blogger.com/atom/ns#' term='unit test'/><title type='text'>"Moqueando" clases abstractas con Rhino Mocks</title><content type='html'>&lt;p&gt;
Una interesante funcionalidad de RhinoMocks es la posiblidad de crear instancias de clases abstractas y utilizar sus método concretos sin más que la ayuda de los PartialMocks, incluso podemos dar comportamiento a sus métodos abstractos, con los cual es posible probar una clase abstracta en su totalidad sin tener una implementación concreta, vamos a ver en el famoso código autodescriptivo.
&lt;/p&gt;
&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
&lt;pre class="csharpcode"&gt;
[TestClass]
&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; UnitTest1
{
    MockRepository _repository;
    &lt;span class="kwrd"&gt;public&lt;/span&gt; MockRepository Mocker
    {
        get
        {
            &lt;span class="kwrd"&gt;if&lt;/span&gt; (_repository == &lt;span class="kwrd"&gt;null&lt;/span&gt;)
                _repository = &lt;span class="kwrd"&gt;new&lt;/span&gt; MockRepository();
            &lt;span class="kwrd"&gt;return&lt;/span&gt; _repository;
        }
    }
    &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;
    &lt;span class="rem"&gt;/// Los PartialMocks nos permiten crear instancias de clases abstractas&lt;/span&gt;
    &lt;span class="rem"&gt;/// para poder probar los métodos concretos con su implementación real&lt;/span&gt;
    &lt;span class="rem"&gt;/// sin necesidad de heredar en una clase concreta&lt;/span&gt;
    &lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;
    [TestMethod]
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; PartialMockTest()
    {
        &lt;span class="rem"&gt;//se pueden crear instancias de clases abstractas para utlizar los&lt;/span&gt;
        &lt;span class="rem"&gt;//métodos concretos&lt;/span&gt;
        AbstractProcessor processor = Mocker.PartialMock&amp;lt;AbstractProcessor&amp;gt;();

        &lt;span class="rem"&gt;//y funciona :-)&lt;/span&gt;
        Assert.AreEqual&amp;lt;&lt;span class="kwrd"&gt;string&lt;/span&gt;&amp;gt;(&lt;span class="str"&gt;"Hola Leonardo"&lt;/span&gt;, processor.Saludar(&lt;span class="str"&gt;"Leonardo"&lt;/span&gt;));
    }

    &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;
    &lt;span class="rem"&gt;/// No podemos modificar el comportamiento de método concreto&lt;/span&gt;
    &lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;
    [TestMethod]
    [ExpectedException(&lt;span class="kwrd"&gt;typeof&lt;/span&gt;(InvalidOperationException))]
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; PartialMockConfigurarComportamientoMetodoConcreto()
    {
        AbstractProcessor processor = Mocker.PartialMock&amp;lt;AbstractProcessor&amp;gt;();

        &lt;span class="kwrd"&gt;using&lt;/span&gt; (Mocker.Record())
            Expect.Call(processor.Saludar(&lt;span class="str"&gt;""&lt;/span&gt;)).Return(&lt;span class="str"&gt;"Método modificado"&lt;/span&gt;).IgnoreArguments();

        &lt;span class="rem"&gt;//utilizo la sintáxis de Record-Playback en lugar de ReplayAll-VerifyAll&lt;/span&gt;
        &lt;span class="kwrd"&gt;using&lt;/span&gt; (Mocker.Playback())
            Assert.AreEqual&amp;lt;&lt;span class="kwrd"&gt;string&lt;/span&gt;&amp;gt;(&lt;span class="str"&gt;"Método modificado"&lt;/span&gt;, processor.MetodoUno());
    }

    &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;
    &lt;span class="rem"&gt;/// También podemos configurar el comportamiento&lt;/span&gt;
    &lt;span class="rem"&gt;/// de los métodos abstratos y concretos&lt;/span&gt;
    &lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;
    [TestMethod]
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; PartialMockConfigurarComportamientoMetodoAbstracto()
    {
        &lt;span class="rem"&gt;//se pueden crear instancias de clases abstractas para utlizar los&lt;/span&gt;
        &lt;span class="rem"&gt;//métodos concretos&lt;/span&gt;
        AbstractProcessor processor = Mocker.PartialMock&amp;lt;AbstractProcessor&amp;gt;();

        &lt;span class="kwrd"&gt;using&lt;/span&gt; (Mocker.Record())
            Expect.Call(processor.MetodoUno()).Return(&lt;span class="str"&gt;"Metodo1 moqueado"&lt;/span&gt;);

        &lt;span class="rem"&gt;//utilizo la sintáxis de Record-Playback en lugar de ReplayAll-VerifyAll&lt;/span&gt;
        &lt;span class="kwrd"&gt;using&lt;/span&gt; (Mocker.Playback())
            Assert.AreEqual&amp;lt;&lt;span class="kwrd"&gt;string&lt;/span&gt;&amp;gt;(&lt;span class="str"&gt;"Metodo1 moqueado"&lt;/span&gt;, processor.MetodoUno());
    }
}

&lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;
&lt;span class="rem"&gt;/// Una clase abstracta no se puede instanciar directamente&lt;/span&gt;
&lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;
&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;abstract&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; AbstractProcessor
{
    &lt;span class="rem"&gt;//método abstracto, sin implementaci´n&lt;/span&gt;
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;abstract&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; MetodoUno();
    &lt;span class="rem"&gt;//método concreto, para usarlo es necesario heredar esta clase&lt;/span&gt;
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; Saludar(&lt;span class="kwrd"&gt;string&lt;/span&gt; nombre)
    {
        &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt;.Format(&lt;span class="str"&gt;"Hola {0}"&lt;/span&gt;, nombre);
    }
}
&lt;/pre&gt;
&lt;br /&gt;
&lt;p&gt;Interesante, utilizalo con sabiduría, saludos&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;Leonardo Micheloni&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/148524916779753368-6809996490152192012?l=leomicheloni.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://leomicheloni.blogspot.com/feeds/6809996490152192012/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=148524916779753368&amp;postID=6809996490152192012' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default/6809996490152192012'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default/6809996490152192012'/><link rel='alternate' type='text/html' href='http://leomicheloni.blogspot.com/2008/06/moqueando-clases-abstractas-con-rhino.html' title='&quot;Moqueando&quot; clases abstractas con Rhino Mocks'/><author><name>Leonardo Micheloni</name><uri>http://www.blogger.com/profile/12085246040181097881</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='30' src='http://3.bp.blogspot.com/_t9Bh42Thfqo/S6TVOJqYWcI/AAAAAAAAANU/MlZc6HpYZis/S220/yo+laguito+en+col%C3%B3n.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-148524916779753368.post-314576888739959592</id><published>2008-06-08T23:27:00.004-03:00</published><updated>2008-06-09T16:49:06.357-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='mock'/><category scheme='http://www.blogger.com/atom/ns#' term='c#'/><category scheme='http://www.blogger.com/atom/ns#' term='rhino'/><category scheme='http://www.blogger.com/atom/ns#' term='unit test'/><title type='text'>Diferentes tipos de Mock Objects con Rhino Mocks</title><content type='html'>&lt;p&gt;Rhino Mocks nos permite crear diferentes tipos de Mock Objetcts según nuestras necesidades, en total son 3 Mocks, Dynamic Mocks y Stubs, simplemente vamos a ver un ejemplo autodescriptivo, para ver los tres tipos y sus aplicaciones.&lt;/p&gt;

&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
&lt;pre class="csharpcode"&gt;
[TestClass]
&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; UnitTest1
{
    MockRepository _repository;

    MockRepository Mocker
    {
        get
        {
            &lt;span class="kwrd"&gt;if&lt;/span&gt; (_repository == &lt;span class="kwrd"&gt;null&lt;/span&gt;)
                _repository = &lt;span class="kwrd"&gt;new&lt;/span&gt; MockRepository();
            &lt;span class="kwrd"&gt;return&lt;/span&gt; _repository;
        }
    }

    &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;
    &lt;span class="rem"&gt;/// Los mock dynamic no verifican la llamada a ningún tipo de métod&lt;/span&gt;
    &lt;span class="rem"&gt;/// sirven por ejemplo para configurar respuestas a métodos pero no verificar&lt;/span&gt;
    &lt;span class="rem"&gt;/// si son llamados&lt;/span&gt;
    &lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;
    [TestMethod]
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; DynamicTest()
    {
        IDummy MockDummy = Mocker.DynamicMock&amp;lt;IDummy&amp;gt;();

        Expect.Call(MockDummy.DummyMethod(&lt;span class="str"&gt;""&lt;/span&gt;)).Return(&lt;span class="str"&gt;"hola"&lt;/span&gt;);

        Mocker.ReplayAll();

        &lt;span class="rem"&gt;//se retorna el valor configurado&lt;/span&gt;
        Assert.AreEqual(&lt;span class="str"&gt;"hola"&lt;/span&gt;,MockDummy.DummyMethod(&lt;span class="str"&gt;""&lt;/span&gt;));

        &lt;span class="rem"&gt;//nada me impide llamar varias veces a un método a pesar de no encontrase&lt;/span&gt;
        &lt;span class="rem"&gt;//configurado para ello, sin embargo no retorna el valor configurado&lt;/span&gt;
        Assert.AreEqual(&lt;span class="kwrd"&gt;null&lt;/span&gt;, MockDummy.DummyMethod(&lt;span class="str"&gt;""&lt;/span&gt;));

        Mocker.VerifyAll();
    }

    &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;
    &lt;span class="rem"&gt;/// Un mock (Strict replay)&lt;/span&gt;
    &lt;span class="rem"&gt;/// verifica que se llamen a los métodos esperados y sólo a estos&lt;/span&gt;
    &lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;
    [TestMethod]
    [ExpectedException(&lt;span class="kwrd"&gt;typeof&lt;/span&gt;(ExpectationViolationException))]
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; MockLlamadaMetodoNoEsperado()
    {
        IDummy MockDummy = Mocker.CreateMock&amp;lt;IDummy&amp;gt;();
        
        Mocker.ReplayAll();

        &lt;span class="rem"&gt;//lanza una excepción de uso inválido porque se llama a un método que no se esperaba&lt;/span&gt;
        MockDummy.DummyMethod(&lt;span class="str"&gt;""&lt;/span&gt;);

        Mocker.VerifyAll();
    }
    &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;
    &lt;span class="rem"&gt;/// Un mock (Strict replay)&lt;/span&gt;
    &lt;span class="rem"&gt;/// verifica que se llamen a los métodos esperados y sólo a estos&lt;/span&gt;
    &lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;
    [TestMethod]
    [ExpectedException(&lt;span class="kwrd"&gt;typeof&lt;/span&gt;(ExpectationViolationException))]
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; MockNoSeLlamoEsperado()
    {
        IDummy MockDummy = Mocker.CreateMock&amp;lt;IDummy&amp;gt;();
        Expect.Call(MockDummy.DummyMethod(&lt;span class="str"&gt;""&lt;/span&gt;)).Return(&lt;span class="kwrd"&gt;null&lt;/span&gt;);

        Mocker.ReplayAll();

        &lt;span class="rem"&gt;//lanza una excepción de uso inválido porque no se llamó a un método esperado&lt;/span&gt;
        Mocker.VerifyAll();
    }

    &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;
    &lt;span class="rem"&gt;/// Un stub no tiene comportamiento, es útil para crear objetos&lt;/span&gt;
    &lt;span class="rem"&gt;/// que necesitamos para hacer funcionar otros pero de los que &lt;/span&gt;
    &lt;span class="rem"&gt;/// no esperamos ningún comportamiento&lt;/span&gt;
    &lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;
    [TestMethod]
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; StubTest()
    {
        IUsuario usuario = Mocker.Stub&amp;lt;IUsuario&amp;gt;();

        Mocker.ReplayAll();

        &lt;span class="rem"&gt;//el stub se comporta como un objeto con propiedades&lt;/span&gt;
        usuario.Nombre = &lt;span class="str"&gt;"leonardo"&lt;/span&gt;;

        Assert.AreEqual&amp;lt;&lt;span class="kwrd"&gt;string&lt;/span&gt;&amp;gt;(&lt;span class="str"&gt;"leonardo"&lt;/span&gt;, usuario.Nombre);

        Mocker.VerifyAll();
    }

    &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;
    &lt;span class="rem"&gt;/// Un stub no tiene comportamiento, es útil para crear objetos&lt;/span&gt;
    &lt;span class="rem"&gt;/// que necesitamos para hacer funcionar otros pero de los que &lt;/span&gt;
    &lt;span class="rem"&gt;/// no esperamos ningún comportamiento&lt;/span&gt;
    &lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;
    [TestMethod]
    [ExpectedException(&lt;span class="kwrd"&gt;typeof&lt;/span&gt;(InvalidOperationException))]
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; StubNoAceptaComportamientoTest()
    {
        IUsuario usuario = Mocker.Stub&amp;lt;IUsuario&amp;gt;();
        &lt;span class="rem"&gt;//el stub no acepta comportamiento, lanza una excepción acá&lt;/span&gt;
        Expect.Call(usuario.ToString()).Return(&lt;span class="str"&gt;"usuario"&lt;/span&gt;);

        Mocker.ReplayAll();

        usuario.Nombre = &lt;span class="str"&gt;"leonardo"&lt;/span&gt;;

        Assert.AreEqual&amp;lt;&lt;span class="kwrd"&gt;string&lt;/span&gt;&amp;gt;(&lt;span class="str"&gt;"leonardo"&lt;/span&gt;, usuario.Nombre);

        Mocker.VerifyAll();
    }
}
&lt;/pre&gt;

&lt;p&gt;Sencillo, hasta la próxima&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;Leonardo Micheloni&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/148524916779753368-314576888739959592?l=leomicheloni.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://leomicheloni.blogspot.com/feeds/314576888739959592/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=148524916779753368&amp;postID=314576888739959592' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default/314576888739959592'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default/314576888739959592'/><link rel='alternate' type='text/html' href='http://leomicheloni.blogspot.com/2008/06/diferentes-tipos-de-mock-objects-con.html' title='Diferentes tipos de Mock Objects con Rhino Mocks'/><author><name>Leonardo Micheloni</name><uri>http://www.blogger.com/profile/12085246040181097881</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='30' src='http://3.bp.blogspot.com/_t9Bh42Thfqo/S6TVOJqYWcI/AAAAAAAAANU/MlZc6HpYZis/S220/yo+laguito+en+col%C3%B3n.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-148524916779753368.post-8064088469553853734</id><published>2008-05-28T14:53:00.002-03:00</published><updated>2008-05-28T20:55:02.319-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Generics'/><category scheme='http://www.blogger.com/atom/ns#' term='c#'/><title type='text'>Cómo poner constraints en método genéricos</title><content type='html'>Una de las cosas que me olvidé de nombrar en el &lt;a href="http://leomicheloni.blogspot.com/2008/04/generics-en-c-o-tipos-genricos-en-c.html"&gt;post sobre generics&lt;/a&gt; es cómo poner
        un constaint para un método, bueno, por ahora eso sólo así que acá está&lt;br /&gt;
        &lt;br /&gt;
        Como poner un constraint a un método&lt;br /&gt;
        &lt;br /&gt;
 
 &lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Probar&amp;lt;T&amp;gt;(T param) &lt;span class="kwrd"&gt;where&lt;/span&gt; T : IBase
{
}&lt;/pre&gt;

&lt;p&gt;
En este código simplemente decimos que el tipo T del parámetro param debe implementar
        la interfaz IBase, esto hasta la próxima.&lt;/p&gt;

&lt;p&gt;Actualización&lt;/p&gt;
&lt;p&gt;Como indica mi colega &lt;a href="http://slion2000.blogspot.com/"&gt;Eduardo&lt;/a&gt; el ejemplo que puse es muy malo, en realidad casi no sirve para nada, en casos muy raros que si bien se me ocurren son muy confusos, veámos casos en los que un constraint es útil en un método&lt;/p&gt;

&lt;b&gt;Tipos de restricciones&lt;/b&gt;&lt;br /&gt;
&lt;p&gt;Vamos a ver tres casos en los que las restricciones pueden ser útiles en los métodos&lt;/p&gt;

&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
&lt;pre class="csharpcode"&gt;
&lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;
&lt;span class="rem"&gt;/// new() indica que T tiene que tener un constructor sin parámetros&lt;/span&gt;
&lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;
&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Probar2&amp;lt;T&amp;gt;(T param) &lt;span class="kwrd"&gt;where&lt;/span&gt; T : &lt;span class="kwrd"&gt;new&lt;/span&gt;()
{
    &lt;span class="rem"&gt;//Si quito la restrucción no puedo hacer esto &lt;/span&gt;
    &lt;span class="rem"&gt;//porque T no tiene implícitamente un constructor sin parámetros&lt;/span&gt;
    T var = &lt;span class="kwrd"&gt;new&lt;/span&gt; T();
}

&lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;
&lt;span class="rem"&gt;/// class indica que T será un tipo por referencia&lt;/span&gt;
&lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;
&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Probar3&amp;lt;T&amp;gt;(T param1, T param2) &lt;span class="kwrd"&gt;where&lt;/span&gt; T : &lt;span class="kwrd"&gt;class&lt;/span&gt;
{            
}

&lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;
&lt;span class="rem"&gt;/// struct indica que T tiene que se un tipo no Nullable&lt;/span&gt;
&lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;
&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Probar4&amp;lt;T&amp;gt;(T param1, T param2) &lt;span class="kwrd"&gt;where&lt;/span&gt; T: &lt;span class="kwrd"&gt;struct&lt;/span&gt;
{
    &lt;span class="rem"&gt;//Si quito la restricción no puedo hacer esto&lt;/span&gt;
    &lt;span class="rem"&gt;//porque el método Nullable.Compare espere dos tipos nos nullables (underlying types)&lt;/span&gt;
    &lt;span class="rem"&gt;//sin embargo se pueden pasar estructuras&lt;/span&gt;
    Nullable.Compare&amp;lt;T&amp;gt;(param1, param2);
}
&lt;/pre&gt;

&lt;p&gt;Bueno, espero que les sirva y gracias Eduardo por la observación&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;Leonardo Micheloni&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/148524916779753368-8064088469553853734?l=leomicheloni.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://leomicheloni.blogspot.com/feeds/8064088469553853734/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=148524916779753368&amp;postID=8064088469553853734' title='4 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default/8064088469553853734'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default/8064088469553853734'/><link rel='alternate' type='text/html' href='http://leomicheloni.blogspot.com/2008/05/cmo-poner-constraints-en-mtodo-genricos.html' title='Cómo poner constraints en método genéricos'/><author><name>Leonardo Micheloni</name><uri>http://www.blogger.com/profile/12085246040181097881</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='30' src='http://3.bp.blogspot.com/_t9Bh42Thfqo/S6TVOJqYWcI/AAAAAAAAANU/MlZc6HpYZis/S220/yo+laguito+en+col%C3%B3n.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-148524916779753368.post-390403805205797375</id><published>2008-05-22T10:34:00.004-03:00</published><updated>2008-05-22T10:40:00.550-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Visual Studio'/><category scheme='http://www.blogger.com/atom/ns#' term='unit test'/><title type='text'>Pruebas manejadas por datos con VIsual Studio o Data Driven Test</title><content type='html'>&lt;strong&gt;Pruebas manejadas por datos con Visual Studio&lt;/strong&gt;&lt;br /&gt;
        &lt;br /&gt;
        Un utilidad interesante del Visual Studio es la posibilidad de que un método de
        prueba (TestMethod) se ejecute múltiples veces a partir de un origen de datos, qué
        quiero decir con esto, teniendo un origen de datos (SqlServer, Access, Oracle, Excel,
        cualquier cosa que tenga un conector .net) podemos hacer que el IDE de Visual Studio
        ejecute un método de prueba (un TestMethod) una vez por cada registro de un origen
        de datos.&lt;br /&gt;
        Por ejemplo, podemos tenes un método para probar un cierto algorítmo pero como no
        podemos tener todos los casos de prueba claro de entemano (quiero decir los posibles
        datos de entrada) podemos hacer que el método los tome del origen de datos y se
        ejecute una vez por cada registros, esto nos permite dos cosas:&lt;br /&gt;
        &lt;br /&gt;
        -Poder dejar para más adelante todos los casos posibles, no pensarlo ahora, o porque
        no los sabemos o porque no queremos o lo que sea.&lt;br /&gt;
        -Delegar a otra persona (funcional tal vez) la tarea de crear los datos de entrada
        e incluso ejecutar la prueba unitaria&lt;br /&gt;
        &lt;br /&gt;
        Por supuesto, no podemos saber de antemano que van a poner, así que una forma astuta
        (que obviamente no se me ocurrió a mí) es poner una columna adicional con el resultado
        esperado, pero bueno, basta, vamos al código&lt;br /&gt;
        &lt;br /&gt;
        
        &lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
&lt;pre class="csharpcode"&gt;&lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;
&lt;span class="rem"&gt;/// Este método se ejecuta una vez por cada fila de la tabla&lt;/span&gt;
&lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;
[TestMethod]
[DataSource(
  &lt;span class="str"&gt;"System.Data.Odbc"&lt;/span&gt;, 
    &lt;span class="str"&gt;@"Dsn=Excel Files;
    dbq=C:\\Pruebas\\datosPruebaDB\\origenDatos.xls;
        defaultdir=C:\\Pruebas\\datosPruebaDB;
    driverid=790;
    maxbuffersize=2048;
    pagetimeout=5"&lt;/span&gt;, 
    &lt;span class="str"&gt;"Datos$"&lt;/span&gt;, 
    DataAccessMethod.Sequential)]
&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; TestMethod1()
{
   &lt;span class="rem"&gt;//recuperados los valores del origen de datos&lt;/span&gt;
    &lt;span class="kwrd"&gt;string&lt;/span&gt; valor = &lt;span class="kwrd"&gt;this&lt;/span&gt;.Context.DataRow[&lt;span class="str"&gt;"Valor"&lt;/span&gt;].ToString();
    &lt;span class="kwrd"&gt;bool&lt;/span&gt; resultado = Convert.ToBoolean(&lt;span class="kwrd"&gt;this&lt;/span&gt;.Context.DataRow[&lt;span class="str"&gt;"Resultado"&lt;/span&gt;]);

    &lt;span class="rem"&gt;//nuestra función de validación de largos&lt;/span&gt;
    &lt;span class="kwrd"&gt;bool&lt;/span&gt; largoCorrecto = (valor.Length&amp;gt;6);

    &lt;span class="rem"&gt;//assert para verficar si coincide con el resultado esperado&lt;/span&gt;
    Assert.AreEqual&amp;lt;&lt;span class="kwrd"&gt;bool&lt;/span&gt;&amp;gt;(largoCorrecto, resultado);

}&lt;/pre&gt;

&lt;p&gt;
Y listo es todo, es este caso mi archivo Excel tiene esta forma&lt;/p&gt;
        &lt;p&gt;
            &lt;table id="TABLE1" border="0" cellpadding="0" cellspacing="0" style="width: 96pt;
                border-collapse: collapse" width="128" x:str="" onclick="return TABLE1_onclick()"&gt;
                &lt;colgroup&gt;
                    &lt;col span="2" style="width: 48pt" width="64" /&gt;
                &lt;/colgroup&gt;
                &lt;tr height="17" style="height: 12.75pt"&gt;
                    &lt;td height="17" style="border-right: #ffffff; border-top: #ffffff; border-left: #ffffff;
                        width: 48pt; border-bottom: #ffffff; height: 12.75pt; background-color: transparent"
                        width="64"&gt;
                        &lt;span style="font-size: 10pt; font-family: Arial"&gt;Valor&lt;/span&gt;&lt;/td&gt;
                    &lt;td style="border-right: #ffffff; border-top: #ffffff; font-size: 10pt; border-left: #ffffff;
                        width: 48pt; border-bottom: #ffffff; font-family: Arial; background-color: transparent"
                        width="64"&gt;
                        Resultado&lt;/td&gt;
                &lt;/tr&gt;
                &lt;tr height="17" style="font-size: 10pt; font-family: Arial; height: 12.75pt"&gt;
                    &lt;td class="xl22" height="17" style="border-right: #ffffff; border-top: #ffffff; border-left: #ffffff;
                        width: 48pt; border-bottom: #ffffff; height: 12.75pt; background-color: transparent"
                        width="64"&gt;
                        Leonardo&lt;/td&gt;
                    &lt;td align="right" class="xl23" style="border-right: #ffffff; border-top: #ffffff;
                        border-left: #ffffff; width: 48pt; border-bottom: #ffffff; background-color: transparent"
                        width="64" x:num=""&gt;
                        1&lt;/td&gt;
                &lt;/tr&gt;
                &lt;tr height="17" style="font-size: 10pt; font-family: Arial; height: 12.75pt"&gt;
                    &lt;td class="xl22" height="17" style="border-right: #ffffff; border-top: #ffffff; border-left: #ffffff;
                        width: 48pt; border-bottom: #ffffff; height: 12.75pt; background-color: transparent"
                        width="64"&gt;
                        Gabriel&lt;/td&gt;
                    &lt;td align="right" class="xl23" style="border-right: #ffffff; border-top: #ffffff;
                        border-left: #ffffff; width: 48pt; border-bottom: #ffffff; background-color: transparent"
                        width="64" x:num=""&gt;
                        1&lt;/td&gt;
                &lt;/tr&gt;
                &lt;tr height="17" style="font-size: 10pt; font-family: Arial; height: 12.75pt"&gt;
                    &lt;td class="xl22" height="17" style="border-right: #ffffff; border-top: #ffffff; border-left: #ffffff;
                        width: 48pt; border-bottom: #ffffff; height: 12.75pt; background-color: transparent"
                        width="64"&gt;
                        Hernán&lt;/td&gt;
                    &lt;td align="right" class="xl23" style="border-right: #ffffff; border-top: #ffffff;
                        border-left: #ffffff; width: 48pt; border-bottom: #ffffff; background-color: transparent"
                        width="64" x:num=""&gt;
                        0&lt;/td&gt;
                &lt;/tr&gt;
                &lt;tr height="17" style="font-size: 10pt; font-family: Arial; height: 12.75pt"&gt;
                    &lt;td class="xl22" height="17" style="border-right: #ffffff; border-top: #ffffff; border-left: #ffffff;
                        width: 48pt; border-bottom: #ffffff; height: 12.75pt; background-color: transparent"
                        width="64"&gt;
                        Gerardo&lt;/td&gt;
                    &lt;td align="right" class="xl23" style="border-right: #ffffff; border-top: #ffffff;
                        border-left: #ffffff; width: 48pt; border-bottom: #ffffff; background-color: transparent"
                        width="64" x:num=""&gt;
                        1&lt;/td&gt;
                &lt;/tr&gt;
                &lt;tr height="17" style="font-size: 10pt; font-family: Arial; height: 12.75pt"&gt;
                    &lt;td class="xl22" height="17" style="border-right: #ffffff; border-top: #ffffff; border-left: #ffffff;
                        width: 48pt; border-bottom: #ffffff; height: 12.75pt; background-color: transparent"
                        width="64"&gt;
                        Norberto&lt;/td&gt;
                    &lt;td align="right" class="xl23" style="border-right: #ffffff; border-top: #ffffff;
                        border-left: #ffffff; width: 48pt; border-bottom: #ffffff; background-color: transparent"
                        width="64" x:num=""&gt;
                        1&lt;/td&gt;
                &lt;/tr&gt;
                &lt;tr height="17" style="font-size: 10pt; font-family: Arial; height: 12.75pt"&gt;
                    &lt;td class="xl22" height="17" style="border-right: #ffffff; border-top: #ffffff; border-left: #ffffff;
                        width: 48pt; border-bottom: #ffffff; height: 12.75pt; background-color: transparent"
                        width="64"&gt;
                        Adrián&lt;/td&gt;
                    &lt;td align="right" class="xl23" style="border-right: #ffffff; border-top: #ffffff;
                        border-left: #ffffff; width: 48pt; border-bottom: #ffffff; background-color: transparent"
                        width="64" x:num=""&gt;
                        0&lt;/td&gt;
                &lt;/tr&gt;
                &lt;tr height="17" style="font-size: 10pt; font-family: Arial; height: 12.75pt"&gt;
                    &lt;td class="xl22" height="17" style="border-right: #ffffff; border-top: #ffffff; border-left: #ffffff;
                        width: 48pt; border-bottom: #ffffff; height: 12.75pt; background-color: transparent"
                        width="64"&gt;
                        Angel&lt;/td&gt;
                    &lt;td align="right" class="xl23" style="border-right: #ffffff; border-top: #ffffff;
                        border-left: #ffffff; width: 48pt; border-bottom: #ffffff; background-color: transparent"
                        width="64" x:num=""&gt;
                        0&lt;/td&gt;
                &lt;/tr&gt;
                &lt;tr height="17" style="font-size: 10pt; font-family: Arial; height: 12.75pt"&gt;
                    &lt;td class="xl22" height="17" style="border-right: #ffffff; border-top: #ffffff; border-left: #ffffff;
                        width: 48pt; border-bottom: #ffffff; height: 12.75pt; background-color: transparent"
                        width="64"&gt;
                        Albino&lt;/td&gt;
                    &lt;td align="right" class="xl23" style="border-right: #ffffff; border-top: #ffffff;
                        border-left: #ffffff; width: 48pt; border-bottom: #ffffff; background-color: transparent"
                        width="64" x:num=""&gt;
                        0&lt;/td&gt;
                &lt;/tr&gt;
            &lt;/table&gt;
        &lt;/p&gt;
        &lt;p&gt;
            Lo hice con Excel para que sea más visual, por supuesto, la hoja donde se encutran
            estos datos se llaman "Datos" y me conecto por ODBC. La columna con el encabezado valor es el valor de entrada y la que se llama resultado es el resultado esperado, como puede verse simplemente agrego un atriburo en el método indicando el origen de datos y después recupero la fila actual con el TestContext.&lt;/p&gt;
        &lt;p&gt;
            Enjoy,&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;Leonardo Micheloni&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/148524916779753368-390403805205797375?l=leomicheloni.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://leomicheloni.blogspot.com/feeds/390403805205797375/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=148524916779753368&amp;postID=390403805205797375' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default/390403805205797375'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default/390403805205797375'/><link rel='alternate' type='text/html' href='http://leomicheloni.blogspot.com/2008/05/pruebas-manejadas-por-datos-con-visual.html' title='Pruebas manejadas por datos con VIsual Studio o Data Driven Test'/><author><name>Leonardo Micheloni</name><uri>http://www.blogger.com/profile/12085246040181097881</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='30' src='http://3.bp.blogspot.com/_t9Bh42Thfqo/S6TVOJqYWcI/AAAAAAAAANU/MlZc6HpYZis/S220/yo+laguito+en+col%C3%B3n.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-148524916779753368.post-4182807781591425371</id><published>2008-05-17T00:35:00.004-03:00</published><updated>2008-05-17T00:39:49.161-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='agiles2008'/><title type='text'>Primeras Jornadas Ágiles de Latinoamérica 2008</title><content type='html'>El proyecto del cual participo como organizador (realmente mi participación es más que escueta)
&lt;a href="http://www.agiles.2008.org/"&gt;http://www.agiles.2008.org/&lt;/a&gt; ya es Agile Alliance Compliant &lt;a href="http://www.scrumalliance.org/events/10-giles"&gt;http://www.scrumalliance.org/events/10-giles&lt;/a&gt;-, felicitaciones al equipo, a Juan, Ricardo y todos los demás.

Saludos.&lt;div class="blogger-post-footer"&gt;Leonardo Micheloni&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/148524916779753368-4182807781591425371?l=leomicheloni.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://leomicheloni.blogspot.com/feeds/4182807781591425371/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=148524916779753368&amp;postID=4182807781591425371' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default/4182807781591425371'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/148524916779753368/posts/default/4182807781591425371'/><link rel='alternate' type='text/html' href='http://leomicheloni.blogspot.com/2008/05/primeras-jornadas-giles-de-latinoamrica.html' title='Primeras Jornadas Ágiles de Latinoamérica 2008'/><author><name>Leonardo Micheloni</name><uri>http://www.blogger.com/profile/12085246040181097881</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='30' src='http://3.bp.blogspot.com/_t9Bh42Thfqo/S6TVOJqYWcI/AAAAAAAAANU/MlZc6HpYZis/S220/yo+laguito+en+col%C3%B3n.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-148524916779753368.post-6458850769463589747</id><published>2008-05-16T23:54:00.002-03:00</published><updated>2008-05-17T00:25:39.045-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='excepciones'/><category scheme='http://www.blogger.com/atom/ns#' term='c#'/><title type='text'>Sobre excepciones en .net</title><content type='html'>&lt;p&gt;
            &lt;b&gt;Excepciones &lt;/b&gt;
        &lt;/p&gt;
        &lt;p&gt;
            El framework de .net utiliza un mecanismo para informar de situaciones que 
            impiden el flujo normal del código como un error, se trata de las excepciones.&lt;/p&gt;
    &lt;p&gt;
&amp;nbsp;Las excepciones se pueden producir por muchas razones, en general situaciones 
        inesperadas, por ejemplo querer acceder a un archivo que no existe, esto produce 
        una horrible excepción, veamos un poco de código
    &lt;/p&gt;
    &lt;p&gt;
        &lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
&lt;pre class="csharpcode"&gt;
&lt;span class="kwrd"&gt;using&lt;/span&gt; (StreamReader reader = &lt;span class="kwrd"&gt;new&lt;/span&gt; StreamReader(&lt;span class="str"&gt;@"c:\archivoQueNoExiste.txt"&lt;/span&gt;))
{
 reader.ReadLine();
 reader.Close();
}
&lt;/pre&gt;
    &lt;p&gt;
&amp;nbsp;Si lo ejecutamos recibimos una fea fea excepción del tipo FileNotFoundException, 
        ok esto es lo que queríamos, ahora bien, qué hacemos ahora?
    &lt;/p&gt;
    &lt;p&gt;
        &lt;b&gt;Alternativa ante las excepciones &lt;/b&gt;
    &lt;/p&gt;
    &lt;p&gt;
        Inicialmente podemos hacer dos cosas cuando nos encontramos con una porción de 
        código que puede lanzar una excepción     &lt;/p&gt;
    &lt;p&gt;
        -Atraparla en un bloque catch
    &lt;/p&gt;
    &lt;p&gt;
        -No hacer nada
    &lt;/p&gt;
    &lt;p&gt;
        Comencemos por el primer caso
    &lt;/p&gt;
&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
&lt;pre class="csharpcode"&gt;
&lt;span class="kwrd"&gt;try&lt;/span&gt; 
{ 
 &lt;span class="kwrd"&gt;using&lt;/span&gt; (StreamReader reader = &lt;span class="kwrd"&gt;new&lt;/span&gt; StreamReader(&lt;span class="str"&gt;@"c:\archivoQueNoExiste.txt"&lt;/span&gt;)) 
 { 
  reader.ReadLine();
  reader.Close();
 } 
}&lt;span class="kwrd"&gt;catch&lt;/span&gt; 
{ 
 &lt;span class="kwrd"&gt;throw&lt;/span&gt;;
} 
&lt;/pre&gt;
    &lt;p&gt;
        Qué pasa acá, bien, lo mismo que no hacer nada, porque en el bloque volvemos a 
        lanzar la excepción por lo tanto es lo mismo que no hacer nada
    &lt;/p&gt;
    &lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
&lt;pre class="csharpcode"&gt;
&lt;span class="kwrd"&gt;try&lt;/span&gt; 
{ 
 &lt;span class="kwrd"&gt;using&lt;/span&gt; (StreamReader reader = &lt;span class="kwrd"&gt;new&lt;/span&gt; StreamReader(&lt;span class="str"&gt;@"c:\archivoQueNoExiste.txt"&lt;/span&gt;)) 
 { 
 reader.ReadLine();
 reader.Close();
 } 
}&lt;span class="kwrd"&gt;catch&lt;/span&gt;(Exception ex) 
{ 
 &lt;span class="kwrd"&gt;throw&lt;/span&gt; ex;
} 
&lt;/pre&gt;
        
    &lt;p&gt;
        Este ejemplo es peor que el anterior porque no sólo no hacemos nada sino que 
        además al colocar Exeception ex y luego hacer throw borramos toda la información 
        que se recopiló hasta el momento del error (el stack trace) por lo tanto, no 
        sólo no la manipulamos sino que además perdemos valiosa información.
    &lt;/p&gt;
    &lt;p&gt;
        Enseñanza:
    &lt;/p&gt;
    &lt;p&gt;
        -Si atrapamos una excepción y la relanzamos haciendo referencia al objeto 
        Exception borramos el stack trace.
    &lt;/p&gt;
    &lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
&lt;pre class="csharpcode"&gt;
&lt;span class="kwrd"&gt;try&lt;/span&gt; 
{ 
 &lt;span class="kwrd"&gt;using&lt;/span&gt; (StreamReader reader = &lt;span class="kwrd"&gt;new&lt;/span&gt; StreamReader(&lt;span class="str"&gt;@"c:\archivoQueNoExiste.txt"&lt;/span&gt;)) 
 { 
  reader.ReadLine();
  reader.Close();
 } 
}&lt;span class="kwrd"&gt;catch&lt;/span&gt;(Exception ex) 
{ 
 GuardarInformacionDelError(ex);
} 
&lt;/pre&gt;
        
    &lt;p&gt;
        Esto es bastante más elegante, ocurre un error y guardamos la información para 
        un análisis posterior, sin embargo esto nos lleva a una enseñanza mejor, po
