虽然我觉得我错过了一些显而易见的东西,但我对此有一个heckuva时间.我有一个继承自的控件,System.Web.UI.WebControls.Button
然后实现我已设置的接口.所以想想......
public class Button : System.Web.UI.WebControls.Button, IMyButtonInterface { ... }
在页面的代码隐藏中,我想从ASPX中找到该按钮的所有实例.因为我真的不知道它将是什么类型,只是它实现的接口,这是我在循环控制树时所要做的.事实上,我从来没有必须确定一个对象是否使用接口而不仅仅是测试它的类型.我怎样才能遍历控制树并IMyButtonInterface
以干净的方式抽出任何实现的东西(Linq会好的)?
再次,知道它是显而易见的,但刚刚开始大量使用接口,我似乎无法专注于我的谷歌搜索结果:)
编辑: GetType()
返回实际的类,但不返回接口,所以我无法测试(例如,它返回" MyNamespace.Button
"而不是" IMyButtonInterface
").在尝试在递归函数中使用" as
"或" is
"时,type
参数甚至无法在函数内被识别!这很奇怪.所以
if(ctrl.GetType() == typeToFind) //ok if(ctrl is typeToFind) //typeToFind isn't recognized! eh?
绝对是在这个问题上摸不着头脑.
Longhorn213几乎有正确的答案,但正如Sean Chambers和bdukes所说,你应该使用
ctrl is IInterfaceToFind
代替
ctrl.GetType() == aTypeVariable
原因在于,如果您使用,.GetType()
您将获得对象的真实类型,不一定也可以在其继承/接口实现链中转换为它.此外,.GetType()
永远不会返回抽象类型/接口,因为您无法新建抽象类型或接口.GetType()
仅返回具体类型.
这不起作用的原因
if(ctrl is typeToFind)
是因为变量的类型typeToFind
实际上是System.RuntimeType
,而不是您设置其值的类型.例如,如果将字符串的值设置为" foo
",则其类型仍为字符串而不是" foo
".我希望这是有道理的.使用类型时很容易混淆.与他们一起工作时,我长期困惑.
关于longhorn213的答案最值得注意的是你必须使用递归,否则你可能会错过页面上的一些控件.
虽然我们在这里有一个可行的解决方案,但我也很想知道是否有更简洁的方法来使用LINQ.
您只需在界面上搜索即可.如果控件具有子控件,即按钮位于面板中,这也使用递归.
private ListFindControlsByType(ControlCollection controls, Type typeToFind) { List foundList = new List (); foreach (Control ctrl in this.Page.Controls) { if (ctrl.GetType() == typeToFind) { // Do whatever with interface foundList.Add(ctrl); } // Check if the Control has Child Controls and use Recursion // to keep checking them if (ctrl.HasControls()) { // Call Function to List childList = FindControlsByType(ctrl.Controls, typeToFind); foundList.AddRange(childList); } } return foundList; } // Pass it this way FindControlsByType(Page.Controls, typeof(IYourInterface));