【问题标题】:How to find all objects that implement a interface and invoke a method如何查找所有实现接口并调用方法的对象
【发布时间】:2013-03-22 09:35:05
【问题描述】:

我有一个 UserControl 有几个子 UserControl,而那些 UserControl 有子 UserControl。

考虑一下:

MainUserControl
  TabControl
    TabItem
      UserControl
        UserControl
          UserControl : ISomeInterface
    TabItem
      UserControl
        UserControl
          UserControl : ISomeInterface
    TabItem
      UserControl
        UserControl
          UserControl : ISomeInterface
    TabItem
      UserControl
        UserControl
          UserControl : ISomeInterface

这是我目前所拥有的,但没有找到ISomeInterface

PropertyInfo[] properties = MainUserControl.GetType().GetProperties();
foreach (PropertyInfo property in properties)
{
    if (typeof(ISomeInterface).IsAssignableFrom(property.PropertyType))
    {
        property.GetType().InvokeMember("SomeMethod", BindingFlags.InvokeMethod, null, null, null);
    }
}

是否有可能从MainUserControl 中找到所有通过反射实现ISomeInterface 并在该接口上调用方法(void SomeMethod()) 的子UserControl

【问题讨论】:

  • 为什么你认为 GetProperties() 方法会递归下去?您正在枚举类型的属性,而不是整个控件层次结构。考虑改为枚举 Controls 集合。

标签: c# .net wpf reflection interface


【解决方案1】:

您需要递归遍历 MainUserControl 中的所有子控件。

这是一个你可以使用的辅助方法:

/// <summary>
/// Recursively lists all controls under a specified parent control.
/// Child controls are listed before their parents.
/// </summary>
/// <param name="parent">The control for which all child controls are returned</param>
/// <returns>Returns a sequence of all controls on the control or any of its children.</returns>

public static IEnumerable<Control> AllControls(Control parent)
{
    if (parent == null)
    {
        throw new ArgumentNullException("parent");
    }

    foreach (Control control in parent.Controls)
    {
        foreach (Control child in AllControls(control))
        {
            yield return child;
        }

        yield return control;
    }
}

然后:

foreach (var control in AllControls(MainUserControl))
{
    PropertyInfo[] properties = control.GetType().GetProperties();
    ... Your loop iterating over properties

或者(如果这对你有用,那就更好了,因为它更简单):

foreach (var control in AllControls(MainUserControl))
{
    var someInterface = control as ISomeInterface;

    if (someInterface != null)
    {
        someInterface.SomeMethod();
    }
}

或者,使用 Linq(需要 using System.Linq 来执行此操作):

foreach (var control in AllControls(MainUserControl).OfType<ISomeInterface>())
    control.SomeMethod();

这似乎是最好的。 :)

【讨论】:

  • 也许您可以使用 is 运算符添加。 OP 似乎正朝着使用反射的方向发展,而动态投射更容易(而且更便宜)(或者我也错过了什么?)
  • 是的,我就是这个意思。已经投票但想象中的+2然后:)
  • System.Windows.Controls.Control 没有 Controls 属性?!
  • @DiegoFrehner 你是对的 - .ControlsWindows.Forms.Control!对于 WPF,我们需要使用 VisualTreeHelper as described here。我不知道为什么 OP 什么也没说...
【解决方案2】:

也许我自己看错了方向。我对 Matthews 回答的评论的意思是:

 foreach (var control in AllControls(MainUserControl))
 {
     if (control is ISomeInterface)
     {

     }
 }

 foreach (var control in AllControls(MainUserControl))
 {
     var someInterface = control as ISomeInterface;
     if (someInterface != null)
     {
          someInterface.SomeMethod();
     }
 }

【讨论】:

  • 同意,我根据您的建议添加了它。 :)
猜你喜欢
  • 2013-08-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-04-07
  • 2014-04-05
  • 1970-01-01
  • 1970-01-01
  • 2010-12-17
相关资源
最近更新 更多