Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using Reflection to call a method of a property

What I'm trying to do is call the method of a property, using Reflection. I have the original Control (a ComboBox), the PropertyInfo of the property (ComboBox.Items) and the name of the method (ComboBox.Items.Add). I've tried the code below to get, alter, set but it doesn't work because Items doesn't have a setter.

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

Does anyone have any advice?

Thanks

like image 273
Antony Woods Avatar asked Mar 21 '11 15:03

Antony Woods


People also ask

How does reflection set property value?

To set property values via Reflection, you must use the Type. GetProperty() method, then invoke the PropertyInfo. SetValue() method. The default overload that we used accepts the object in which to set the property value, the value itself, and an object array, which in our example is null.

What is reflection explain how do you invoke methods using reflection with an example?

Reflection provides objects (of type Type) that describe assemblies, modules, and types. You can use reflection to dynamically create an instance of a type, bind the type to an existing object, or get the type from an existing object and invoke its methods or access its fields and properties.

How do you call MethodInfo?

To invoke a static method using its MethodInfo object, pass null for obj . If this method overload is used to invoke an instance constructor, the object supplied for obj is reinitialized; that is, all instance initializers are executed. The return value is null .


2 Answers

That was quick... I changed the Invoke line to...

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

...and it worked :P

like image 161
Antony Woods Avatar answered Sep 25 '22 00:09

Antony Woods


@acron, Thanks for providing a great question and answer. I want to extend your solution for a slightly different scenario for anyone looking in the future.

Facing a similar problem in the ASP.NET world I was trying to find a common way to load either a System.Web.UI.Webcontrols.DropDownList OR a System.Web.UI.HtmlControls.HtmlSelect While both of these have an "Items" property of type "ListItemCollection", with a corresponding "Add" method, they do not share a common interface (as they SHOULD... hey Microsoft...) so that casting can be used.

The additional challenge that your solution didn't provide for is the overloading of the Add method.

Without the overloads your line: MethodInfo m = p.PropertyType.GetMethod(methodName); works just fine. But, when the Add method is overloaded an additional parameter is called for so that the runtime can identify which overload to invoke.

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

like image 37
Cos Callis Avatar answered Sep 26 '22 00:09

Cos Callis