Showing posts with label csharp. Show all posts
Showing posts with label csharp. Show all posts

Monday, April 13, 2009

Interfaces Web Forms herencia multiple

Interfaces en .NET son pocas veces usadas, por NO decir que jamas son mencionadas, en la implementacion de tu producto de software.

¿Que esta sucediendo? ¿Como te sentis al saber que NO estas utilizando todo el potencial de la tecnologia que tienes en tus manos, hablando estrictamente de C#, claro esta?

Pues VB.NET es un juguete para niños, mas nada :)

Lo que sucede es que NO le encuentras, muchas veces, razon de ser a la necesidad de definir una serie de metodos en una Interface que luego deberas implementar en cada Clase o Class que requiera implementarla.

Suena a realizar trabajo doble. A que NO ganas nada, en realidad, desde un limitado punto de vista.

Nada mas falso que la verdad :)

Las Interfaces tienen una valiosa utilidad. Aquella en la que ese comportamiento definido pueda ser utilizado por otras clases con la finalidad de brindar una valvula de escape al famoso, pero poco usado polimorfismo, en un lenguaje de programacion Orientado a Objetos, quimicamente NO puro, como el caso de los lenguajes de .NET ;)

Por ejemplo, la interfaz IEnumerable, que por cierto es la mas utilizada por el .NET Framework, radica su valiosa utilidad en brindarle la posibilidad a la clase que la implemente en que esta pueda ser iterable sobre el famoso foreach. Omnipresente estructura de control de flujo en el C#.

IEnumerable es de un nivel primario que casi forma parte de la esencia misma del lenguaje C#.NET.

Nosotros ya NO implementamos IEnumerable en nuestras propias clases, pues existen diferentes estructuras de datos, que la implementan y nos facilitan ya esa tarea. Solo nos limitamos a usarla, a sabiendas que existe una estructura de control que la recibe para hacer algo con ella, iterarla. Hablamos del curioso foreach.

He alli la clave para la existencia de Interfaces en el modelo de clases orientadas al producto de software que estamos diseñando.

La necesidad de la existencia de una Clase a la par que defines Interfaces para que las utilizen y hagan algo con ellas, el trabajo pesado. Es decir, para que estas sean parte de la implementacion de un comportamiento de orden superior por el cual fueron concebidos.

¿Se entiende? ¿Toy hablando piedras?

Un ejemplo por favor...!

Bueno, el mas trivial de todos se encuentra en la definicion de un Modelo de Clases e Interfaces para el manejo de Web Forms y Web User Controls en productos de software con conectividad a Base de Datos.

Los Web Forms asumen la gestion de las acciones realizadas por el usuario e implementan el comportamiento, como respuesta a dichas acciones.

Los Web User Controls realizan las tareas a un nivel especifico de detalle, hacen el trabajo laborioso: asignar valores a los TextBox, llenar un DropDownList, recolectar los valores seteados de su propia estructura en un Business Entity y entregarselos a quien lo solicita, and other stuffs :)

En ese sentido, son los Web User Controls candidatos ideales a implementar tus propias Interfaces, previamente definidas, con la intencion de centralizar ciertos comportamientos e implementarlos a nivel de Web Forms.

En concreto, tendras una clase UIPage que hereda de Page, facilitando cierta funcionalidad comunmente usada.

class UIPage : Page
{
protected override void OnLoad( EventArgs e )
{
if( ! this.IsPostBack )
{
this.FirstRequest();
}
}

protected virtual void FirstRequest() { }

protected override void OnInit( EventArgs e )
{
this.DefineHandlers();
this.DefineObjects();
}

protected virtual void DefineHandlers() { }
protected virtual void DefineObjects() { }

// Otras tantas funcionalidades
}

A la vez, tendras una clase UIPageForm que hereda de UIPage

class UIPageForm<TForm> : UIPage
where TForm : IForm
{
protected virtual TForm MyForm
{
get { throw new NotImplementedException(); }
}

// Otras tantas funcionalidades
}

