2017-07-09 1 views
1

最終的にWPF Windowクラスを保持するビューを継承する継承チェーンにオーバーロードされた仮想メソッドを呼び出すという奇妙な動作が発生しています。
オーバーロードされたメソッドは、より派生したインターフェイスを引数としてとりますが、代わりに、より少ない派生インターフェイス引数を受け取るメソッドを呼び出したように見えます。以下はオーバーロードされたメソッドの引数として `this`を渡す型問題

私が呼ばれ、引数として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ウィンドウ)が、登録するウィンドウから呼び出されます。

このクラスは、あまりにも最終的にはWPFのウィンドウクラスから、以下のコード、継承:

public interface IWpfWindow : IWindow 
{ 
    void AddRootElement(UIElement element); 
} 

public interface IWindow 
{ 
} 

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); 
    } 
} 

今、このクラスが順番にIWindowインターフェイスを拡張しないIWpfWindowインタフェースを実装それでも、クラスをIWpfWindowと見なすことは、これを渡す際にまず必要になります。 View.RegisterWindow(this)に渡す前にIWpfWindowにキャストしても、bevaviourは変更されません。

誰もがこれにどのような光を当てはめることができますか、または私はそれがオーバーロードされたメソッドを呼び出すことができますか?

+0

_「私はいくつかの奇妙な動作に遭遇しています」_プログラミングでは、「奇妙な動作」はほとんど常に本当に「私の誤解に合わない正常な動作」です。 –

+0

私は、人々がスタックオーバーフローに来る主な理由は、彼らのコンピュータが非合理的に働いていることを証明するのではなく、彼らの誤解を解決することだと思います。名前:ありがとう! –

答えて

0

コード例には、IViewインターフェイス宣言がありません。しかし、インターフェイスにはvoid RegisterWindow(IWindow)のオーバーロードしかないと仮定すると、あなたが記述した動作は完璧です。 ViewプロパティのタイプはIViewです。電話番号View.RegisterWindow(this)には、で通話することを選択するために、void RegisterWindow(IWindow)オーバーロードしかありません。それがあなたが得るものです。

率直に言えば、デザイン全体が私に壊れています。複数のインターフェイスでRegisterWindow()の複数の実装は、あなたが現在行っている混乱の種類を正確に求めています。

どのようにオーバーロードされたメソッドを呼び出すことができますか?

適切なタイプにViewをキャストする必要があります。

あなたの質問は、誰もが実際にが正しい解決策が何であるかを知ることができるようになるMinimal, Complete, and Verifiable example欠けているが、この場合には、それはあなたが呼び出しの目的のためにIWpfViewViewをキャストしたいだろうと思われます。さらに良いのは、ViewIWpfView View { get; }と宣言しているので、既にあなたが望むタイプです。宣言タイプはWpfWindowなので、タイプはIWpfViewとなります。

ボトムライン:これは呼び出しでViewの種類を行うには呼び出しで、このタイプのを行うには何も、およびすべてを持っていません。コンパイラは利用可能な唯一のオーバーロードを選択しています。

+0

あなたは正しいですが、私が見ることができなかったことは、私が間違った見方をしていたことでした。 WpfWindowは引数としてIWpfViewを取ることになっていましたが、これは正しいメソッドを公開していました。 しかし私は一般的なデザインに満足していません。WindowsのリストとRegisterWindow()の実装を避けるためにジェネリック型を追加すると思います。洞察力ありがとう! –

関連する問題