Stratos: Punto de Encuentro de Desarrolladores

¡Bienvenido a Stratos!

Acceder

Foros





Implementar reflection con c#

Iniciado por Diferencial, 27 de Junio de 2007, 10:23:56 AM

« anterior - próximo »

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.
PARA TENER COSAS QUE NUNCA HAS TENIDO, TENDRÁS QUE HACER COSAS QUE NUNCA HAS HECHO.

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

Diferencial

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.
PARA TENER COSAS QUE NUNCA HAS TENIDO, TENDRÁS QUE HACER COSAS QUE NUNCA HAS HECHO.

Diferencial

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.
PARA TENER COSAS QUE NUNCA HAS TENIDO, TENDRÁS QUE HACER COSAS QUE NUNCA HAS HECHO.

Vicente

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

Diferencial

gracias vicente, lo mirare. Cabe decir que en silverlight el enlace es una gozada.
PARA TENER COSAS QUE NUNCA HAS TENIDO, TENDRÁS QUE HACER COSAS QUE NUNCA HAS HECHO.

Diferencial

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.
PARA TENER COSAS QUE NUNCA HAS TENIDO, TENDRÁS QUE HACER COSAS QUE NUNCA HAS HECHO.






Stratos es un servicio gratuito, cuyos costes se cubren en parte con la publicidad.
Por favor, desactiva el bloqueador de anuncios en esta web para ayudar a que siga adelante.
Muchísimas gracias.