c# - 如何在 C# 中执行跨层次调用
问题描述
我正在开发一个简单的 GUI 框架,但在调用受保护的虚拟方法时遇到了问题。
这是IKeyboardInputListenerService
我用来接收键盘事件的服务接口和Control
代表我所有 GUI 控件的基础的类。内部方法是被重构的方法。
public interface IKeyboardInputListenerService
{
event EventHandler<KeyboardEventArgs> KeyPressed;
}
public abstract class Control
{
public IKeyboardInputListenerService KeyboardInputListenerService { get; }
protected Control(IKeyboardInputListenerService keyboardInputListenerService) =>
KeyboardInputListenerService = keyboardInputListenerService;
public event EventHandler<KeyboardEventArgs> KeyPressed;
/* protected */ internal virtual void OnKeyPressed(object sender, KeyboardEventArgs args)
{
if (enabled && visible && focused && !args.Suppressed)
{
KeyPressed?.Invoke(sender, args);
args.Suppressed = true;
}
}
public void Activate() =>
KeyboardInputListenerService.KeyPressed += new EventHandler<KeyboardEventArgs>(OnKeyPressed);
}
我还创建了一个ContainerControl
应该包含子控件的类(如 Windows 窗体中的Panel
or GroupBox
)并覆盖虚拟方法:
public abstract class ContainerControl : Control
{
private readonly ObservableCollection<Control> controls;
protected ContainerControl(IKeyboardInputListenerService keyboardInputListenerService)
: base(keyboardInputListenerService) =>
controls = new ObservableCollection<Control>();
/* protected */ internal override void OnKeyPressed(object sender, KeyboardEventArgs args)
{
foreach (Control control in controls)
control.OnKeyPressed(sender, args);
base.OnKeyPressed(sender, args);
}
}
问题是,我无法决定将哪个修饰符用于诸如OnKeyPressed
. 我想制作它们protected
,但它会导致编译器错误:
错误 CS1540 无法通过“Control”类型的限定符访问受保护的成员“Control.OnKeyPressed(object, KeyboardEventArgs)”;限定符必须是“ContainerControl”类型(或派生自它)
我可以制作它们public
,但我真的不认为这是一个好主意,因为除了解决跨层次调用引起的问题之外,没有任何理由这样做。我做了它们internal
,但也有一个缺点:如果有人想创建用户控件,他们将无法接收事件,因此控件将无用。
问题是如何从派生类访问基类的虚拟方法,而不使这些方法可以公开访问。
解决方案
利用protected internal
protected internal virtual void OnKeyPressed(object sender, KeyboardEventArgs args)
{ ... }
文档说:
protected internal类型或成员可以被声明它的程序集中的任何代码访问,也可以从另一个程序集中的派生类中访问。
推荐阅读
- python - python错误-TypeError:字符串索引必须是整数
- python - 如何在双元组上使用递归来总结第二个值?
- mysql - 条件更新查询
- drupal - 如何从 Drupal 8 中的 hook_form_alter 将参数传递给 ajax 回调
- java - Linux中散列命令之间的区别
- java - Using Intent to send user to another activity from Adapter
- git - 设置上游远程分支时不会运行预推送脚本
- css - 用于显示 CSS 属性定义的 WebStorm 工具
- java - Spring AMQP - 发布者确认不关闭未使用的频道
- reactjs - React Native 上的 redux 商店更改时键盘关闭