9

現在、バイナリ アプリケーション プロトコル用のライブラリを開発しています。次のコード サンプルはコンパイルされません (静的メソッドの定義は抽象型では許可されていません。残念ながら :()、私の意図を示しています。

public abstract class CmdBody<T>
{
    public static abstract byte[] ToBytes(T cmdBody);
    public abstract int GetLength();
}

public class CmdBodyA : CmdBody<CmdBodyA>
{
    static override byte[] ToBytes(CmdBodyA cmdBody) 
    { // Implementation }
}

public class CmdBodyB : CmdBody<CmdBodyB>
{
    static override byte[] ToBytes(CmdBodyB cmdBody)
    { // Implementation }
}

[...]

public class Cmd<T>
{ 
    public CmdHeader Header { get; set; }
    public CmdBody<T> Body { get; set; }

    public byte[] ToBytes()
    {
        byte[] cmdBytes = new byte[Header.GetLength() + Body.GetLength()];
        Header.ToBytes().CopyTo(cmdBytes, 0);
        Body.ToBytes().CoptyTo(cmdBytes, Header.GetLength());

        return cmdBytes;
    } 
}

非常に基本的なもので、Cmd は Header と Body で構成され、Header 型はすべての Cmd(s) に共通で、Body は Cmd 型に応じて異なるパラメーター (プロパティ) を持ちます。Cmd オブジェクトを操作したいと思います。 ToBytes() を呼び出して、ネットワーク経由で送信できるようにします。

私の実際の実装では、ToBytes() メソッドの代わりに変換演算子を使用していますが、コード サンプルをシンプルにしたかったので、最後に同じ仕事をします。

私はさまざまな種類のコマンドを持っていますが、それをシンプルに保ち、単一の汎用 Cmd 型だけで目的を達成するための解決策を見つけることができません。私が考えることができる唯一の解決策は、基本 CmdBody クラスの静的メソッドを取り除き、一般的な側面を取り除き、CmdBody タイプごとに関連する Cmd クラス (クラス CmdA、クラス CmdB ...) を作成することですが、これは1 日の終わりに多くのコードの重複が発生します。

これを回避するのに役立つ素敵なデザインのアイデアはありますか?

4

1 に答える 1

13

仮想/抽象/オーバーライドは実行時にインスタンスがオーバーライドされることを示唆しているため、「仮想」静的メソッドを持つことはできません。

ただし、次のようなこともできます。

public abstract class CmdBody
{
    public static byte[] ToBytes<T>(T cmdBody) where T : CmdBody
    {
         return cmdBody.ToBytes();
    }

    protected abstract byte[] ToBytes();

    public abstract int GetLength();
}

public class CmdBodyA : CmdBody
{
    protected override byte[] ToBytes() 
    { // Implementation }
}

public class CmdBodyB : CmdBody
{
    protected override byte[] ToBytes() 
    { // Implementation }
}

これにより、各「CmdBody」タイプはそれ自体をシリアル化する方法を定義できますが、基本クラスの静的メソッドは、それにアクセスするための唯一の公開された方法になります。

そうは言っても、ユースケースを考えると、これを静的にする理由はまったくありません。あなたはただ行うことができます:

public abstract class CmdBody
{
    public abstract byte[] ToBytes();

    public abstract int GetLength();
}

public class CmdBodyA : CmdBody
{
    public override byte[] ToBytes() 
    { // Implementation }
}

public class CmdBodyB : CmdBody
{
    public override byte[] ToBytes() 
    { // Implementation }
}


public class Cmd<T> where T : CmdBody
{ 
    public CmdHeader Header { get; set; }
    public T Body { get; set; }

    public byte[] ToBytes()
    {
        byte[] cmdBytes = new byte[Header.GetLength() + Body.GetLength()];
        Header.ToBytes().CopyTo(cmdBytes, 0);
        Body.ToBytes().CopyTo(cmdBytes, Header.GetLength());

        return cmdBytes;
    } 
}
于 2012-08-03T18:26:45.997 に答える