2012-08-03 5 views
7

Attualmente sto sviluppando una libreria per un protocollo di applicazione binaria. Il seguente esempio di codice non viene compilato (metodi statici definizione non ammessi nel tipo astratto Peccato :(.), Ma mostra la mia intenzione:Impossibile definire i metodi statici nei tipi astratti. Come lavorare intorno?

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; 
    } 
} 

roba di base così bella, un Cmd è costituito da un un'intestazione e un corpo , Il tipo di intestazione è comune a tutti i Cmd (s) e Body con parametri diversi (proprietà) dipendenti dal tipo Cmd e mi piacerebbe lavorare con oggetti Cmd e poter richiamare ToBytes() su di essi per inviarli rete

Nella mia implementazione reale sto utilizzando l'operatore di conversione anziché il metodo ToBytes(), ma volevo mantenere semplice l'esempio del codice, alla fine fa lo stesso lavoro.

Ho molti tipi di comando diversi e non riesco a trovare una soluzione per mantenerlo semplice e ottenere ciò che voglio con un solo tipo Cmd generico. L'unica soluzione che posso pensare sarebbe quella di eliminare il metodo statico nella classe base CmdBody, eliminare l'aspetto generico e per ogni tipo CmdBody creare una classe Cmd associata (classe CmdA, classe CmdB ...) ma questo comporterà molti duplicati di codice alla fine della giornata.

Qualche idea per un bel tentativo di aiutarmi a lavorare intorno a questo?

+0

È possibile che tu stia cercando un'interfaccia, piuttosto che un tipo astratto? Un tipo astratto viene utilizzato per definire le classi che ne ereditano, in cui viene utilizzata un'interfaccia per definire i metodi ei campi richiesti per una classe da implementare. – Codeman

+0

Non importa qui. Interfaccia o classi astratte non possono definire metodi statici, il problema del design rimarrebbe. – darkey

+0

=/Non è possibile definire metodi statici senza implementazione su classi astratte. (Un membro statico non può essere contrassegnato come override, virtuale o astratto) – marcoaoteixeira

risposta

13

Non è possibile avere metodi statici "virtuali", poiché virtuale/abstract/override suggerisce di sovrascrivere un'istanzain fase di runtime.

Si potrebbe fare qualcosa di simile, però:

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 } 
} 

Questo permette ad ogni tipo "CmdBody" per definire come essa si è serializzato, ma il metodo statico della classe base da l'unico modo pubblicamente visibile per accedervi .

Detto questo, dato il tuo caso d'uso, non c'è motivo per fare questo statico affatto. Basta fare:

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; 
    } 
} 
+0

Woooo! Molto bello il lavoro nel tuo primo esempio di codice. Roba sexy :) E grazie mille per la tua seconda proposta (dovresti solo modificarla per rimuovere una delle definizioni ToBytes() in CmdBody). Molte grazie ! – darkey

+0

@darkey Risolto il problema con ToBytes ... –

Problemi correlati