C#设计-本质上,如何在没有空接口的情况下将类和枚举分组到列表中?

问题描述 投票:1回答:1

我正在设计文本渲染器。我正在建立如何将字符串分成几行以适合文本框的逻辑。我要这样做的方法是,首先将完整的字符串分成“单词”,“空格”和“换行符”,然后构建一种算法来测量一行中可以容纳多少行,然后再移动到下一行。

但是,“ Word”必须是一个类/结构,因为它要保留“ FontStyle”,“ Colour”等附加属性。“ Space”和“ NewLine”仅是标记-不需要任何标记数据。

目前,我具有以下框架:

interface ILineComponent
{
}

struct Word : ILineComponent
{
    public string Text;
    public FontStyle Style;
    public Colour Colour;

    public Word(string text, FontStyle style, Colour colour)
    {
        Text = text;
        Style = style;
        Colour = colour;
    }
}

struct Space : ILineComponent
{
}

struct NewLine : ILineComponent
{
}

struct Line
{
    public List<ILineComponent> Segments;

    public Line(List<ILineComponent> segments)
    {
        Segments = segments;
    }
}

然后,我的想法是通过直线,并测量将一条线(或单词,...,换行符)分解为另一条线之前,要在一行(或单词,...,换行符)中容纳多少(单词,空格,...,单词,空格)线。目前,这将利用如下逻辑:

foreach (ILineComponent component in line)
{
    if (component is Word)
    //..
    else if (component is Space)
    //...
    else if (component is NewLine)
    //...
}

但是此设计违反了CA1040

我该如何更好地设计?

c# list interface
1个回答
0
投票

首先,我认为Space的定义不完整。没有字体也无法确定空间的宽度。因此,我认为空间应类似于Word。也许它不需要颜色,当然也不需要文本作为参数。

struct Space : ILineComponent
{
    public readonly string Text = " ";
    public FontStyle Style;

    public Word(FontStyle style)
    {
        Style = style;
    }
}

我也认为此代码具有误导性

foreach (ILineComponent component in line)

由于您尚不知道,所以会有多少行,所以变量line不正确。该值应为componentsOfText或类似值。在循环内,您将在需要时开始新行。

接下来,我建议您将这三个组件需要做的所有事情都放入界面中。据我了解,那就是:

interface ILineComponent
{
    int Measure();
    bool IsTrimmedAtEndOfLine;
    bool TerminatesLine;
}

您的代码如下所示:

//       IList<LineComponent> is a line
// IList<       -"-          > are many lines
// Maybe you want to define an alias for that, or even a class
IList<IList<ILineComponent>> lines = new ...;

int remainingSpace = 2000; // px or whatever
while (componentsOfText.Length > 0)
{
     component = componentsOfText[0];

     var space = component.Measure();
     if (space > remainingSpace)
     {
          // finish current line and start a new one, 
          // i.e. add a new List<LineComponent>,
          // reset remaining space,
          // do the line post processing (e.g. space width adjustment)

          // Do not remove component from the list
          continue;
     }

     if (component.TerminatesLine)
     {
           // Finish current line and start a new line
           // just as before
     }

     remainingSpace -= space;
     // Remove component from the list
}

对于“完成当前行并开始新的行::

var lastitem = line[line.Count - 1];
if (lastitem.IsTrimmedAtEndOfLine)
{
    line.Remove(lastitem);
}

// start the second pass for calculating the width of a space etc.
© www.soinside.com 2019 - 2024. All rights reserved.