Asi mismo, tendras una clase UIPageEdit que hereda de UIPageForm, centralizando el comportamiento para editar los elementos de ciertas entidades de negocio.

class UIPageEdit<TForm, TAtom> : UIPageForm<TForm>
where TForm : IFormEdit<TAtom>
where TAtom : ITransaction
{
protected virtual TAtom MyAtom
{
get { throw new NotImplementedException(); }
}

// Otras tantas funcionalidades
}

Ahora, imaginemos que se requiere un nuevo comportamiento, por el cual al editar un Business Entity sobre el Web Form, uno de los datos ingresados por el usuario, sobre la vista o View, deba ser unico. Permitiendo la posibilidad de validar aquello a traves de una opcion especial en el View. Asi como, tambien, estrictamente validable al elegir la opcion Save.

Entonces optaremos por una implementacion como esta:

class UIPageEditValidate<TForm, TAtom> :
UIPageEdit <TForm, TAtom>
where TForm : IFormEdit<TAtom>, IFormValidate
where TAtom : ITransaction
{
// Se varia el comportamiento base sobre este contexto
// para soportar el nuevo requerimiento.
}

Ahora, se requiere que ciertos Web Forms soporten el manejo de informacion historica por cada registro, permitiendo navegar sobre dicho historico a traves del mismo Web Form.

Este nuevo requerimiento podria aplicar tanto a Web Forms que soporten la funcionalidad de IFormValidate como a los que NO.

Aqui empieza nuestro problema, como consecuencia de la NO existencia de una herencia multiple de clases, como lo pregona aquella preciosa teoria de la POO, que tanto añoramos.

Si nuestro C# fuese un lenguaje Orientado a Objetos quimicamente puro, bastaria implementar la funcionalidad requerida sobre una clase llamada Navigator, llamada asi para efectos didacticos, y hacer que los Web Forms que requieran dicha funcionalidad la herenden, a la par que heredan su tradicional clase base, que en el mas alto nivel hereda de Page.

Pero NO es posible, entonces tendremos que buscar una forma de superar esta limitacion tecnica.

En esa busqueda, el uso correcto de Interfaces sera la solucion para este requerimiento, definiendo una interfaz INavigator y una clase llamada ConcreteNavigator.

Haciendo una simple analogia, con fines didacticos, INavigator seria como IEnumerable y a su vez ConcreteNavigator seria como la estructura de control foreach. Aquella que hace algo con la interfaz, que la utiliza en el contexto de la implementacion de un comportamiento de orden superior a la simple definicion de una Interfaz.

En ese sentido, tendriamos algo como esto para la interfaz INavigator:

public interface INavigator
{
event EventHandler PreviousClicked;
event EventHandler CurrentClicked;
event EventHandler NextClicked;

void StatusPrevious( Boolean enabled );
void StatusCurrent( Boolean enabled );
void StatusNext( Boolean enabled );
}

Por su parte la clase ConcreteNavigator tendria una implementacion como esta.

public class ConcreteNavigator<TForm, TAtom>
where TAtom : IHasHistory, IBuildHistory<TAtom>
where TForm : IFormEditHistory<TAtom>
{
StateBag _viewstate;
INavigator _navigator;
TForm _form;
TAtom _atom;

public ConcreteNavigator(
StateBag viewstate,
INavigator navigator,
TForm form,
TAtom atom )
{
this._viewstate = viewstate;
this._navigator = navigator;
this._form = form;
this._atom = atom;
}

public void DoPreviousClicked()
{
// Implementacion del comportamiento requerido
// usando los parametros entregados
// al instanciar ConcreteNavigator
// estando INavigator como parte de ellos.
}

public void DoNextClicked()
{
// Idem
}
public void DoCurrentClicked()
{
// Idem
}
}

Entonces se definiran dos nuevas clases para aquellos Web Forms que requieran utilizar el comportamiento plasmado en ConcreteNavigator.

Asi, tendremos las clase UIPageEditNavigator que hereda de UIPageEdit utilizando una instancia de ConcreteNavigator.

