首页 / 知识

关于c#:查找在ASP.NET中使用特定接口的控件

2023-04-13 06:32:00

关于c#:查找在ASP.NET中使用特定接口的控件

Finding controls that use a certain interface in ASP.NET

在这段时间里度过了愉快的时光,尽管我觉得我缺少明显的东西。我有一个从System.Web.UI.WebControls.Button继承的控件,然后实现了我设置的接口。所以想...

1
public class Button : System.Web.UI.WebControls.Button, IMyButtonInterface { ... }

在页面后面的代码中,我想从ASPX中找到此按钮的所有实例。因为我真的不知道类型是什么,所以只知道它实现的接口,这就是我遍历控制树时要做的所有事情。事实是,我不必确定对象是否使用接口,而不必测试其类型。我怎样才能遍历控制树并以干净的方式提取实现IMyButtonInterface的任何东西(Linq会很好)?

同样,知道这很明显,但是现在刚开始大量使用界面,我似乎无法集中我的Google结果来弄清楚它:)

编辑:GetType()返回实际的类,但不返回接口,因此我无法对此进行测试(例如,它将返回" MyNamespace.Button"而不是" IMyButtonInterface")。在递归函数中尝试使用" as"或" is"时,type参数甚至在函数中都未被识别!这很奇怪。所以

1
2
3
if(ctrl.GetType() == typeToFind) //ok

if(ctrl is typeToFind) //typeToFind isn't recognized! eh?

绝对是我的头。


Longhorn213几乎是正确的答案,但是正如肖恩·钱伯斯(sean Chambers)和bdukes所说,应该使用

1
ctrl is IInterfaceToFind

而不是

1
ctrl.GetType() == aTypeVariable

之所以这样,是因为如果使用.GetType(),您将获得对象的真实类型,不一定是它在继承/接口实现链中也可以转换为的对象。同样,.GetType()将永远不会返回抽象类型/接口,因为您无法新建抽象类型或接口。 GetType()仅返回具体类型。

不起作用的原因

1
if(ctrl is typeToFind)

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

关于longhorn213的答案,最重要的一点是您必须使用递归,否则您可能会错过页面上的某些控件。

尽管这里有一个可行的解决方案,但我也很想看看LINQ是否有更简洁的方法。


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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
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的示例进行以下更改以对其进行清理:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
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"运算符进行了必要的更改。


"运算符"是否可以工作?

1
2
3
4
if (myControl is ISomeInterface)
{
  // do something
}

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

1
2
3
4
5
6
foreach (Control c in this.Page.Controls) {
    IMyButtonInterface myButton = c as IMyButtonInterface;
    if (myButton != null) {
        // do something
    }
}

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

1
2
3
if (c is IMyButtonInterface) {
    ...
}

您总是可以使用as强制转换:

1
2
3
4
5
6
c as IMyButtonInterface;

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

如果您要对该类型进行一些工作,那么TryCast是我要使用的。

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

接口控件查找设置

最新内容

相关内容

热门文章

推荐文章

标签云

猜你喜欢