【问题标题】:Check for implementation of an Interface recursively, c#递归检查接口的实现,c#
【发布时间】:2010-11-12 16:58:32
【问题描述】:

我在 WebForm 中遇到一种情况,我需要通过控件树递归查找所有实现给定接口的控件。

我该怎么做?

我试过写这样的扩展方法

public static class ControlExtensions
{
    public static List<T> FindControlsByInterface<T>(this Control control)
    {
        List<T> retval = new List<T>();
        if (control.GetType() == typeof(T))                
            retval.Add((T)control);


        foreach (Control c in control.Controls)
        {
            retval.AddRange(c.FindControlsByInterface<T>());
        }

        return retval;
    }
}

但它不喜欢第 7 行对T 的强制转换。 我也想过尝试 as 运算符,但这不适用于接口。

我看到了Scott Hanselmans disucssion,但无法从中收集到任何有用的信息。

任何人都可以给我任何指示。谢谢。

格雷格

【问题讨论】:

  • 那个演员阵容给你带来了什么错误?你需要演员表吗?
  • as 运算符确实适用于接口。
  • 我假设您已经尝试过完全不强制转换控件和/或将返回值更改为控件列表,对吧?

标签: c# reflection interface recursion


【解决方案1】:

我觉得你需要把这个方法分成两部分

  1. 递归查找控件
  2. 查找实现基于 #1 的接口的控件

这里是#1

public static IEnumerable<Control> FindAllControls(this Control control) {
    yield return control;
    foreach ( var child in control.Controls ) {
        foreach ( var all in child.FindAllControls() ) {
          yield return all;
        }
    }
}

现在要获取一个类型的所有控件,请使用 OfType 扩展方法

var all = someControl.FindAllControls().OfType<ISomeInterface>();

【讨论】:

  • 不错!你错过了静态方法声明
  • 另外,第 3 行需要是“yield return control;”否则你会得到“关键字'this'在静态属性中无效,静态方法......”
  • 很好的解决方案 JaredPar。我没试过,但看起来你可以用'yield return child.FindAllControls();'替换内部foreach循环?
  • @dewald,很遗憾你不能这样做,因为收益回报不会扩展可枚举。您必须使用 for 循环手动扩展它:(
【解决方案2】:

我会使用 as 关键字。

public static class ControlExtensions {
    public static List<T> FindControlsByInterface<T>(this Control control) where T : class
    {
        List<T> retval = new List<T>();
        T item = control as T;
        if (T != null)
            retval.Add(item);

        foreach (Control c in control.Controls)
            retval.AddRange(c.FindControlsByInterface<T>());

        return retval;
    }
}

【讨论】:

  • 这需要对 T 进行类约束。
  • 嗨 Zyphrax,正如我上面所说的“我也想过尝试 as 运算符,但它不适用于接口。”。否则这会奏效
  • 好的,我认为这可行。您也可以使用 typeof(IInterface).isAssignableFrom(typeof(AClass)),我必须打开 Reflector 才能看到该方法的内部工作原理。但是 JaredPar 的解决方案非常好。
【解决方案3】:

演员真的有必要吗?如果你有一个实现 T 的控件,它不应该是。 另外,看看 is 关键字:

if (control is T)   
        retval.Add(control);

【讨论】:

  • 是的,因为编译器不允许您将 Control 类型的控件添加到 List 中,因为它不知道 T 是什么,因此您可以尝试执行 List.Add(new BananaRama());它不会喜欢这样的
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-01-06
  • 1970-01-01
  • 1970-01-01
  • 2022-01-09
  • 2010-09-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多