You need to enable JavaScript to run this app. C#继承WindowsElement扩展功能时强制转换抛出InvalidCastException问题
优惠活动
大模型
产品
解决方案
定价
更多

C#继承WindowsElement扩展功能时强制转换抛出InvalidCastException问题

错误原因

你的实现没有语法问题,WindowsElement也支持继承,报错的核心是父类实例无法直接强制转换为子类实例:Session.FindElementByName返回的对象本身就是原生WindowsElement类型,没有你的子类扩展的任何成员,运行时自然不允许这种向下转换。


推荐的3种实现方案

方案1:使用扩展方法(最简洁,优先推荐)

如果你的扩展方法不需要维护自定义状态,只是基于原生WindowsElement的属性做逻辑,直接用C#扩展方法即可,无需额外包装类:

// 必须放在静态类中
public static class WindowsElementExtensions
{
    public static void ClickInMiddleOfControl(this WindowsElement element)
    {
        if (element == null) throw new ArgumentNullException(nameof(element));
        
        var rect = element.Rect;
        var offsetx = (int)(0.5 * rect.Width);
        var offsety = (int)(0.5 * rect.Height);
        new Actions(Helper.Session)
            .MoveToElement(element, 0, 0)
            .MoveByOffset(offsetx, offsety)
            .Click()
            .Build()
            .Perform();
    }

    // 可以继续扩展你需要的其他方法
    public static bool IsVisible(this WindowsElement element) => element.Displayed;
}

调用方式和原生方法完全一致,不需要任何类型转换:

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

方案2:使用组合模式做包装类(无侵入,易扩展)

如果需要维护自定义状态,推荐用组合而非继承实现包装,避免类型转换问题:

public class WindowsElementWrapper
{
    // 内部持有原生WindowsElement实例
    public WindowsElement NativeElement { get; }

    public WindowsElementWrapper(WindowsElement nativeElement)
    {
        NativeElement = nativeElement ?? throw new ArgumentNullException(nameof(nativeElement));
    }

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

    // 需要用到原生方法时直接透传即可
    public void Click() => NativeElement.Click();
    public string Text => NativeElement.Text;
}

调用方式:

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

方案3:继承模式手动构造实例(不优先推荐)

如果确实有必须继承的场景(比如要重写父类虚方法),不要直接强转原生实例,而是取原生实例的参数手动构造子类对象:

var nativeElement = (WindowsElement)Session.FindElementByName("ElementName");
// 传入原生实例的驱动和ID手动构造子类
var wrapper = new WindowsElementWrapper(nativeElement.WrappedDriver, nativeElement.Id);
wrapper.ClickInMiddleOfControl();

该方案本质是生成了新的元素实例,性能和兼容性不如前两种,仅在必要时使用。

内容的提问来源于stack exchange,提问作者HeadlessJ

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.10 16:27:01