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
相关产品推荐
相关产品推荐