public class UIPageEditNavigator<TForm, TAtom> :
UIPageEdit<TForm, TAtom>
where TAtom : ITransaction, IHasHistory, IBuildHistory<TAtom>
where TForm : IFormEditHistory<TAtom>
{
private ConcreteNavigator<TForm, TAtom> _concrete;

protected virtual INavigator MyNatigator
{
get { throw new NotImplementedException(); }
}

protected override void DefineObjects()
{
this._concrete = new ConcreteNavigator<TForm, TAtom>(
this.ViewState,
this.MyNavigator,
this.MyForm,
this.MyAtom );
}

private void MyNavigator_PreviousClicked( Object sender, EventArgs e )
{
this._concrete.DoPreviousClicked();
}

// Otras tanta funcionalidades que se ajustan con
// lo soportado por ConcreteNavigator
}

De la misma forma, definimos la clase UIPageEditValidateNavigator que hereda de la clase UIPageEditValidate utilizando una instancia de ConcreteNavigator

public class UIPageEditValidateNavigator<TForm, TAtom> :
UIPageEditValidate<TForm, TAtom>
where TAtom : ITransaction, IHasHistory, IBuildHistory<TAtom>
where TForm : IFormEditHistory<TAtom>, IFormValidate
{
private ConcreteNavigator<TForm, TAtom> _concrete;

protected virtual INavigator MyNatigator
{
get { throw new NotImplementedException(); }
}

protected override void DefineObjects()
{
this._concrete = new ConcreteNavigator<TForm, TAtom>(
this.ViewState,
this.MyNavigator,
this.MyForm,
this.MyAtom );
}

private void MyNavigator_PreviousClicked( Object sender, EventArgs e )
{
this._concrete.DoPreviousClicked();
}

// Otras tanta funcionalidades que se ajustan con
// lo soportado por ConcreteNavigator
}


De esta manera, se supera la limitacion tecnica de la NO herencia multiple de clases inexistente en los lenguajes de .NET, como C#.

La clase ConcreteNavigator hace el trabajo pesado de una funcionalidad que luego es posible reflejar en diferentes clases, evitando el COPY & PASTE.

Al NO lograr este nivel de abstraccion, estaremos con seguridad, dejando de utilizar todas las bondades que la tecnologia nos brinda, hablamos de la POO.

Nuestro producto de software muy probablemente este disgregado de codigo, como consecuencia irresponsable del COPY & PASTE por everywhere.

Haciendo de este dolorasemente mantenible y vergonzosamente presentable :)

Wednesday, April 08, 2009

Por que usar interfaces en .NET

¿Por que usar interfaces en .NET?

Es la pregunta que siempre aflora cada vez que te encuentras implementando un modelo de clases que se ajuste a la realidad de negocio para el cual debes encontrar una solucion y en la que estas involucrado.

La Programacion Orientada a Objetos, aka POO, nos enseña que uno de los pilares de su existencia es la herencia, en sentido estricto: la herencia multiple.

La herencia multiple de clases es una bondad de la POO, pero al tocarse con la cruda realidad encuentra dificil su implementacion, sin brindarle estabilidad al modelo de clases construido.

Dificil implementacion en el sentido, de una flexibilidad atroz, que en algun momento escape de nuestro control y permita la construccion posterior de comportamientos NO concebidos por el negocio, plasmadas en la construccion de ese modelo de clases que vienes implementando.

La herencia multiple permite que pueda converger en una sola entidad diferentes comportamientos que muy probablemente colisionen sin tener mayor control sobre esa futura mutacion.

Esa flexibilidad se acota en .NET, al permitir solo la herencia simple de clases, NO la herencia multiple.

Los lenguajes de desarrollo en .NET dejan de ser, por eso, lenguajes orientado a objetos como mandan los canones :)

Fue una decision de diseño del CLR Team y el equipo de C#, que se tomo en algun momento, luego de evaluar las debilidades de un leguaje orientado a objetos quimicamente puro, como el precioso C++, por ejemplo.

Por su parte, la teoria de la POO, ya concebia la definicion de interfaces, de una manera distinta. Las clases abstractas son, en la actual implementacion de los lenguajes orientado a objetos, las famosas interfaces con una restriccion: que cada metodo de dicha clase abstracta sea de orden publico.

Las interfaces nacen alli. Y al tener su implementacion en control de quien construye el modelo de clases, de tu producto de software, se permite a nivel de diseño heredar multiples interfaces.

Las interfaces son esa valvula de escape de un lenguaje orientado a objetos que NO permite herencia multiple de clases, con la ambicion de serlo a regaña dientes.

Pero, ¿por que usar interfaces en .NET?

Al utilizar interfaces y definirlas en nuestro modelo de clases estaremos permitiendo la posibilidad de aprovechar las bondades de un lenguaje orientado a objetos en .NET, en beneficio de una mejor implementacion del producto de software.

Una de esas tantas bondades es el polimorfismo.

¿Que beneficio encontrare al utilizar las interfaces?

Tiempo, simplemente. ¿Te parece poco, pregunto?

El uso de interfaces que definen comportamientos, que aquellas clases que las hereden deban establecer su correcta implementacion, eleva tus posibilidades de reducir los tiempos en la construccion del software, abrumadoramente.

Orientar la implementacion de tu modelo de objetos en funcion a la herencia simple de clases apoyada en la herencia multiple de interfaces, para el uso de estas en el envio de informacion entre las clases de tu propio modelo, para la definicion de tus Templates y para el manejo apremiante de delegates, te permitiran alcanzar un nivel de abstraccion, en el diseño y la arquitectura de tu modelo de clases, que se vera reflejado en reducir los tiempos para desarrollar tu producto de software y por ende los costos.

De nada sirve tipear codigo a diestra a siniestra, que promueve el COPY & PASTE por everywhere, haciendo del codigo un telaraña dolorosamente mantenible y vergonzosamente presentable.

Si NO defines tus propias interfaces en el modelo de objetos que haz diseñado, NO estaremos avanzando, solo retrocediendo.

El dolor vendra la proxima vez que tengas que meterle mano a esa basura de codigo, donde las clases que tienen comportamientos similares esten implementadas de formas totalmente distintas, sin guardar coherencia entre si, NI centralizar las lineas bases de dicho comportamiento.

Solo te quedara exclamar: Esos cambios son muy drasticos...!!!

Monday, April 06, 2009

Tres capas desarrollo software arquitectura

Desarrollar software permite la posibilidad de crear, algo que NO necesariamente existe en el entorno inmediato, para reutilizar y hacer que funcione en la cruda realidad: produccion.

El entorno de produccion es aquel siniestro lugar al cual estamos sentenciados y nos dirigimos cada vez.

Diseñar una arquitectura que nos permita cierta flexibilidad y la vez rigidez en su propia base ayudara a que nuestra implementacion y posterior deployment este bajo nuestro control.

Si algo escapa de nuestro control, todo sera un dolor de cabeza.

Una de estas arquitecturas es el desarrollo sobre Tres Capas, muy conocida por cierto, excesivamente utilizada y pesimamente implementada, la mayoria de las veces.

En el diseño de una arquitectura, debes concebir que la capa inferior facilite las tareas de la capa superior, y que esta la utilize de manera simple y natural.

Aquella es la idea, su razon de ser.

NO debe exisitr redundancia de operaciones entre una capa y la otra. De lo contrario, NO tendria mayor valor NI significado su existencia.

Por ejemplo, en el clasico y trivial ejercicio, donse se requiere sumar dos numeros enteros ubicados sobre un WebForm, en el cual se debe ingresar los datos sobre un par de controles TextBox y un boton que ejecute la operacion para que se muestre el resultado en otro TextBox establecido en modo readonly, muy probablemente te encuentres con un diseño de tres capas, similar a este:

private void Sumar_Click( Object sender, EventArgs e )
{
BLSumar o = new BLSumar();
this.c.Text = BLSumar.Calculate( this.a.Text, this.b.Text );
}

De esta manenra, la clase BLSumar, donde BL nos quiere decir Business Layer, tendra, muy probablemente, una implementacion como esta:

public class BLSumar()
{
public Int32 Calculate( Int32 a, Int32 b )
{
DLSumar o = new DLSumar();
return o.Insert( a, b );
}
}

Del mismo modo, la clase DLSumar, donde DL nos quiere decir Data Layer, ajustara su implementacion en algo similar a esto:

public class DLSumar()
{
public Int32 Insert( Int32 a, Int32 b )
{
Store procedure = new Store( "SP_SumarInsert" );
procedure.AddInParameter( a );
procedure.AddInParameter( b );
procedure.AddOutputParameter( "c" );

Helper.ExecuteNonQuery( procedure );
return procedure.Parameters[ "c" ].Value;
}
}

Asumiendo, para los efectos de la explicacion, que existe una Tabla en la Database con tres campos, donde los dos primeros seria los sumandos de la operacion y el tercero un campo calculado que obtiene la suma aritmetica de los dos primeros, entonces continuamos :)

En este supuesto escenario, ¿cual seria la razon de ser del Business Layer que funciona de mero wrapper del Data Layer?

Recuerda que aun falta la implementacion del Store Procedure que es llamado desde la clase DLSumar, que en teoria debe realizar un simple INSERT sobre la tabla Suma.

¿Tantas clases y un store procedure para realizar una operacion tan simple?

Por Dios! Nunca fue tan laborioso realizar una operacion contra la Database :)

Definitivamente, algo anda mal. Ten la plena seguridad que NO estamos haciendo las cosas bien.

La solucion poco decorosa de una implementacion sobre Tres capas, de esta manera, solo provoca que se gasten lineas de codigo entre una capa y otra, sin mayor valor agregado para los efectos del resultado final.

Aplicando el mismo criterio para la construccion de tus clases, en la vida real, donde te has de encontrar con un mayor numero de tablas y un abrumador numero de campos por cada tabla, entonces nos damos cuenta que nuestra solucion es una verdadera porqueria :)

La correcta solucion pasa por darle a la implementacion de cada capa un valor agregado que facilite la vida de la capa superior. NO redundar con la misma operacion, en contextos distintos.

Una implementacion de esta manera, promueve el COPY & PASTE.

Si ello sucede en la construccion de tu producto de software, estate seguro que nuestro desarrollo camina a piñon fijo hacia una pesima escalabilidad con el codigo disgregado por everywhere.

Dolorosamente sostenible en el tiempo, aburridamente mantenible y vergonzosamente presentable :)

Wednesday, March 25, 2009

Templates Tipos Genericos Herencia

Cuando estas desarrollando software, es una consecuencia natural el uso de Templates para facilitar la construccion del codigo, ahorrar lineas repetitivas disgregadas en diferentes clases de uso final, y reducir los tiempos.

Si dentro de la construccion de tus clases solo utilizas Templates para hacer un List<String> o a lo mucho un IEnumerable<Client>, ten la plena seguridad que estas desperdiciando el uso favorable de la tecnologia que tienes en tus manos, en este caso C#, de manera irresponsable y muy probablemente estes quemando tus neuronas haciendo el laborioso COPY & PASTE por everywhere...!

Debes cambiar el rumbo, alguien debe girar el timon :)

En ese uso de siniestros Templates, dentro de la definicion de aquellas clases que heredan su comportamiento de otras clases que se han diseñado como Templates, muy probablemente te encuentres con un mensaje como este:

'TEntity' must be a non-abstract type with a public parameterless constructor in order to use it as parameter 'TEntity' in the generic type or method 'SomeClass<TEntity>'

Lo que sucede es que la clase SomeClass presenta una serie de restricciones para su normal ejecucion. Dichas restricciones se implementan con el uso de la clausula where en la definicion de la clase o en los metodos de la misma, que el arquitecto establecio en el diseño de dicha clase.

