Sunday, October 29, 2006

Como instanciar una clase que tenga un constructor privado

Este articulo aplica a C# (probado en VS2005)

Hace poco hablaba sobre como podemos ejecutar metodos privados (de otra clase) usando refleccion; parece que no mucha gente esta enterada de que se puede hacer esto y siempre genera todo tipo de comentarios. Pues aqui les tengo otra para ustedes, tambien podemos crear una instancia de una clase, aun si los constructores de esta son privados.

Aqui estoy incluyendo un ejemplo para un constructor privado, un protegido y un (normal) publico, todos ellos usando refleccion.

Vamos a crear una clase para poder jugar:

public class TestClass {
private TestClass() {
Console.WriteLine("private TestClass constructor");
}
protected TestClass(int i) {
Console.WriteLine(string.Format("protected TestClass constructor (int:{0})", i));
}
public TestClass(string s) {
Console.WriteLine(string.Format("public TestClass constructor (string:{0})", s));
}
}

Ahora vamos a ver que facil es crear instancias de esta clase usando cualquiera de sus constructores, sin importar su visibilidad:


- Para este codigo necesitas incluir System.Reflection en el uses.


El primero es un constructor privado simple que no tiene ningun parametro, no se requiere mucho para este

//*** Private constructor
ConstructorInfo ci1 = typeof(TestClass).GetConstructor(
//*** Non public and instance (non static) constructor
BindingFlags.NonPublic | BindingFlags.Instance,
//*** No binder, no parameters, so no parameter modifiers
null, new Type[0], new ParameterModifier[0]);
//*** Call our constructor
TestClass tc1 = (TestClass)ci1.Invoke(new object[0]);

El segundo es protected (aun cuenta como "no publico"), aqui inclui un parametro asi que tenemos que pasarle el tipo del parametro

//*** Protected constructor
ConstructorInfo ci2 = typeof(TestClass).GetConstructor(
//*** non public and instance (non static) constructor
BindingFlags.NonPublic | BindingFlags.Instance,
//*** no binder, 1 parameter of type int, no modifiers for the param
null, new Type[1] { typeof(int) }, new ParameterModifier[0]);
//*** Call our constructor
TestClass tc2 = (TestClass)ci2.Invoke(new object[1] { 10 });

El tercero es publico, asi que podriamos crear la instancia sin tener que usar el metodo de refleccion, pero le deje aqui solo como ejemplo

//*** Public constructor
ConstructorInfo ci3 = typeof(TestClass).GetConstructor(
//*** public and instance method
BindingFlags.Public | BindingFlags.Instance,
//*** no binder, 1 parameter of type string, no parameter modifiers
null, new Type[1] { typeof(string) }, new ParameterModifier[0]);
//*** Call our constructor
TestClass tc3 = (TestClass)ci3.Invoke(new object[1] { "test" });

Eso es todo, asi de sencillo; esta tecnica realmente es muy raro que la tengamos que utilizar, mas que todo me interesa que sepan que es posible y cuan facil es lograrlo


Uno podria incluso combinar los flags: BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance y podriamos crear la instancia de la clase sin importar si esta fuera private, protected o public (por ejemplo en el caso de que cargaramos un assembly dinamicamente y solo nos interesara que la clase estuviera ahi)


Pueden encontrar el codigo completo aqui,


por cierto, en estos momentos estoy en Guadalajara, estare aqui hasta el martes y luego voy a Tulancingo Hidalgo y de ahi a Aguascalientes, si alguien esta interesado en echar una platicada o ir a cenar aqui estamos a la orden


salu2 

Thursday, October 26, 2006

curiosidades en Javascript

Me encontre esto en el blog de Javi Moya's

1. Resalten el texto de aquí abajo (marquenlo completamente)
2. Pulsen Ctrl+C (para copiarlo al portapapeles)
3. Pulsen Alt+D (o vaya a la barra de direcciones del navegador)
4. Pulsen Ctrl+V (para pegar el código javascript)
5. Pulsen Enter

javascript:scroll(0,0); R=0; x1=.1; y1=.05; x2=.25; y2=.24; x3=1.6; y3=.24; x4=300; y4=200; x5=300; y5=200; DI=document.getElementsByTagName("img"); DIL=DI.length; function A(){for(i=0; i-DIL; i++){DIS=DI[ i ].style; DIS.position='absolute'; DIS.left=(Math.sin(R*x1+i*x2+x3)*x4+x5)+"px"; DIS.top=(Math.cos(R*y1+i*y2+y3)*y4+y5)+"px"}R++}setInterval('A()',5); void(0);

