【发布时间】:2013-10-27 18:38:33
【问题描述】:
我有一个代表桌面窗口的Window 类,其中一些可以通过包装器 (TitledWindow) 命名,其中一些可以通过包装器 (TopWindow )。
现在,我正在尝试为Window 创建一个视图模型,并且我希望它支持这三个接口(@987654327@、ITitledWindow 和ITopWindow)。它看起来像这样:
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();
}
}
问题是我只能获得层次结构中的 1st 包装器。
OpenWindows 中的所有窗口也是ITopWindow,但不是ITitledWindow,因为它将其包装在private readonly 字段中(可能应该保持这种方式)。
我想到的唯一解决方案是引入一个将它们合并的类(如TitledTopWindow),但我必须为窗口的每一个变化都做它,这太混乱了(尤其是稍后当我引入新的引入新功能的包装器)。
正确的做法是什么?
更新:
在我的搜索中,我读到您使用包装器来扩展功能,而不是扩展 API(这是这里的目标)。
那么如果这个问题不能按照我想要的方式解决,我该如何以这种方式添加功能?
【问题讨论】:
-
如果您的样本接近您想要实现的目标,请考虑包含而不是继承:窗口可以包含可通过界面搜索的“特征”实例列表。
-
是否必须将这些接口分开?如果没有,您可以将它们折叠到 Window 中,为所有操作提供默认/回退实现(如果需要,NotImplementedException),引入一个中间包装类,它将所有可选操作委托给被包装的实例,并让您的具体包装从它继承。然后,具体类会覆盖属于相应功能的方法。 (另请参阅Decorator pattern)但正如您所想象的那样,这仍然有其自身的缺点。
-
@AlexeiLevenkov 我会很感激一个例子或一个很好的参考。
-
@JayK 不能将界面折叠成
Window。正如你所看到的,包装器/装饰器已经被使用了。这就是问题所在。
标签: c# oop design-patterns mvvm wrapper