Foros - Stratos

Programadores => General Programadores => Mensaje iniciado por: Diferencial en 27 de Junio de 2007, 10:23:56 AM

Título: Implementar reflection con c#
Publicado por: Diferencial en 27 de Junio de 2007, 10:23:56 AM
Hola a todos,
A ver si alguien me saca de la duda porque creo que puedo hacer algo chulo con reflection pero no lo consigo.

Type type = typeof(Usuario);
object usrRegistrado = Activator.CreateInstance(type);
string result = type.InvokeMember("Nombre", BindingFlags.Default | BindingFlags.InvokeMethod, null, usrRegistrado, null).ToString();
Response.Write(result);


Intento conseguir invocar un metodo de un objeto en tiempo de ejecucion, lo uso para enlazarlo a un formulario de una página web. Pero no se porque no funciona ya que tengo una clase con una propiedad publica que se llama Nombre y devuelve un string "Javi" a ver si alguien me sabe decir que es lo que no funciona.
Título: Re: Implementar reflection con c#
Publicado por: Vicente en 27 de Junio de 2007, 10:36:05 AM
Cita de: "Diferencial"Hola a todos,
A ver si alguien me saca de la duda porque creo que puedo hacer algo chulo con reflection pero no lo consigo.

Type type = typeof(Usuario);
object usrRegistrado = Activator.CreateInstance(type);
string result = type.InvokeMember("Nombre", BindingFlags.Default | BindingFlags.InvokeMethod, null, usrRegistrado, null).ToString();
Response.Write(result);


Intento conseguir invocar un metodo de un objeto en tiempo de ejecucion, lo uso para enlazarlo a un formulario de una página web. Pero no se porque no funciona ya que tengo una clase con una propiedad publica que se llama Nombre y devuelve un string "Javi" a ver si alguien me sabe decir que es lo que no funciona.

1- Te devuelve alguna excepción?

2- Intenta a usar BindingFlags.Public | BindingFlags.Instance para la llamada en vez de las que tienes puestas. Si no prueba también con BindingFlags.InvokeMethod | BindingFlags.GetProperty (aunque yo creo que con Public e Instance debería funcionar...).

Un saludo!

Vicente
Título: Re: Implementar reflection con c#
Publicado por: Diferencial en 27 de Junio de 2007, 10:50:05 AM
Cita de: "Vicente"
Cita de: "Diferencial"Hola a todos,
A ver si alguien me saca de la duda porque creo que puedo hacer algo chulo con reflection pero no lo consigo.

Type type = typeof(Usuario);
object usrRegistrado = Activator.CreateInstance(type);
string result = type.InvokeMember("Nombre", BindingFlags.Default | BindingFlags.InvokeMethod, null, usrRegistrado, null).ToString();
Response.Write(result);


Intento conseguir invocar un metodo de un objeto en tiempo de ejecucion, lo uso para enlazarlo a un formulario de una página web. Pero no se porque no funciona ya que tengo una clase con una propiedad publica que se llama Nombre y devuelve un string "Javi" a ver si alguien me sabe decir que es lo que no funciona.

1- Te devuelve alguna excepción?

2- Intenta a usar BindingFlags.Public | BindingFlags.Instance para la llamada en vez de las que tienes puestas. Si no prueba también con BindingFlags.InvokeMethod | BindingFlags.GetProperty (aunque yo creo que con Public e Instance debería funcionar...).

Un saludo!

Vicente

Me ha funcionando usando las banderas que estan en negrita, muchas gracias Vicente.
Título: Implementar reflection con c#
Publicado por: Diferencial en 27 de Junio de 2007, 03:48:21 PM
Voy a poner aqui el ejemplo para que os hagais una idea de lo que estoy haciendo:

Código:

protected void UsuarioCampos(object sender, EventArgs e)
       {            
           TextBox campo = sender as TextBox;
           Type type = typeof(Usuario);
           object usrRegistrado = Activator.CreateInstance(type);
           if (ViewState["idUsuario"].ToString() != "0") usrRegistrado = Usuario.Edit(Convert.ToInt32(ViewState["idUsuario"]));
           string result = type.InvokeMember(campo.ID, BindingFlags.InvokeMethod | BindingFlags.GetProperty, null, usrRegistrado, null).ToString();
           campo.Text = result;
       }