6. Puedes navegar a otros sitios y pegar el codigo en la barra de direccion 

7. Aun mejor en sitios que tienen muchas imagenes 

8. No andes por ahi navegando en sitios copiando y pegando javascript en tu barra de direccion! =oP

Caracteres de escape para usar palabras reservadas como nombres de variables en .NET

Este articulo es en referencia al articulo de Jean-Paul: Nombrando variables usando el tipo de la variable como nombre (truco inservible #1).(articulo en ingles)

Pues bien, resulta que el truco no es tan inservible, solo tenemos que ver mas alla de nuestra nariz.

en la documentacion MSDN en español (que creo que mucha gente todavia no sabe de este gran recurso) encontramos el siguiente texto:

Las palabras clave son identificadores predefinidos reservados que tienen un significado especial para el compilador. No se pueden utilizar como identificadores en un programa a menos que incluyan el carácter @ como prefijo. Por ejemplo, @if es un identificador válido pero if no, por ser una palabra clave.

.NET vino a resolver lo que era uno de los problemas mas grandes en el area de desarrolo, esto es (o era) el poder interactuar facilmente con codigo escrito en otro lenguaje, esto se resuelve en .NET porque los compiladores convierten el codigo a Lenguaje Intermedio.

Hoy en dia uno puede escribir codigo en cualquier lenguaje de .NET y usar el codigo (las librerias generadas) en cualquier otro lenguaje de .NET; esto crea un problema, ya que las palabras reservadas en un lenguaje pueden (y muchas veces es asi) no significar nada en otro lenguaje, por ejemplo podrias estar programando en C# y usar una variable begin, la cual es una palabra reservada en Delphi, y entonces cuando alguien quisiera usar tu codigo C# desde Delphi, no podrian; para resolver este problema los lenguajes deben (para su propio "bienestar") implementar algun tipo de caracter de escape que permita usar palabras reservadas como nombres de variables en caso de que estes usando codigo escrito en otro lenguaje en el que hallan declarado una variable con el nombre de una palabra reservada en el lenguaje que estas usando (uff, no se si se entendio esto)

en C# usamos el prefijo @

string @while = "something"
Console.WriteLine(@while);

en Delphi usamos el prefijo &

&begin:Integer;
begin
  &begin := 10;
  Console.WriteLine(&begin);

en VB.NET encerramos la palabra reservada en brackets

Dim [Dim] = 20
Console.WriteLine([Dim])

obviamente (es una de las primeras cosas que se aprenden) uno no usa palabras reservadas como nombres de variables cuando estas en el lenguaje mismo, pero si tienen un uso valido cuando empezamos a interactuar con codigo escrito en otros lenguajes, si no tuvieramos esos caracteres de escape, mucho codigo no funcionaria

Si alguien sabe de los caracteres de escape para otros lenguajes de .NET dejenme un comentario para actualizar el articulo

p.d. despues de escribir esto, me encontre con que Jeff les llama escaped identifiers

Monday, October 23, 2006

Como ejecutar metodos privados de otra clase

Este articulo aplica a C# (probado en C# 2.0)

De acuerdo a la documentacion de MSDN el modificador de acceso private es el nivel de acceso mas restrictivo (acceso es limitado solo al tipo que contiene dicho miembro)

De vez en cuando quisieramos poder accesar un metodo privado en alguna clase para la cual no tenemos el codigo fuente, generalmente no deberiamos tener que hacer esto, pero pues en caso de que se ofrezca, esta es una manera de lograrlo:

primero que nada, tenemos una clase para nuestro ejemplo:

public class TestClass {
public TestClass() {
}
private void HiddenMethod() {
Console.WriteLine("secret method, should only be called from the containing class itself");
}
private string HiddenMethodWithParams(string firstName, int age) {
return string.Format("hello {0}, you are {1} years old", firstName, age);
}
}

basicamente esta clase no sirve de nada, porque no expone ningun metodo que podamos usar... a menos que tengamos acceso a los metodos privados (aun asi no sirve de nada, pero esto es solo un ejemplo =oP ):


Ahora vamos a ver como accesar los metodos privados

TestClass tc = new TestClass();
Type testClaseType = typeof(TestClass);

MethodInfo hiddenMethod =
testClaseType.GetMethod("HiddenMethod",
BindingFlags.NonPublic | BindingFlags.Instance);
hiddenMethod.Invoke(tc, null);

MethodInfo hiddenMethodWithParams =
testClaseType.GetMethod("HiddenMethodWithParams",
BindingFlags.NonPublic | BindingFlags.Instance,
null, new Type[2] { typeof(string), typeof(int) }, null);
string result = (string)hiddenMethodWithParams.Invoke(tc, new object[2] { "Eber", 25 });
Console.WriteLine("result: "+ result);

Console.Read();

vamos a ver:



  1. la primera linea simplemente crea una instancia (tc) de la clase que contiene los metodos en los que estamos interesados

  2. la segunda linea obtiene el tipo de la clase, que en este caso seria TestClass, esta variable nos servira para preguntarle informacion sobre los metodos que se encuentran en ella.

  3. luego viene lo interesante, adquirir un puntero hacia la funcion privada "HiddenMethod", los parametros BindingFlags.NonPublic y BindingFlags.Instance quieren decir: quiero un metodo no-publico (osease privado en este ejemplo), que sea un metodo proveniente de una instancia (lo opuesto de este ultimo seria estatico, ya que los metodos estaticos no se ejecutan de una instancia, sino llamandolos directamente)

  4. acto seguido, ya que tenemos un puntero a esta funcion, solo queda mandarla llamar, esto lo hacemos ejecutando el metodo Invoke, y pasando tc, la cual es la instancia en la cual se va a ejecutar el metodo (tc fue la instancia creada en la primer linea)

Basicamente eso es todo lo que hay que hacer, pero claro que una funcion que no regrese nada y que no acepte parametros pocas veces es util, asi que inclui tambien un ejemplo de llamar un metodo el cual acepta parametros y regresa algo.


Lo unico que tenemos que agregar para hacer que esta funcione, es lo siguiente:


en el paso 3, al obtener el puntero hacia el metodo que queremos ejecutar, necesitamos pasar informacion sobre los tipos de datos de los parametros de la funcion, esos datos los pasamos un arreglo; si te vas hasta arriba a ver la declaracion del metodo HiddenMethodWithParams, veras que acepta 2 parametros, un string y un int, ahora de regreso aca, eso lo especificamos asi:


new Type[2] { typeof(string), typeof(int) }


Lo cual quiere decir: 2 parametros, el primero es un string, el segundo un int


Por supuesto, podemos pasar cualquier tipo de parametro


Ahora ya tenemos el puntero al metodo que necesitamos, pero como este metodo regresa algo, pues tambien tenemos que cambiar la forma en como lo mandamos llamar:


string result = (string)hiddenMethodWithParams.Invoke(tc, new object[2] { "Eber", 25 });


aqui creamos una variable para guardar el resultado, luego mandamos llamar el metodo, haciendole una conversion al tipo de datos que sabemos que regresa (string), el parametro tc sigue igual, recuerda que ese es la instancia en la cual se esta ejecutando el metodo, por ultimo tenemos que pasar los parametros a la funcion, la manera de hacerlo es muy similar a la forma en la que le definimos el tipo de datos de los mismos


new object[2] { "Eber", 25 }


que se traduce a: 2 parametros, el primero es "Eber", el segundo es:25


Señores (y señoritas) eso todo por hoy; no abusen de esta tecnica! el codigo completo lo encuentran aqui

Como obtener el primer y ultimo elemento de un Enum

Este articulo aplica a C# 2.0

Hay veces que tenemos un tipo enumeracion y queremos asegurarnos que cierto parametro esta dentro del rango de nuestra enumeracion, la gran mayoria del codigo que he visto checa haber si X valor es mayor al ultimo elemento de la enumeracion, algo asi:

enum TestEnum {

  Enum1 = 1, Enum2 = 2, Enum3 = 3;

}

TestEnum myValue; //generalmente esto pasa cuando esta variable viene como parametro a una funcion

if (myValue > TestEnum.Enum3) //algun codigo para manejar este problema

y cada vez que tuvieran que actualizar la enumeracion tendrian que modificar esta parte del codigo.

Esta funcion nos regresa el primer y ultimo elemento de un tipo Enum, la escribi de forma generica para que pueda ser usada con cualquier tipo enum, pero podrian modificarla para ser para un tipo especifico y se podria usar en C# 1.0 (VS2003), creo que el uso seria raro pero pues aqui esta para cuando se ofrezca

public void GetLowHighFromEnum<T>(out T lowElement, out T highElement) {
if (!typeof(T).IsSubclassOf(typeof(Enum))) //make sure we got an Enum
throw new ArgumentException("parameterized type should be Enum");
T[] values = (T[])Enum.GetValues(typeof(T));
lowElement = values[0];
highElement = values[values.Length - 1];
}

para usarla seria algo mas o menos asi

TestEnum te1, te2;
GetLowHighFromEnum<TestEnum>(out te1, out te2);
Console.WriteLine(te1.ToString());
Console.WriteLine(te2.ToString());

Sunday, October 22, 2006

Es posible convertir cualquier valor entero a un tipo Enum, aun si el valor entero esta fuera de los valores definidos en tu Enum

Este articulo aplica a C# (probado en C# 2.0 (VS2005))

Pues si, casi se los cuento todo en el titulo, pero asi es, ultimamente he estado investigando bastante sobre Enums y he encontrado unas cosillas muy interesantes, esta es una de ellas; por ejemplo este codigo es valido y se ejecuta sin ningun problema:

public enum TestEnum {
  Enum1 = 1,
  Enum2 = 2,
  Enum3 = 3
}
...
TestEnum t = (TestEnum)10; //WTF?
Console.Write(t.ToString()); //cual creen que sea la salida?
Console.Read();

Si a eso le agregas que el valor que estas convirtiendo viene (por ejemplo) de una base de datos, podras entender como esto podria esto afectar la logica en tu programa.

Si estas trabajando con Enums, te recomiendo que leas este articulo de Krzysztof Cwalina (solo en ingles), que es una referencia / guia muy completa para los tipos de enumeraciones; ahora que cuando uno se mete con Nullable Enums, la cosa se pone aun mas interesante, ya les platicare algunas cosillas que estoy haciendo en esa area

Wednesday, October 18, 2006

Usando el mouse: sabias que...?

Sabias que el boton medio del mouse (ironicamente ahorita no quiero hablar de ratones por razones muy desagradables) nos sirve para cerrar ventanas en la mayoria de las aplicaciones de navegacion por pestañas (tabbed-documents)? (para cerrarlas solo damos click con el boton de enmedio en la pestaña)

por ejemplo todos los navegadores nuevos: Internet Explorer 7, Firefox, Flock, Opera, etc tienen esta funcionalidad, pero tambien Visual Studio, aplicaciones como Notepad++, MSN Messenger, etc, en general la mayoria de este tipo de aplicaciones implementan esta funcionalidad.

Aparte de esto, en los browsers, dando "middle click" en un link, abre el link en una pestaña nueva

decidi bloguear sobre esto, porque he conocido mucha gente que no sabe sobre este pequeño pero util truco

En busca de un mejor sistema CAPTCHA

Recientemente, Geoff empezo a preocuparse con el SPAM en los comentarios a su blog y con las alternativas actuales que existen para combatirlo, desde entonces se puso a trabajar en una opcion mas simple (para los usuarios) en la cual se proveen fotos en vez de texto, luego tienes que dar click en ciertas imagenes dependiendo de unas instrucciones que se te dan; la idea es original y me parece que si es mas facil para el usuario, pero yo creo que tiene algunos problemitas:

  • Las imagenes necesitan bajarse para cada usuario (ancho de banda)
  • Creo que tienes que tener un numero considerable de imagenes para que esto realmente se pueda usar, esto para hacer mas dificil la creacion de un robot, con esto tambien tenemos mas problemas de ancho de banda
  • Cada implementacion tendria que tener sus propias imagenes y reglas asociadas con las imagenes
  • Es algo grande

De cualquier manera, esto me ha dado una idea, porque no combinamos texto regular con la idea de Geoff?

osease que podemos tener texto (convertido a imagenes) y las preguntas, algo mas o menos asi:

Da click en los numeros pares: 123641

Da click en los simbolos matematicos: 123+45/6*21

Da click en las ultimas 2 letras mayusculas: 1A654aPaK

etc, el font por supuesto seria diferente (y mas grande), las ventajas que le veo son:

  • Imagenes muy pequeñas
  • numero infinito de CAPTCHAS pueden ser generados con un pequeño programita, ni siquiera necesitas guardar las preguntas o respuestas en ningun lado
  • Es bastante legible
  • Tomando las debidas precauciones (para evitar confusion con algunos caracteres) puede ser muy claro y simple lo que el usuario necesita hacer (algunas veces no se si Geoff esta riendose o esta enojado =o| )

Hay algo que no estoy viendo, o me acabo de inventar la idea del siglo contra SPAM? =o)