En consecuencia, al implementar la herencia de una clase que tiene dichas restricciones, solo queda ir de la mano con ella.

En terminos sencillos, tendras que establecer las mismas restricciones haciendo uso de la clausula where en la implementacion de tu nueva clase y agregar otras nuevas que creas conveniente para la construccion de la tuya.

En el caso en concreto del mensaje que te mostre anteriormente, este nos indica que el tipo generico TEntity requiere ser instanciada en alguna parte del codigo de la clase heredable.

Es decir, debes agregar esta restriccion: where TEntity : new() en tu nueva clase.

Friday, January 09, 2009

Usando Threads con parametros

Utilizar Threads brota a la necesidad de ejecutar multiples operaciones relativamente pesadas.

Pesadas en el sentido que el tiempo para concluir su ejecucion, es relativamente indeterminado. Es decir, la aplicacion NO puede quedarse a la espera de que concluya dicha operacion sin que el usuario quede inhabilitado de continuar usando el software.

Los Threads permiten una solucion a esta necesidad.

Sin embargo, como toda operacion siempre se requerira de una especie de parametrizacion, es decir, enviarle una serie de parametros para que se ejecute con ciertas variables inicializadas previamente.

¿Que hacer ante este requerimiento? ¿Como puedo pasarle parametros a un metodo corriendo sobre un Thread?

Un metodo extenso, es casi siempre una potencial clase, es decir un class, que podras encapsular de la manera que mejor creas conveniente.

Aquel metodo relativamente extenso y pesado, podra ser abstraido a una clase, a la cual expondras un metodo publico sin parametros: Run, por ejemplo.

El constructor de la clase, tendra todos los parametros necesarios que requiera esa operacion relativamente pesada.

Entonces, tu instanciaras un objeto de dicha clase, y colocaras sobre un Thread el metodo Run de aquella class.

MyClass o = new MyClass( param1, param2 )
Thread t = new Thread( o.Run );
t.Start();

Este mecanismo te brindara la solucion a tus problemas.

Por otro lado, existe una clase propia del .NET Framework llamada ParameterizedThreadStart pero como todo lo que esta disponible para usar en el .NET Framework, tiene un costo, perder el control sobre la ejecucion interna de la operacion sobre el Thread.

Algo que a la primera, puede que NO le tomes la minima importancia, pero que luego, conforme van madurando el producto de software, este debe ajustarse a mas necesidades que la inicialmente indicadas.

Por lo que perder el control, tendra un costo mas alto despues.

Ese despues, esta solo a la vuelta de la esquina. NO lo dudes!

Monday, August 18, 2008

Tipos anonimos en C# 3.0

Una de las cosas que me fascinan del C# 3.0 es el uso de tipo anonimos.

Las tipos anonimos o anonymous types, tambien conocidos como clases anonimas, brindan una posibilidad interesante que nos hubiese gustado poder disfrutar en la version C# 2.0 del Visual Studio .NET 2005.

Una de las primeras aplicaciones de los tipos anonimos lo encontramos en el desuso de los RowDataBound del GridView al mostrar informacion de vistas relativamente sencillas.

Gracias a que existen los tipos anonimos, puedes entregar un lista de elementos cuya estrutura NO se encuentra definida previamente.

Muchas veces, al usar un modelo de objetos basado en Collections and Business Entities, se hacia necesario utilizar el RowDataBound del GridView para poder enlazar los controles definidos en los TemplateColumn -que hayas diseñado en el GridView- con el dato que deseas.

Por ejemplo, si tenias un collection de Clientes y tienes una propiedad para cada cliente llamada TipoCliente.

Evidentemente NO hibas a enlazar en una columna del GridView solo el ID del TipoCliente.

Era requerido por el usuario final, mostrar la descripcion del TipoCliente en la grilla de datos.

Ese tipico escenario, era motivo para utilizar el RowDataBound del GridView, con la intencion de enlazar el Label que habias definido en el TemplateColumn con el dato que se encontraba en ICliente.TipoCliente.Descripcion que habias establecido segun el modelo de objetos a nivel de la capa de negocio del producto de software que te encontrabas construyendo.

