C# Appium/Selenium 派生 WindowsElement 在转换时抛出错误

C# Appium/Selenium Derive WindowsElement throws error on cast

在我的 C# .NET Framework 4.8 项目中,我试图派生 WindowsElement class 以在新的 class 中实现一些附加功能。 例如 ClickInMiddleOfControlIsVisibleSelectedItem(在 ComboBox 中)。

public class WindowsElementWrapper : WindowsElement
{
    public WindowsElementWrapper(RemoteWebDriver parent, string id) : base(parent, id) { }

    public void ClickInMiddleOfControl()
    {
        var rect = this.Rect;
        var offsetx = (int)(0.5 * rect.Width);
        var offsety = (int)(0.5 * rect.Height);
        new Actions(Helper.Session)
            .MoveToElement(this, 0, 0)
            .MoveByOffset(offsetx, offsety)
            .Click()
            .Build()
            .Perform();
    }
}

然后我尝试将 WindowsElement 投射到我的 WindowsElementWrapper。

var element = (WindowsElementWrapper)Session.FindElementByName("ElementName");
element.ClickInMiddleOfControl();

但是在运行时我收到以下错误消息:

System.InvalidCastException: 'Unable to cast object of type OpenQA.Selenium.Appium.Windows.WindowsElement' to type 'WEW.WindowsElementWrapper'.'

是否无法从 WindowsElement 派生class?还是我犯了根本性错误?

WindowsElementWindowsElementWrapper 的转换是 downcast

为了使向下转型成功,对象的运行时类型必须是目标类型本身,或者是从它派生的类型。

尽管 WindowsElementWrapperWindowsElement,但 WindowsElement 不一定是 WindowsElementWrapper

换句话说,这种向下转换永远不会成功,除非 SeleniumAPI 实例化 对象作为 WindowsElementWrapper 开始。

为了实现你想做的事情,你可以应用以下设计之一:


Composition

public class WindowsElementWrapper
{
   private readonly WindowsElement element;

   public WindowsElementWrapper(WindowsElement element, (int Width, int Height) rect)
   {
      this.element = element;
      Rect = rect;
   }

   public (int Width, int Height) Rect { get; init; }

   public void ClickInMiddleOfControl()
      => new Actions(Helper.Session)
            .MoveToElement(element, 0, 0)
            .MoveByOffset(Rect.Width / 2, Rect.Height / 2)
            .Click()
            .Build()
            .Perform();
}

Extension methods

public static class Extensions
{
   public static void ClickInMiddleOfControl(this WindowsElement source, (int Width, int Height) rect)
      => new Actions(Helper.Session)
            .MoveToElement(source, 0, 0)
            .MoveByOffset(rect.Width / 2, rect.Height / 2)
            .Click()
            .Build()
            .Perform();
}

此致