Con este trozo de codigo lo que se consigue(que no es poco) es que todos los campos del formulario que sean del tipo TextBox obtengan el valor que les corresponde a traves de un objeto, en este caso Usuario.
Para que esto suceda en el evento OnDataBinding del TextBox se debe poner el metodo que lo implementa, en esta caso es UsuarioCampos. Bien pues ahora lo que quiero conseguir es justo el paso contrario que de la interfaz se enlace al objeto. Se me ha ocurrido varias posibilidades pero no acabo de resolverlo.
¿Se puede poner un evento que se lance, cuando se llame al metodo del objeto DataBinding()?
El problema es que esto no se como hacerlo, pero estoy convencido de que es lo que deberia de hacer. Si alguien puede arrojar algo de luz al tema se lo agradezco gracias.
Título: Implementar reflection con c#
Publicado por: Vicente en 27 de Junio de 2007, 04:39:44 PM
Estoy seguro que el databinding entre el objeto y los webcontrols se puede hacer de forma mucho más sencilla (sobre todo si tu objeto tiene propiedades públicas), pero no sé como :(

Busca un poco que seguro que ves algo del tema (o pregunta en MAD.NUG). Un saludo!

Vicente
Título: Implementar reflection con c#
Publicado por: Diferencial en 27 de Junio de 2007, 05:14:10 PM
gracias vicente, lo mirare. Cabe decir que en silverlight el enlace es una gozada.
Título: Implementar reflection con c#
Publicado por: Diferencial en 01 de Julio de 2007, 03:03:21 PM
Bueno aqui les dejo mi pequeña solución al problema que plantee, hay que hacer un par de pasos de más pero creo que a la larga se agradece.

Primer paso es crear una clase que herede de atributos.

[AttributeUsage(AttributeTargets.Property,AllowMultiple = false)]
public class UsuarioBinding : Attribute
{
   private string Menber_;

   public string Menber
   {
       get { return Menber_; }
       set { Menber_ = value; }
   }    
}


El segundo paso es aplicar la clase anterior a la clase que representa  una tabla de la base de datos.

public class Usuario
{    
   private string Nombre_ = "Javi";

   [UsuarioBinding(Menber="Text")]
   public string Nombre
   {
       get { return Nombre_; }
       set { Nombre_ = value; }
   }

   private int TipoUsuario_ = 1;

   [UsuarioBinding(Menber="SelectedValue")]
   public int TipoUsuario
   {
       get { return TipoUsuario_; }
       set { TipoUsuario_ = value; }
   }
}

El tercer paso es aplicar el evento OnDataBinding de nuestros controles para que llame a un metodo de nuestra pagina web.

<span>Nombre:</span>
       <span><asp:TextBox ID="Nombre" runat="server" OnDataBinding="UsuarioFormBinding"></asp:TextBox></span>
       <span>Tipo Usuario:</span>
       <span>
           <asp:DropDownList ID="TipoUsuario" runat="server" OnDataBinding="UsuarioFormBinding">
               <asp:ListItem Text="Seleccione..." Value="" Selected="True" />
               <asp:ListItem Text="Registrado" Value="1" />
               <asp:ListItem Text="Administrador" Value="2" />
               <asp:ListItem Text="SuperAdministrador" Value="3" />
           </asp:DropDownList>
       </span>

El cuarto paso es implementar el metodo UsuarioFormBinding con Reflection.

   protected void UsuarioFormBinding(object sender, EventArgs e)
   {
       Type objType = sender.GetType();
       string property = objType.InvokeMember("ID", BindingFlags.InvokeMethod | BindingFlags.GetProperty, null, sender, null).ToString();
       Type objUsuario = typeof(Usuario);
       object usrRegistrado = Activator.CreateInstance(objUsuario);
       PropertyInfo objField = objUsuario.GetProperty(property);
       UsuarioBinding objBinding = (UsuarioBinding)objField.GetCustomAttributes(typeof(UsuarioBinding), true)[0];
       object[] param = new object[1];
       param[0] = objUsuario.InvokeMember(property,BindingFlags.InvokeMethod | BindingFlags.GetProperty,null,usrRegistrado,null).ToString();
       objType.InvokeMember(objBinding.Menber, BindingFlags.SetProperty, null, sender, param);
   }  

El ultimo paso seria hacer que nuestra web se enlace con nuestro objeto en mi caso es Usuario.

   protected void Page_Load(object sender, EventArgs e)
   {
       if(!IsPostBack)
           DataBind();
   }

Bueno ahora solo hace falta hacer justo el paso al reves que desde el formulario, obtener los datos para establcerlos en el objeto usuario. Pero con lo que he puesto aqui ya se puede hacer rapidamente, aunque parezca inutil a la larga cuando se vayan incrementando los campos es mucho mas comodo de esta forma, solo se tiene que agregar el campo y ya esta.