Gracias a las clases anonimas y su facil uso, hemos dejado de usar los RowDataBound del GridView en algunos tipicos escenarios.

Esto ayuda mucho en la mejora del tiempo para el desarrollo del software.

Al poder definir un collection de tipos anonimos de una forma relativamente similar a: new { item.Entity.ID, item.Entity.Nombre, item.TipoCliente.Descripcion }; donde item es un objeto del tipo ICliente y naturalmente la clase Cliente implementa la interfaz ICliente, todo se hace mas sencillo y menos trabajoso para el developer.

Los tipos anonimos han logrado facilitarnos la vida, como NO tienes idea.

Thursday, August 07, 2008

Partial Class en Visual Studio .NET

Una de las mejoras del C# 2.0 son las Partial Class o clases parciales.

Partial Class permite definir una misma clase y sus miembros en archivos .cs distintos.

Una de sus primeras aplicaciones lo encontramos en los .designer de las ASPx web pages.

Pues en las versiones anteriores del Visual Studio .NET previas al 2005 los elementos definidos en el diseñador de las paginas ASPx eran plasmados en un solo archivo aspx.cs.

Lo cual se le hacia muy complicado gestionar al Visual Studio .NET 2002 y 2003, por ejemplo.

Hoy esto ha sido superado. Facilitando el manejo del designer y la estabilidad del Visual Studio .NET 2005 y con mayor razon en el Visual Studio .NET 2008.

Usar las Partial Class es un primer ejemplo del Divide y Venceras.

Monday, July 28, 2008

SetValue PropertyInfo FieldInfo Struct

Cuando defines tus Business Entities como structuras y NO como clases, es decir como struct.

Estableciendo sus diferentes atributos, para que posteriormente manejar el mapping correcto con su correspondiente tabla a nivel de base de datos, requeriras de una mecanismo generico para hacer la lectura de los registros de dicha tabla de base de datos hacia una coleccion de Business Entities, para manejarlos como tal dentro del mundo .NET

Hasta alli, todo relativamente normal.

Pero al usar un struct para definir cierto Business Entity, te daras cuenta que el metodo SetValue del PropertyInfo o el FieldInfo -dependiendo lo que estes usando para definir las propiedades o atributos de tu Business Entity- NO estan funcionando como tu esperas.

Lo que sucede es que las estructuras o struct, son tipos de datos por valor a diferencia de las clases o class.

Y este es uno de los puntos en contra al utilizar estructuras o struct para definir tus Business Entities.

En este incidente la clase ValueType resuelve tu problema.

TEntity entity = new TEntity();

Debera ser reemplazado por:

ValueType entity = new TEntity();

Dentro del bucle que este leyendo el SqlDataReader para iterar cada uno de los registros de la consulta que hayas realizado, mapeando cada uno de estos registros dentro de su Business Entity para retornar finalmente a una coleccion de Business Entities, a quien haya utilizado el metodo generico que implementaste.

IEnumerable ExecuteReader( String sql ) where TEntity : struct

Vale recalcar que es importante utilizar la clausula where TEntity : struct para poder instanciar el template TEntity dentro de la implementacion de dicha funcion y para poder castearlo a un ValueType, posteriormente.

Wednesday, September 19, 2007

VB.NET versus C#

Coger un proyecto en VB.NET es fustrante. Las limitaciones que tiene este lenguaje en comparación al C# son notorias y se traducen en una baja producción. Lo que al final trae como consecuencia más horas en el desarrollo.

Se extraña lo breve del codigo en C#. Lo estricto para el manejo de las variables y la firma de los metodos. Así como el soporte que brinda para los Iterators, usando yield return.

Cuando tienes un proyecto web en VB.NET es lamentable ver errores de sintaxis que arrojan el .NET Framework cuando testeas el producto.

En consecuencia, dificilmente tenga un futuro alentador VB.NET como lenguaje de programación.

C# forever and ever!