Si aun prefirieras la idea de Geoff, creo que al menos las imagenes (y las preguntas asociadas) podrian ser generadas programaticamente, por ejemplo lineas en diferentes angulos, circulos, triangulos, etc. solo con eso resolveriamos la mayoria (o todos?) los problemas que veo con la solucion de Geoff... y es hasta cierto punto, otra idea mas

como ven?

Thursday, October 12, 2006

cuidado con las comas en comandos SQL

Ayer tuvimos un pequeño bug con un codigo mas o menos asi:

select field1, field2, field3
field4, field5
from SomeTable
where field1 = 'someValue'

pueden ver el bug?

el comando se ejecuta sin errores, pero el resultado podria no ser el deseado

El problema es que le falta una coma entre field3 y field4, entonces es como decir:

field1, field2, field3 as field4, field5

Lo que, como se podran imaginar, uno espera ciertos datos (y cierto tipo de datos) en ese campo pero recibe algo totalmente diferente y aparte que hay un campo que no sale en el resultado

La sintaxis yo creo que es estandar Ansi 92 SQL, asi que el problema lo podrian tener usando MSSQL, MySQL, Oracle, etc (en nuestro caso el codigo corrio bien en MySQL pero nos salio el error corriendo el mismo codigo contra Oracle porque ahi teniamos diferentes datos que hicieron que saliera a la vista)

