我遇到了一些奇怪的行为,在一个继承链中调用一个重载的虚方法,该方法扩展了一个最终拥有WPF Window类的视图。
重载方法将更多派生接口作为参数,但调用似乎使得该方法采用较小的派生接口参数。
下面是视图的继承链的相关部分,我希望调用IWpfWindow作为参数的重写方法:
public class EmbeddedBrowserWpfView : WpfView
{
protected IEmbeddedWpfBrowser Browser { get; }
protected IEmbeddedWpfBrowserFactory BrowserFactory { get; }
protected EmbeddedBrowserWpfView(IEmbeddedWpfBrowserFactory browserFactory) : base()
{
this.BrowserFactory = browserFactory;
this.Browser = BrowserFactory.Create();
}
public override IDisposable RegisterWindow(IWpfWindow window)
{
var unsubscriber = base.RegisterWindow(window);
window.AddRootElement(Browser.Element);
return unsubscriber;
}
}
public class WpfView : ViewBase, IWpfView
{
protected new ICollection<IWpfWindow> Windows { get; }
public WpfView() : base()
{
this.Windows = new List<IWpfWindow>();
}
public virtual IDisposable RegisterWindow(IWpfWindow window)
{
// Check whether view is already registered. If not, add it
if (!Windows.Contains(window))
{
Windows.Add(window);
}
return new SimpleUnsubscriber<IWpfWindow>(Windows, window);
}
}
public abstract class ViewBase : IView
{
protected ICollection<IWindow> Windows { get; }
protected ViewBase()
{
this.Windows = new List<IWindow>();
}
public virtual IDisposable RegisterWindow(IWindow window)
{
// Check whether view is already registered. If not, add it
if (!Windows.Contains(window))
{
Windows.Add(window);
}
return new SimpleUnsubscriber<IWindow>(Windows, window);
}
}
我希望调用的方法是EmbeddedBrowserWpfView类中的RegisterWindow(IWpfWindow窗口)。
相反,来自ViewBase类的RegisterWindow(IWindow窗口)是从想要注册它的Window中调用的。
这个类也最终从WPF窗口类继承下面的代码:
public class FullScreenWpfWindow : WpfWindow, IWpfWindow
{
public FullScreenWpfWindow(IView view) : base(view)
{
}
}
public partial class WpfWindow : Window, IWpfWindow
{
protected IView View { get; }
public WpfWindow(IView view)
{
this.View = view;
InitializeComponent();
View.RegisterWindow(this);
}
public void AddRootElement(UIElement element)
{
RootGrid.Children.Add(element);
}
}
现在这个类实现了IWpfWindow接口,后者又扩展了IWindow接口:
public interface IWpfWindow : IWindow
{
void AddRootElement(UIElement element);
}
public interface IWindow
{
}
尽管如此,我还是希望班级在传递它时首先将自己视为IWpfWindow。请注意,即使将其传递给IWpfWindow,然后将其传递给View.RegisterWindow(this)也不会改变bevaviour。
任何人都可以对此有所了解或如何让它调用重载方法?
答案 0 :(得分:0)
您的代码示例缺少IView
接口声明。但是,假设接口只有void RegisterWindow(IWindow)
重载,那么您描述的行为非常有意义。 View
属性的类型为IView
。来电View.RegisterWindow(this)
只有void RegisterWindow(IWindow)
重载,可以选择与this
通话。这就是你得到的。
RegisterWindow()
的多个实现只是要求您正好拥有的那种混淆。
我怎样才能调用重载方法?
您必须将View
投射到合适的类型。
您的问题缺少允许任何人实际知道正确解决方案的Minimal, Complete, and Verifiable example,但在这种情况下,您可能希望投射{{1} } View
用于呼叫目的。更好的是,只需将IWpfView
声明为View
,因此它已经是您想要的类型。由于声明类型为IWpfView View { get; }
,因此类型可能为WpfWindow
似乎是合理的。
底线:这与呼叫中的此类型无有关,而一切与呼叫中IWpfView
的类型有关。编译器正在挑选唯一可用的重载。