键入问题将`this`作为参数传递给重载方法

时间:2017-07-09 23:01:04

标签: c# wpf inheritance interface overloading

我遇到了一些奇怪的行为,在一个继承链中调用一个重载的虚方法,该方法扩展了一个最终拥有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。

任何人都可以对此有所了解或如何让它调用重载方法?

1 个答案:

答案 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的类型有关。编译器正在挑选唯一可用的重载。