1

C# で TUI ライブラリを開発していますが、表示オブジェクトのカラー テーマを実行する方法についてアドバイスが必要です。画面に描画できるオブジェクトはすべて、このインターフェイスから継承されます。

public interface IDrawable
    {
        Area ScreenArea { get; }
        List<char[]> DisplayChars { get; }
        //some other properties...

    }

というか、より具体的には、各ドローアブル オブジェクトのインターフェイスがこのインターフェイスを実装しています (IWindowは ですIDrawable)。それぞれIDrawableが Area 構造体で表されるコンソール ウィンドウの指定された部分に描画されます。

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)
        {
            //....
        }
    }

オブジェクトの実際の描画は、DisplayChars の各要素を呼び出す静的Displayクラスのメソッドによって処理されます。Console.Write()から継承する各クラスに、IDrawableその領域を個別の色の領域に分割する方法について独自のルールを強制的に実装することを希望します。たとえば、ポップアップ ウィンドウには、外側の境界線、タイトル (外側の境界)、およびその内側の領域。

私は頭の中でこれを行う方法をしばらく考えていました。ColorSchemeどの文字をどの色で書くかというルールを含む型を に作成する必要があります。これを行う最善の方法は、色を個別に適用できる「サブエリア」のリストを含む抽象クラスにすることだと判断しました。

IDrawableから継承する独自のクラスを実装する必要がありますColorScheme。たとえば、抽象Window : IWindowクラスにはそのような実装はありませんが、クラスには、作成者がクラスを個別の領域に分割する方法を定義するPopupWindow : Window対応する型が必要です。それぞれに、このタイプの独自のインスタンスがあり、特定の色が含まれます。PopupWindowColorScheme : ColorSchemePopupWindowAreaPopupWindow

これは可能ですか?そうでない場合、IDrawable型の作成者にその領域を色付け可能な領域に分割する方法を指定させる別の方法はありますか?

4

1 に答える 1

0

IDrawableそれぞれに固有の実装を強制することはできませんColorScheme(たとえば、複数の異なる実装でIDrawable使用できますPopupWindowColorScheme)。ただし、次のように、ジェネリック型の制約を使用して、インターフェイスを実装するための追加の要件を追加できます。

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()
{
}

ここで、 の各実装は、それがIDrawableColorSchemeを使用するかを指定する必要があり、またそれぞれが適用対象ColorSchemeを指定する必要がありますIDrawable。また、それぞれがパラメーターなしのコンストラクターを必要とするため、どちらも共通の基本型を指定できません。これを実装すると、少し奇妙に見えます。

public class MyDrawable : IDrawable<MyDrawable, MyColorScheme> { }

public class MyColorScheme : ColorScheme<MyDrawable> { }

ColorScheme再利用可能なorを実装することはまだ可能ですIDrawable(例MyOtherDrawable : MyDrawableuses MyColorScheme)。ただし、私の意見では、これは実装がかなり面倒で退屈になり始めています。一般に、型制約を使用する技術的な理由がない限り、型制約使用することは避けたいと思います。

于 2016-05-08T01:52:03.583 に答える