2011-03-21 17 views
11

Lo que intento hacer es llamar al método de una propiedad, usando Reflection. Tengo el Control original (un ComboBox), el PropertyInfo de la propiedad (ComboBox.Items) y el nombre del método (ComboBox.Items.Add). He intentado con el siguiente código para obtener, modificar, configurar pero no funciona porque Items no tiene un setter.Usar Reflection para llamar a un método de una propiedad

PropertyInfo p = controlType.GetProperty(propertyName); // gets the property ('Items') 
MethodInfo m = p.PropertyType.GetMethod(methodName); // gets the method ('Items.Add') 
object o  = p.GetValue(newControl, null);   // gets the current 'Items' 

m.Invoke(o, new object[] { newValue });     // invokes 'Add' which works 
p.SetValue(newControl, o, null);       // exception: 'Items' has no setter 

¿Alguien tiene algún consejo?

Gracias

+1

Así como una sugerencia, si usted está interesado en hacer llamadas como éste a través de la reflexión más fácil y está usando C# 4, es posible que desee para envolver esta funcionalidad reflejo en un DynamicObject. He escrito una publicación sobre cómo hacer eso aquí: http://mattmc3.blogspot.com/2011/03/fun-with-dynamicobject-and-making-net.html – mattmc3

+0

Oooh, voy a echar un vistazo gracias ! – acron

Respuesta

14

eso fue rápido ... Me cambiaron la línea de invocación a ...

m.Invoke(p.GetValue(newControl, null), new object[] { newValue }); 

... y funcionó: P

+9

Me encanta cuando las personas encuentran las respuestas y luego publican cómo resolvieron sus propios problemas. Ojalá más gente hiciera esto. – jermny

+0

¿Cómo funcionó este cambio? ¿Puedes explicarme un poco sobre qué fue lo que salió mal? –

+0

@PavanManjunath No estoy del todo seguro de tener miedo. Es posible que estuviese boxeando el resultado de 'GetValue' por conversión implícita a' object', que 'Invoke' no pudo deshacer. – acron

1

El error que indica que está recibiendo que la propiedad en cuestión es de solo lectura. No hay un método establecido definido. No podrá establecer el valor de la propiedad sin un setter.

Publique nuevamente con el nombre del inmueble o más contexto y podremos darle una mejor respuesta o una alternativa.

+0

Sí, me doy cuenta de que es porque no hay un colocador. Mi código era solo un ejemplo de lo que había intentado. Además, el nombre de la propiedad está en mi publicación - ComboBox.Items. Es una ObjectCollection específica de ComboBox. – acron

5

@acron, Gracias por proporcionar una gran pregunta y respuesta. Quiero extender su solución para un escenario ligeramente diferente para cualquiera que mire en el futuro.

enfrenta a un problema similar en el mundo ASP.NET yo estaba tratando de encontrar una forma común para cargar o bien un System.Web.UI.Webcontrols.DropDownList O una System.Web.UI.HtmlControls.HtmlSelect Si bien ambos tienen una propiedad "Elementos" de tipo "ListItemCollection", con el correspondiente método "Agregar", no comparten una interfaz común (, ya que DEBEN ... oye Microsoft ...) para que la conversión pueda ser usado.

El desafío adicional que su solución no previó es la sobrecarga del método Agregar.

Sin las sobrecargas, su línea: MethodInfo m = p.PropertyType.GetMethod(methodName); funciona bien. Pero, cuando el método Add está sobrecargado, se requiere un parámetro adicional para que el tiempo de ejecución pueda identificar qué sobrecarga invocar.

MethodInfo methInfo = propInfo.PropertyType.GetMethod("Add", new Type[] { typeof(ListItem) });

Cuestiones relacionadas