Wednesday, October 11, 2006

de gira por Guadalajara y Aguascalientes

Del dia 28 de Octubre al 6 de Noviembre andare vacacionando alla por Guadalara y Aguascalientes (talvez vaya al DF un par de dias) si alguien (de mis 3 lectores) me quiere encontrar por alla para platicar de programacion y cosas geek nomas dejen un comentario y nos ponemos de acuerdo

salu2

Tuesday, October 10, 2006

Filemon es para archivos como ___ es para debugging

si contestaste Debug View te ganaste una estrellita!; ahora que si conoces esta herramienta, pues dejame te la  introduzco (la herramienta pues!, luego luego ahi van...)

Debug View es una herramienta que te permite monitorear salida de debugueo de tu sistema local o cualquier computadora en la red que puedas ver via TCP/IP. Es capaz de mostrar salida de modo-kernel y salida de debug de Win32, de tal manera que no necesitas un debugueador para cachar la salida de debug que tus aplicaciones o controladores (drivers) generen, tampoco necesitas modificar tus aplicaciones o controladores para usar salida de debug no-standard.

Debug View funciona en Windows 95, 98, Me (miren que esto si es mucho decir), 2000, XP, Windows Server 2003, Windows for X64 processors and Windows Vista

Basicamente, en tu codigo (practicamente cualquier lenguaje, solo con que utilice las librerias estandares de Windows para salida de debug), por ejemplo en C#, solo ponemos algo asi:

Debug.WriteLine("Esto esta mega-cañon!");

ahora nadamas corres Debug View, luego corres tu programa (aplicacion web o lo que sea que estes debugueando) y listo! Debug View te mostrara los mensajes muy similar a la manera como Filemon te muestra cualquier actividad con los archivos

Traido a ustedes por el señor que no vee problemas, sino soluciones; Mark Russinovich por supuesto

Tuesday, October 03, 2006

Haciendo el "Filemon"

Estaba buscando un video donde muestran el uso de la herramienta Filemon (que espero que sepas que es, si no buscalo en google, es el primer resultado), total que me puse a buscar el video, porque hace unos cuantos dias lo vi, creo que en los "Hanselminutes", y me encontre este video como el primer resultado, dije, ah pues a la mejor este video es mas especifico, y nada, jajaja, fue chistoso