[Reflection] Un momento de reflexión… para Windows Mobile (MenuItem.Click)

Las limitaciones a las que nos vemos sometidos habitualmente los desarrolladores de Compact Framework, sobre todo si trabajamos sobre código manejado, suelen resultar muchas veces frustrantes, frustantes en el sentido de que algo que podíamos hacer de una manera sencilla en cualquier aplicación de escritorio no funciona de igual modo en la plataforma móvil.

Una de esas cosas, que de paso utilizo para el ejemplo, es poder enlazar el evento Click de un elemento MenuItem del cual desconozco su método asociado (en este caso OnClick), desde una función en código.

Lo más sencillo sería, venga va, si tienes el código fuente pues no seas desastre y mira el método que tienes asociado al evento click del MenuItem y a correr… está claro que es lo más sencillo ¿no? Pero si estás desarrollando un control que requiere ejecutar lo que el desarrollador enlace al evento Click del MenuItem la cosa se complica. Resulta que el método OnClick del MenuItem en Compact Framework esta declarado internamente como «Protected Internal vitual» así que nos olvidamos de poder invocarlo… y tampoco podemos recuperar el EventHandle al que esta asociado el evento Click del MenuItem.

Código interno del metodo OnClick dentro del control MenuItem

protected internal virtual void OnClick(EventArgs e)
{
    if (this.Click != null)
    {
        this.Click(this, e);
    }
}

Pues utilizando un poquito de reflection, podemos asociar el evento a nuestro propio código utilizando tan solo unas líneas de código.

En el ejemplo estamos asociando que cuando se dispare nuestro metodo, al que hemos llamado quickMenuItem.click, se ejecute también el método OnClicK del MenuItem que pasemos por código y por consiguiente se dispare el EventHandle asociado al click del MenuItem

using System.Reflection;
(…)
//Creamos un EventHandler y lo instanciamos con la definición del evento Click del menuItem que deseemos
EventHandler click = (EventHandler)GetPrivateField(menuItemX, «Click»);
quickMenuItem.Click += click;
(…)

//Recuperamos el campo privado a enlazar
private object GetCampoPrivado(object obj, string campo)
{

      //Prestar especial atención a los atributos
      FieldInfo fi = obj.GetType().GetField(campo, BindingFlags.NonPublic|BindingFlags.GetField|BindingFlags.Instance);
      return fi.GetValue(obj);
}

Esto es realmente sencillo, y nos muestra que muchas de las limitaciones con las que nos encontramos tienen una fácil solución.

NOTA: Una herramienta (comunmente concida) que realmente nos puede ayudar es la Red Gate’s .NET Reflector a la hora de descubrir métodos eventos y propiedades privadas.

Un saludo a todos.

José Antonio Gallego

Mobile .NET Users Group

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *