2011-03-21 104 views
11

我试图做的是调用属性的方法,使用反射的方法。我有原始的控件(一个ComboBox),属性的PropertyInfo(ComboBox.Items)和方法名称(ComboBox.Items.Add)。我试过下面的代码来获取,修改,设置,但它不起作用,因为Items没有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 

有没有人有任何建议?

感谢

+1

正如一个建议,如果你有兴趣在通过反射更容易这样的拨打电话和使用C#4,你可能希望在DynamicObject来包装这个反射功能。我写了一个关于如何做到这一点在这里发布:http://mattmc3.blogspot.com/2011/03/fun-with-dynamicobject-and-making-net.html – mattmc3 2011-03-21 15:27:24

+0

哦,我要看看谢谢! – acron 2011-03-22 09:04:50

回答

14

快啊......我改变了调用线...

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

...和它的工作:P

+9

当人们找到答案,然后发布他们如何解决自己的问题时,我绝对喜欢。我希望更多的人这样做。 – jermny 2013-01-29 14:52:43

+0

这个改变是如何工作的?你能解释一下哪里出了问题? – 2015-10-15 20:22:19

+0

@PavanManjunath我并不完全确定我害怕。这可能是我将'GetValue'的结果隐式转换为''object'',而'Invoke'无法取消装箱。 – acron 2015-10-18 19:15:34

1

,你得到的错误指示该财产是只读的。没有定义设置的方法。如果没有设置器,您将无法设置该属性的值。

回来后与物业或多个上下文的名字,我们或许可以给你一个更好的答案或替代。

+0

是的,我意识到这是因为没有二传手。我的代码只是我尝试过的一个例子。此外,该属性的名称是在我的后 - ComboBox.Items。这是一个ComboBox特有的ObjectCollection。 – acron 2011-03-22 09:04:09

5

@acron,感谢您提供一个很好的问题和答案。我希望扩展您的解决方案,为面向未来的任何人提供稍微不同的场景。

在ASP.NET世界面临着类似的问题,我试图找到为加载System.Web.UI.Webcontrols.DropDownListSystem.Web.UI.HtmlControls.HtmlSelect的常用方法尽管这两种有一个“项目”类型“ListItemCollection”的属性,具有相应的“添加”方法,它们不共享一个通用的接口(,因为他们应该...哎...微软),使铸件能使用。

您的解决方案并没有提供额外的挑战是Add方法的重载。

没有过载你的线路: MethodInfo m = p.PropertyType.GetMethod(methodName); 工作得很好。但是,当Add方法被重载时,会调用一个附加参数,以便运行时可以识别要调用的重载。

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