2

我有一个Window代表桌面窗口的类,其中一些可以通过包装器(TitledWindow)命名,其中一些可以在其他之上,也可以通过包装器(TopWindow)。

UML 视图

现在,我正在尝试为 a 创建一个视图模型Window,并且我希望它支持这三个接口(IWindowITitledWindowITopWindow。它看起来像这样:

public class WindowViewModel : ITopWindow, ITitledWindow
{
    private readonly IWindow _window;

    public WindowViewModel(IWindow window)
    {
        _window = window;
    }

    public IntPtr Handle
    {
        get { return _window.Handle; }
    }

    public Boolean? IsTopmost
    {
        get
        {
            var thisTopWindow = _window as ITopWindow;
            if (thisTopWindow == null)
                return null;
            return thisTopWindow.IsTopmost;
        }
        set
        {
            var thisTopWindow = _window as ITopWindow;
            if (thisTopWindow != null)
                thisTopWindow.IsTopmost = value;
        }
    }

    public String Title
    {
        get
        {
            var thisTitledWindow = _window as ITitledWindow;
            return thisTitledWindow == null ? null : thisTitledWindow.Title;
        }
    }
}

这就是我获得视图模型的方式:

public IList<WindowViewModel> OpenWindows
{
    get
    {
        var windowViewModels =
            from window in _windowEnumerator.EnumerateWindows()
            let titledWindow = new TitledWindow(window, _windowTitleReader)
            let topWindow = new TopWindow(titledWindow, _topmostManager)
            select new WindowViewModel(topWindow);
        return windowViewModels.ToList();
    }
}

问题是我只能获得层次结构中的第一个包装器。

中的所有窗口OpenWindows也是ITopWindow,但不是ITitledWindow因为它将它包装在一个private readonly字段中(可能应该保持这种方式)。

我想到的唯一解决方案是引入一个将它们联合起来的类(比如TitledTopWindow),但我必须为窗口的每个变体都做它,这太混乱了(特别是后来当我引入新的包装器来引入新功能时) .

正确的方法是什么?

更新:
在我的搜索中,我读到您使用包装器来扩展功能,而不是扩展 API(这是这里的目标)。

因此,如果这个问题不能以我想要的方式解决,我该如何以这种方式添加功能?

4

1 回答 1

2

我的建议类似于

 class Window
 {
     List<object> traits;  

     T GetTrait<T>() 
     {
        return traits.Where(t => t.GetType() == typeof(T)).FirstOrDefault();
     } 
 }

 Window w;
 var topLevel = w.GetTrait<TopLevel>();
 if (topLevel != null)....

但是这个建议需要对接口/代码进行认真的修改。

我认为你真的想要像遵循无效代码这样的东西,这样你就可以添加任意数量的包装器,并且仍然让所有接口在最终类上可见:

 class TopLevel<T> : T where T:Window

我认为你不能直接实现这一点(因为你不能从模板参数派生模板类)。

一种解决方法是在运行时生成派生类,添加必要的接口并代理内部类实现的所有接口。在动态创建代理类(即这个简单的动态代理)中讨论/链接的可能方法。

于 2013-10-27T23:15:42.950 回答