martes, 25 de diciembre de 2007

Dependency Injection DI

Al parecer este patron de diseño para resolver el problema de acomplamiento que sufren las aplicaciones que impeden la extensibilidad, mantenibilidad y la prueba o testing esta muy de moda. Es el patron que nos llevará a otro nivel en las aplicaciones desacopladas y a la extensibilidad. Esto no es nuevo, y viene del mundo java (su mayor expositor el chief computer scientiest y gurú de los patrones de diseño Martin Fowler pero microsoft y su equipo ha hecho para la comunidad de usuarios de desarrollo de la plataforma .net una aplicación y solución muy elegante. Y fue estrenada con las factories.

viernes, 30 de noviembre de 2007

Reunion del 21 de noviembre del 2007 en la comunidad

Estuvimos con los muchachos de la comunidad compartiendo este tema. Que a mi juicio la estrella y el patrón de moda hoy es Dependency Injection, este fue mi estrella en la presentación, que haré un tema para desarrollar este patron con ejemplos en mi blog.

Tema: Principios de OOP con .NET Framework 2.0

Expositor: Manolo Herrera(MVP Client Application 2007).

Fecha: Miércoles 21 de Noviembre de 2007
Horario: 6:30 P.M. – 8:30 P.M.
Lugar: Hotel Intercontinental Salón Rosul
Costo: Gratis
Otros: Habrá Coffee Break, Parqueo y Premios

Invita: Comunidad de Desarrolladores .NET en Guatemala, con Apoyo de Microsoft de Guatemala


Atentamente,

Manolo Herrera
Coordinador de La Comunidad de Desarrolladores .NET en Guatemala (http://groups.google.com/group/LaComunidadNET/web/memorias-de-las-reuniones-de-la-comunidad)

jueves, 22 de noviembre de 2007

Could not load file or assembly 'CrystalDecisions.CrystalReports.Engine, Version=10.5.3700.0, Culture=neutral, PublicKeyToken=692fbea5521e1304' or one of its dependencies. The system cannot find the file specified.

Could not load file or assembly 'CrystalDecisions.CrystalReports.Engine,
Version=10.5.3700.0, Culture=neutral, PublicKeyToken=692fbea5521e1304' or one of its dependencies.
The system cannot find the file specified.


Este error me dio cuando abri un proyecto vs 2005 en VS2008 y mantuve la compatibilidad al framework 2.0, al parecer no solo me convierte la solucion sino que me agrega unos nuevos dlls del engine de crystal para aplicaciones web y me convierte los archivos de reportes rpt de Crystal.

Que hay que hacer:

agregar en el web config la referencia de los assemblies viejos de 2005 en la seccion runtime como se muestra aquí:

<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="CrystalDecisions.CrystalReports.Engine " publicKeyToken="692fbea5521e1304"/>
<bindingRedirect oldVersion="10.5.3700.0" newVersion="10.2.3600.0"/>
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="CrystalDecisions.CrystalReports.Shared" publicKeyToken="692fbea5521e1304"/>
<bindingRedirect oldVersion="10.5.3700.0" newVersion=" 10.2.3600.0"/>
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="CrystalDecisions.Shared" publicKeyToken="692fbea5521e1304"/>
<bindingRedirect oldVersion="10.5.3700.0" newVersion="10.2.3600.0"/>
</dependentAssembly>
</assemblyBinding>
</runtime>


y luego se reemplaza las referencias de los dlls viejos por los nuevos y se copia los archivos rpt del proyecto de 2005 original, Se compila la solución y listo todo funciona como debe.

Por lo demas VS 2008 parece muy estable y si corre lado a lado con las versiones anteriores de 2005. Si intentan instalar el runtime de crystal 2008 necesitan una produc key misterioso que no se sabe cual es o si instalar los de redistribución que viene en la media de VS 2008, les cambia el error por este:

Aquí la referencia de la solución parcial:
http://tim.mackey.ie/default,month,2007-05.aspx (Lo que no incluye me imagino porque no era sobre la version RTM que cambia los archivos rpt de crystal y es necesario copiar los originales a los que le hace backup).

Retrieving the COM class factory for component with CLSID {5FF57840-5172-4482-9CA3-541C7878AE0F} failed due to the following error: 800736b1.

Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

Exception Details: System.Runtime.InteropServices.COMException: Retrieving the COM class factory for component with CLSID {5FF57840-5172-4482-9CA3-541C7878AE0F} failed due to the following error: 800736b1.

Source Error:


An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.


Stack Trace:


[COMException (0x800736b1): Retrieving the COM class factory for component with CLSID {5FF57840-5172-4482-9CA3-541C7878AE0F} failed due to the following error: 800736b1.]    CrystalDecisions.CrystalReports.Engine.ReportDocument..cctor() +182  [TypeInitializationException: The type initializer for 'CrystalDecisions.CrystalReports.Engine.ReportDocument' threw an exception.]    CrystalDecisions.CrystalReports.Engine.ReportDocument..ctor() +0    LaUnion.Sistema.CajaYBancos.ServicioReporte.PreparaReportDocument(String pathReporte, DataSet dataSource, Hashtable fields) in C:\DevProjects\Guatemala\Main\Source\LaUnion.Sistema.CajaYBancos.AplicacionWeb\Code\Servicios\ServicioReporte.cs:260    LaUnion.Sistema.CajaYBancos.ServicioReporte.ReporteEnMemoria(String pathReporte, DataSet dataSource, Hashtable fields, ExportFormatType formatoSalidaImpresion) in C:\DevProjects\Guatemala\Main\Source\LaUnion.Sistema.CajaYBancos.AplicacionWeb\Code\Servicios\ServicioReporte.cs:251    LaUnion.Sistema.CajaYBancos.Operaciones.LiquidacionCajaChicaV3.Imprimir() in C:\DevProjects\Guatemala\Main\Source\LaUnion.Sistema.CajaYBancos.AplicacionWeb\Operaciones\LiquidacionCajaChicaV3.aspx.cs:947    LaUnion.Sistema.CajaYBancos.Operaciones.LiquidacionCajaChicaV3.BotonesLiquidacionCajaChica_Click(Object sender, BotonesLiquidacionCajaChicaEventArgs e) in C:\DevProjects\Guatemala\Main\Source\LaUnion.Sistema.CajaYBancos.AplicacionWeb\Operaciones\LiquidacionCajaChicaV3.aspx.cs:68    LaUnion.Sistema.CajaYBancos.BotonesLiquidacionCajaChicaCOM.OnPresionado(Object sender, BotonesLiquidacionCajaChicaEventArgs e) in C:\DevProjects\Guatemala\Main\Source\LaUnion.Sistema.CajaYBancos.AplicacionWeb\Componentes\CajaYBancos\BotonesLiquidacionCajaChicaCOM.ascx.cs:26    LaUnion.Sistema.CajaYBancos.BotonesLiquidacionCajaChicaCOM.CargarImprimir() in C:\DevProjects\Guatemala\Main\Source\LaUnion.Sistema.CajaYBancos.AplicacionWeb\Componentes\CajaYBancos\BotonesLiquidacionCajaChicaCOM.ascx.cs:314    LaUnion.Sistema.CajaYBancos.BotonesLiquidacionCajaChicaCOM.Opcion_Click(Object sender, EventArgs e) in C:\DevProjects\Guatemala\Main\Source\LaUnion.Sistema.CajaYBancos.AplicacionWeb\Componentes\CajaYBancos\BotonesLiquidacionCajaChicaCOM.ascx.cs:188    System.Web.UI.WebControls.LinkButton.OnClick(EventArgs e) +90    System.Web.UI.WebControls.LinkButton.RaisePostBackEvent(String eventArgument) +76    System.Web.UI.WebControls.LinkButton.System.Web.UI.IPostBackEventHandler.RaisePostBackEvent(String eventArgument) +7    System.Web.UI.Page.RaisePostBackEvent(IPostBackEventHandler sourceControl, String eventArgument) +11    System.Web.UI.Page.RaisePostBackEvent(NameValueCollection postData) +177    System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +1746 


Y allí no le he encontrado ninguna solución. Si la encuentran me avisan.

Code4Fun!,


Manolo Herrera

miércoles, 21 de noviembre de 2007

VS 2008 RTM una Version Estable

Mi primer dia con la version VS 2008 RTM emocionante y confiable.  Tengo instalado la version 2003, 2005 y ahora la version 2008 RTM y como lo anuncion Scott Gu esta ultima corre "Side by side".  Por el momento estoy ejecutando mis proyectos en 2008 pero con el framework 2.0 y funciona de maravilla. No noto ninguna lentitud y a decir verdad, el webserver de 2008 parace estar mejorado ya que se ejectua con mayor rápides luego de la primera vez generado.  El designer aunque tengo la opcion de split la parte en el diseño aunque me lo muestra mejor pareciera que no entiendie todos los metatags de mi proyecto en 2.0, pero esta por verse si es el disgner o algunas instrucciones no bien definidas del lado del html o css.  Pero el momento me ha asombrado la estabilidad del producto y la correcta funcionalidad que tiene con proyectos de version anterior como lo es 2.0. Algunas opciones de mejora en la optimizacion de los usings (remove and order) he encontrado en la herramiento de VS 2008, pense encontrar mas opciones de refactor pero no fue asi, supongo que continuaré utilizando ReSharper, haber como funciona con 2008?

--
Code4Fun!,


Manolo Herrera

viernes, 16 de noviembre de 2007

Que paso con el buen uso del TryParse(string, out int variable)


En la version 2.0 del framework con el arribo de Generics, vino los nullables  y los TryParse que cada tipo de dato que lo que pretenden es que evitemos el overhead del try catch para castear un valor que normalmente esta en string a un tipo de dato como un entero.  Este sencillo método que lo tienen todos los tipos primitivos de datos del framework 2.0 en adelante me dan una solución elegante y menos cargada para los tipicos casteos de controles que reciben valores string y es necesario convertirlo a un tipo primitivo como entero, decimal, double, etc.
 
Chequen este ejemplo que lo que no debe de hacerse a partir del framework 2.0 y en adelante.
 
int Codigo = 0;
try
{
      Codigo = Convert.ToInt32(CodigoTextBox.Text);
}catch (Excepction)
{
    blablabla..
}
 
Ahora lo que si podemos hacer gracias a este nuevo metodo incorporado en el framework 2.0:
 
int Codigo = 0;
if ( int.TryParse(CodigoTextBox, out Codigo)
{
    Bla..bla..bla.
}
 
Si logra con éxito realizar el parser entrara en las llaves sino sabremos que no lo hizo.  El valor de Codigo si no logra realizar el parseo siempre es cero.
 
Code4Fun!

Manolo Herrera

Failed to update database because the database is read-only.

Este error es muy común cuando no se tiene la costumbre de trabajar con archivos mdf adjuntos al proyecto web asp.net 2.0 si estas corriendo en IIS 6.0 necesitas darle a la carpeta acceso de escritura y lectura a la cuenta NETWORK SERVICE.

Code4Fun!
 
Manolo

viernes, 12 de octubre de 2007

Proxima reunion de la comunidad VS2008 en Vivo!!!

Tema:

Un vistazo a Visual Studio 2008 Beta 2

Expositor: Manolo Herrera (Coordinador de la comunidad .NET en Guatemala).

Fecha : Miércoles 24 de Octubre de 2007

Horario: 6:30 P.M. – 8:30 P.M.

Lugar: Hotel Intercontinental Salón Rosul

Costo: Gratis

Otros: Habrá Coffee Break, Parqueo y Premios

Invita: Comunidad de Desarrolladores .NET en Guatemala, con Apoyo de Microsoft de Guatemala

Atentamente,

Manolo Herrera

Coordinador de La Comunidad de Desarrolladores .NET en Guatemala (Blog: http://jmhogua.blogspot.com/)

viernes, 5 de octubre de 2007

Imaginese poder depurar la Class Library del .net framework

Increíble pero cierto, cada vez mas vemos a un Microsoft abriendose a la comunidad de usuarios de sus productos, en el blog de Scott Gu http://weblogs.asp.net/scottgu/ podrán encontrar la noticia que Microsoft permitirá a través del acuerdo de una licencia y del producto VS2008 RTM(aunque no disponible para todas las versiones), la capacidad de poder depurar el codigo de la libreria de clases del .net framework. Las especificaciones de lo que se podrá ver esta en la licencia de uso. Para ver la noticia puede acceder:
Releasing the Source Code for the .NET Framework Libraries
http://weblogs.asp.net/scottgu/archive/2007/10/03/releasing-the-source-code-for-the-net-framework-libraries.aspx


Ademas informa que a finales de este año ya se tendrá disponible la version RTM del VS 2008, otra gran noticia!!.

Que lo disfruten y seguramente aprenderemos mucho a comprender mejor el .net framework y su poder.

Hasta la proxima.

jueves, 27 de septiembre de 2007

Como saber si una columna existe en una tabla desde T-SQL

Creo que es un util consejo para los que nos gusta escribr codigo:

Como saber si una columna existe en una tabla

select

*

FROM

INFORMATION_SCHEMA.COLUMNS AS c1

where

c1.column_name = 'ValorCYBRegimenRetencionTributaria'

and

c1.table_name = 'cybFactura'
Mire esto como saber en que tablas utiliza esta columna

select

Table_Name

FROM

INFORMATION_SCHEMA.COLUMNS AS c1

where

c1.column_name = 'CodigoEmpresa'


Hasta le proximo consejo o artículo. CODE4FUN!

miércoles, 15 de agosto de 2007

Meaningful

Según el significado encontrado en google esta palabra significa: having a meaning or purpose; "a meaningful explanation"; "a meaningful discussion"; "a meaningful pause"

En español podríamos traducir como: Que tiene un significado o propósito. Esto nos da una mejor idea del significado de esta palabra que dentro del desarrollo ágil el desarrollo guiado por pruebas de sus siglas en inglés TDD (Test Driven Development), acuña el termino Meaningful o Significativo para el nombramiento de los métodos (ver pagina 42 del libro Test-Driven Development in Microsoft .NET de James W. Newkirk y Alexei A. Vorontsov).

Veamos literalmente el comentario: "Meaningful method names are important for code readability and in turn its overall maintainnability. In short, method names should convey their intentions." Que parafraseado diriamos lo siguiente: los nombres de los metodos deben de comunicar un significado o su propósito para la legilibidad del codigo y mantenimiento. En resumen los nombres de los métodos deberían transmitir sus intenciones.

Y para ser justos haremos una referencia al libro de Refactoring de Martin Fowler que acuño el concepto de Refactorización del código y que luego surgió el concepto de desarrollo ágil. De hecho en el libro de TDD la referencia de la página hace mención de la refactorización como una disciplina importante a tomar en cuenta en el desarrollo guiado por pruebas o TDD.

En la página 273 del libro de Martin Fowler "Refactoring". Una técnica de la refactorización es el renombrar los métodos y explica: La Motivación es los métodos deberían nombrarse en un forma que comunica su intención. Recuerde su código es para humanos primero y luego para la computadora. Termina diciendo los buenos nombres, es una habilidad que requiere práctica: mejorar esta habilidad es la llave para empezar ha ser un verdadero programador hábil.

Y para finalizar esta introducción al termino Meaningful vamos acuñar el concepto de la disciplina llamada "Refactoring", no es mas que: El proceso de cambiar un sistema de software de tal manera que este no altera el comportamiento externo del código pero mejora su estructura interna (Pagina XVI del libro en mención).

Esta breve introducción da pie al siguiente ejemplo:

Escenario:

Es una aplicación Web y tenemos un control de usuario que hace la búsqueda de proveedores por tres filtros que serán controles de texto o Textbox identificados de la siguiente manera: NITProveedor, NombreProveedor y CodigoInternoProveedor. Deseamos darle el comportamiento de tal forma que si el usuario ingresa un valor en alguno de los controles de entrada los otros controles nos aseguremos que es eliminado cualquier valor de los demás controles para que al buscar por cualquiera de ellos y no por la combinación de varios de ellos nos traiga la información requerida por el usuario.

Para ir directo al grano y delimitar de alguna forma el alcance de este ejemplo no nos detendremos a redactar la parte de búsqueda de la información requerida por el usuario, sino únicamente el comportamiento que deseamos que tenga los controles para mostrar un ejemplo del concepto Meaningful que es la motivación de una de las técnicas de Refactoring de renombrar métodos. El ejemplo esta hecho en Visual Studio 2005 y en C# 2.0 para los que preguntan.

Veamos por una mera referencia o idea visual el código html de la página en la cual vamos a trabajar:

<%@ Page Language="C#" AutoEventWireup="true" Codebehind="TeachingTheConceptMeaningFul.aspx.cs"

Inherits ="TeachingTheConceptMeaningFul" %>

<! DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" " http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

< html xmlns="http://www.w3.org/1999/xhtml">

< head runat="server">

<title>Busqueda de Proveedores</title >

</ head >

< body >

<form id="form1" runat ="server">

<div>

Proveedor:&nbsp;

<asp:TextBox ID ="NITProveedor" runat="server" OnTextChanged="NITProveedor_Cambio"

AutoPostBack="true" ToolTip="Ingrese el NIT del proveedor."/>

&nbsp;

<asp:TextBox ID ="NombreProveedor" runat="server" OnTextChanged="NombreProveedor_Cambio"

AutoPostBack="true" ToolTip="Ingrese el nombre del proveedor."/>

&nbsp;

<asp:TextBox ID ="CodigoInternoProveedor" runat="server" OnTextChanged="CodigoInternoProveedor_Cambio"

AutoPostBack ="true" ToolTip="Ingrese el codigo interno del proveedor."/>

</ div>

</form>

</ body>

</ html>

Veamos la parte remarcada donde esta el caso de nuestro ejemplo, Tenemos los tres controles y cada uno de ellos tiene un evento que se ejecuta cada vez que cambia el valor ingresado en cada uno de los controles de texto la propiedad AutoPostBack nos indica que hará un postbak al servidor cada vez que cambie el texto al perder el foco del control, esto sucede asi por el ambiente Web en que estamos trabajando y la orientación de las aplicaciones asp.net que fueron diseñadas para validar del lado del servidor preferiblemente y no del lado del cliente, aunque se puede. Y por ultimo el útil Tooltip que aparece un recuadro en amarillo que aparece al acercar el cursor sobre el control en el cual estamos navegando.

Ahora veamos el código del lado del servidor que es el que realmente nos interesa.

public partial class TeachingTheConceptMeaningFul : System.Web.UI.Page

{

protected void Page_Load(object sender, EventArgs e)

{

}

protected void NITProveedor_Cambio(object sender, EventArgs e)

{

this.NombreProveedor.Text = null;

this.CodigoInternoProveedor.Text = null;

}

protected void NombreProveedor_Cambio(object sender, EventArgs e)

{

this.NITProveedor.Text = null;

this.CodigoInternoProveedor.Text = null;

}

protected void CodigoInternoProveedor_Cambio(object sender, EventArgs e)

{

this.NITProveedor.Text = null;

this.NombreProveedor.Text = null;

}

}

Al apreciar este código parece que todo esta muy claro y que no es difícil que comprender, pero que pasa si tenemos que agregar otros filtros digamos unos 2 o 3 o tal vez 5 filtros mas deberemos repetir el código y tener el cuidado de no limpiar el contenido del control en el que el usuario. Pero ver asignar null al contenido de cada control de texto verdaderamente comunica el propósito de lo que estamos haciendo?. Bueno no me conteste ahora apliquemos la refactorización a nuestro código para hacerlo mas legible o por lo menos para centralizar las mismas operaciones.

Digamos que vamos a tener un solo método que se conecta a todos los controles y desde allí centralizamos el comportamiento de cada control.

Para ello comentamos el código html original para regresar al código anterior si todo nos sale mal (esto es una buena practica no eliminar el código hasta estar seguro que el cambio quedo bien. Y luego indicamos que el método al cual se pegará el disparar el evento del cambio del texto de cada control es el mismo y lo llamaremos "FiltroProveedor_Cambio". Veamos el código:

< div >

Proveedor:&nbsp;

<asp :TextBox ID="NITProveedor" runat="server" OnTextChanged ="FiltroProveedor_Cambio"

AutoPostBack="true" ToolTip="Ingrese el NIT del proveedor." />

&nbsp;

<asp :TextBox ID="NombreProveedor" runat="server" OnTextChanged ="FiltroProveedor_Cambio"

AutoPostBack="true" ToolTip="Ingrese el nombre del proveedor." />

&nbsp;

<asp:TextBox ID ="CodigoInternoProveedor" runat="server" OnTextChanged="FiltroProveedor_Cambio"

AutoPostBack ="true" ToolTip="Ingrese el codigo interno del proveedor." />

</ div>

Veamos ahora el código del lado del servidor:

protected void FiltroProveedor_Cambio(object sender, EventArgs e)

{

TextBox ControlTexto = (TextBox)sender;

switch (ControlTexto.ID)

{

case "NITProveedor":

this.NombreProveedor.Text = null;

this.CodigoInternoProveedor.Text = null;

break;

case "NombreProveedor":

this.NITProveedor.Text = null;

this.CodigoInternoProveedor.Text = null;

break;

case "CodigoInternoProveedor":

this.NITProveedor.Text = null;

this.NombreProveedor.Text = null;

break;

default :

break;

}

}

Que hicimos ahora, no mucho solo centralizamos el problema, no nos comunica mucho, es prácticamente el mismo código pero así es en la refactorización empezamos con pequeños cambios, para prepararnos para mejorar nuestro código. Es importante mencionar que aunque es valido utilizar el switch como una estructura de selección es muy rígida y que dentro de los patrones de diseño (Gof Design Patterns ) sugiere evitar su uso lo mas posible, con el objetivo que nuestro código sea mas adaptable y extensible con el menor cambio posible. Aplicando este concepto e implementando una solución posible y sencilla modificaremos nuestro código para hacerlo extensible y adaptable a los futuros cambios sin alterar nuestro código luego de estos cambios:

Primero vamos a convertir el div que agrupa los controles como un control de servidor y lo utilizaremos como un contenedor de controles para utilizar un loop para recorrer los controles dentro del div. Así como aparece a continuación:

<div id="ContenedorFiltrosProveedor" runat ="server">

Proveedor:&nbsp;

<asp:TextBox ID ="NITProveedor" runat="server" OnTextChanged="FiltroProveedor_Cambio"

AutoPostBack="true" ToolTip="Ingrese el NIT del proveedor." />

&nbsp;

<asp:TextBox ID ="NombreProveedor" runat="server" OnTextChanged="FiltroProveedor_Cambio"

AutoPostBack="true" ToolTip="Ingrese el nombre del proveedor." />

&nbsp;

<asp:TextBox ID="CodigoInternoProveedor" runat="server" OnTextChanged ="FiltroProveedor_Cambio"

AutoPostBack ="true" ToolTip="Ingrese el codigo interno del proveedor." />

</ div>

Ahora veamos el código del lado del servidor:

protected void FiltroProveedor_Cambio(object sender, EventArgs e)

{

TextBox ControlTexto = (TextBox)sender;

foreach (Control control in this.ContenedorFiltrosProveedor.Controls)

{

TextBox texto = control as TextBox;

if (texto != null)

{

if (texto.ID != ControlTexto.ID)

texto.Text = null;

}

}

}

Esto cambio completamente la rigidez de la estructura switch y nos permitirá agregar otros filtros tipo TextBox sin alterar el código. Veamos un ejemplo, digamos que vamos agregar un nuevo filtro tipo TextBox veamos lo que necesitamos hacer en el código html:

<div id="ContenedorFiltrosProveedor" runat ="server">

Proveedor:&nbsp;

<asp:TextBox ID ="NITProveedor" runat="server" OnTextChanged="FiltroProveedor_Cambio"

AutoPostBack="true" ToolTip="Ingrese el NIT del proveedor." />

&nbsp;

<asp:TextBox ID ="NombreProveedor" runat="server" OnTextChanged="FiltroProveedor_Cambio"

AutoPostBack="true" ToolTip="Ingrese el nombre del proveedor." />

&nbsp;

<asp:TextBox ID ="CodigoInternoProveedor" runat="server" OnTextChanged="FiltroProveedor_Cambio"

AutoPostBack ="true" ToolTip="Ingrese el codigo interno del proveedor." />

<asp:TextBox ID="RazonSocialProveedor" runat="server" OnTextChanged="FiltroProveedor_Cambio"

AutoPostBack="true" ToolTip="Ingrese el nombre de la razón social del proveedor." />

</ div>

Y del lado del servidor, absolutamente nada. Pero un minuto no hemos terminado ser recuerdo el objetivo del ejemplo es aprender a darle un nombre a los métodos que expliquen su propósito o significado, para ello vamos a utilizar la opción de Visual Studio 2005 Refactor (click derecho sobre el código seleccionado( y Seleccionaremos la opción ExtratMethod y ahora si colocaremos el nombre del método, como aparece a continuación:

protected void FiltroProveedor_Cambio(object sender, EventArgs e)

{

TextBox ControlTexto = (TextBox)sender;

LimpiarValorControlesTexto(ControlTexto);

}

private void LimpiarValorControlesTexto(TextBox ControlTexto)

{

foreach (Control control in this.ContenedorFiltrosProveedor.Controls)

{

TextBox texto = control as TextBox;

if (texto != null)

{

if (texto.ID != ControlTexto.ID)

texto.Text = null;

}

}

}

De alguna manera encapsulamos la funcionalidad y explicamos claramente lo que hace nuestro codigo sin decirlo como lo hace ya que esto no es el objetivo de la encapsulación y si del Concepto Meaningful Method Name.

Hasta la próxima. Write Code For Fun!,

Manolo