我正在用C#开发一个TUI库,我需要有关如何为显示对象做颜色主题的建议。可以在屏幕上绘制的对象都继承自此界面:
public interface IDrawable
{
Area ScreenArea { get; }
List<char[]> DisplayChars { get; }
//some other properties...
}
或者更确切地说,每个可绘制对象的接口实现此接口(IWindow
是IDrawable
)。每个IDrawable
都绘制在由区域结构表示的控制台窗口的指定部分上:
public struct Area
{
public readonly int EndX;
public readonly int EndY;
public readonly int Height;
public readonly int StartX;
public readonly int StartY;
public readonly int Width;
public Area(int startX, int endX, int startY, int endY)
{
StartX = startX;
EndX = endX;
StartY = startY;
EndY = endY;
Height = endY - startY;
Width = endX - startX;
}
/// <summary>
/// Get the overlapping area between this area and another.
/// </summary>
/// <param name="refArea"></param>
/// <returns>Overlap area relative to the upper left corner of the ref area.</returns>
public Area OverlapWith(Area refArea)
{
//....
}
}
对象的实际绘制由静态Display
类中的方法处理,该类在DisplayChars中的每个元素上调用Console.Write()
。我希望从IDrawable
继承的每个类被强制实现自己的规则,如何将其区域划分为单独的颜色区域,例如,弹出窗口可能具有用于其外边界的单独可着色区域,它的标题(在其外边界内)及其内部区域。
我已经在脑子里捣乱了一段时间。我需要创建一个类型ColorScheme
,以包含用什么颜色写入哪些字符的规则。我决定最好的方法是将它作为一个抽象类,其中包含一个&#34;子区域列表&#34;这些颜色可以单独应用。
我希望每个非抽象IDrawable
都必须实现自己继承自ColorScheme
的类。例如,抽象Window : IWindow
类没有这样的实现,但PopupWindow : Window
类必须具有相应类型的PopupWindowColorScheme : ColorScheme
,其中PopupWindow
的作者将定义如何分开课程&#39; Area
分为不同的区域。每个PopupWindow
都有自己的此类型实例来包含其特定的颜色。
这可能吗?如果没有,是否有另一种方法可以强制IDrawable
类型的作者指定将其区域划分为可着色区域的方法?
答案 0 :(得分:0)
您无法强制每个IDrawable
拥有ColorScheme
的唯一实现(例如IDrawable
的多个不同实现可以使用PopupWindowColorScheme
)。但是,您可以使用generic type constraints添加实现界面的其他要求,如下所示:
public interface IDrawable<TColorScheme>
where TColorScheme : ColorScheme
{
Area ScreenArea { get; }
List<char[]> DisplayChars { get; }
//some other properties...
TColorScheme ColorScheme { get; }
}
现在,IDrawable
的每个实现都需要指定要使用的ColorScheme
类型。但消费者可能只是实施IDrawable<ColorScheme>
这种目的(取决于您的要求)。我们可以更进一步:
public interface IDrawable<TColorScheme>
where TColorScheme : ColorScheme, new()
{
}
public abstract class ColorScheme { }
这里,由于ColorScheme
是抽象的,并且泛型类型约束需要提供的类型参数来实现无参数构造函数(new()
),因此ColorScheme
本身不能用作参数。任何实现类都需要指定ColorScheme
的自定义实现,该实现提供公共的无参数构造函数。
但我们可以走得更远:
public interface IDrawable { }
public interface IDrawable<TDrawable, TColorScheme> : IDrawable
where TDrawable : IDrawable, new()
where TColorScheme : ColorScheme<TDrawable>, new()
{
object ScreenArea { get; }
List<char[]> DisplayChars { get; }
//some other properties...
TColorScheme ColorScheme { get; }
}
public abstract class ColorScheme<TDrawable>
where TDrawable : IDrawable, new()
{
}
此处,IDrawable
的每个实现都必须指定ColorScheme
使用的 和 每个ColorScheme
还必须指定IDrawable
它适用于。并且因为每个都需要无参数构造函数,所以它们都不能指定公共基类型。实现这一点现在看起来有点奇怪:
public class MyDrawable : IDrawable<MyDrawable, MyColorScheme> { }
public class MyColorScheme : ColorScheme<MyDrawable> { }
仍然可以实现可重复使用的ColorScheme
或IDrawable
,(例如MyOtherDrawable : MyDrawable
使用MyColorScheme
)。但是,在我看来,这开始变得相当繁琐和冗长。一般情况下,除非您有技术原因导致 使用类型约束,否则我会避免使用它,因为您将来会发现它过于局限。