繁体   English   中英

查找在ASP.NET中使用某个接口的控件

[英]Finding controls that use a certain interface in ASP.NET

虽然我觉得我错过了一些显而易见的东西,但我对此有一个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()永远不会返回抽象类型/接口,因为您无法新建抽象类型或接口。 GetType()仅返回具体类型。

这不起作用的原因

if(ctrl is typeToFind)  

是因为变量typeToFind的类型实际上是System.RuntimeType ,而不是您将其值设置为的类型。 例如,如果将字符串的值设置为“ foo ”,则其类型仍为字符串而不是“ foo ”。 我希望这是有道理的。 使用类型时很容易混淆。 与他们一起工作时,我长期困惑。

关于longhorn213的答案最值得注意的是你必须使用递归,否则你可能会错过页面上的一些控件。

虽然我们在这里有一个可行的解决方案,但我也很想知道是否有更简洁的方法来使用LINQ。

您只需在界面上搜索即可。 如果控件具有子控件,即按钮位于面板中,这也使用递归。

private List<Control> FindControlsByType(ControlCollection controls, Type typeToFind)
{
    List<Control> foundList = new List<Control>();

    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<Control> childList = FindControlsByType(ctrl.Controls, typeToFind);

            foundList.AddRange(childList);
        }
    }

    return foundList;
}

// Pass it this way
FindControlsByType(Page.Controls, typeof(IYourInterface));

我对Longhorn213的例子进行了以下更改,以便稍微清理一下:

private List<T> FindControlsByType<T>(ControlCollection controls )
{
    List<T> foundList = new List<T>();

    foreach (Control ctrl in this.Page.Controls)
    {
        if (ctrl as T != null )
        {
            // Do whatever with interface
            foundList.Add(ctrl as T);
        }

        // Check if the Control has Child Controls and use Recursion
        // to keep checking them
        if (ctrl.HasControls())
        {
            // Call Function to 
            List<T> childList = FindControlsByType<T>( ctrl.Controls );

            foundList.AddRange( childList );
        }
    }

    return foundList;
}

// Pass it this way
FindControlsByType<IYourInterface>( Page.Controls );

通过这种方式,您可以获得所需类型的对象列表,这些对象不需要使用其他强制转换。 我还对其他人指出的“as”运算符进行了必要的更改。

接口足够接近它应该感觉相同的类型。 我使用as运算符

foreach (Control c in this.Page.Controls) {
    IMyButtonInterface myButton = c as IMyButtonInterface;
    if (myButton != null) {
        // do something
    }
}

您也可以根据需要使用is运算符进行测试。

if (c is IMyButtonInterface) {
    ...
}

“是”运营商会工作吗?

if (myControl is ISomeInterface)
{
  // do something
}

如果你打算在那种类型上做一些工作,那么我会使用TryCast。

Dim c as IInterface = TryCast(obj, IInterface)
If c IsNot Nothing
    'do work
End if

你总是可以使用as cast:

c as IMyButtonInterface;

if (c != null)
{
   // c is an IMyButtonInterface
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM