Domanda

Prima di tutto, ho capito le ragioni per cui un'interfaccia o una classe astratta (in .NET/C# la terminologia) non può avere abstract metodi statici.La mia domanda è quindi più incentrata sul design migliore.

Quello che voglio è un insieme di "helper" classi che tutti hanno i loro propri metodi statici in modo tale che se ho oggetti A, B, e C da un fornitore di terze parti, posso avere il supporto di classi con metodi come

AHelper.RetrieveByID(string id);
AHelper.RetrieveByName(string name);
AHelper.DumpToDatabase();

Dal momento che il mio AHelper, BHelper, e CHelper classi saranno tutti in fondo hanno gli stessi metodi, sembra a senso spostare questi metodi di un'interfaccia che queste classi derivare da.Tuttavia, volendo questi metodi statici osta a me di avere una interfaccia generica o astratta classe di provenienza.

Ho sempre potuto fare di questi metodi non statici e quindi istanziare gli oggetti prima come

AHelper a = new AHelper();
a.DumpToDatabase();

Tuttavia, questo codice non sembra così intuitivo per me.Quali sono i vostri suggerimenti?Devo abbandonare il tramite di un'interfaccia o classe astratta del tutto (la situazione in cui mi trovo ora) oppure possono eventualmente essere rielaborato per realizzare il progetto che sto cercando?

È stato utile?

Soluzione

Guardando la tua risposta Sto pensando lungo le seguenti linee:

  • Si potrebbe semplicemente avere un metodo statico che accetta un parametro di tipo, ed esegue il previsto logica in base al tipo.
  • Si potrebbe creare un metodo virtuale nella vostra base astratta, in cui si specifica il codice SQL nella classe di calcestruzzo.Così, che contiene tutto il codice che viene richiesto da entrambi (ad es.exectuting il comando e la restituzione di un oggetto) e includere l' "specialista" bit (es.SQL) nella sotto-classi.

Io preferisco la seconda opzione, anche se la sua naturalmente verso di voi.Se hai bisogno di me per andare in ulteriori dettagli, per favore fatemelo sapere e sarò felice di modifica/aggiornamento :)

Altri suggerimenti

Se fossi in te, cercherei di evitare qualsiasi statica.IMHO ho sempre finito con un qualche tipo di problemi di sincronizzazione giù per la strada con la statica.Detto questo si sta presentando un classico esempio di programmazione generica utilizzando i modelli.Voglio adottare il modello di soluzione a base di Rob Rame presentato in uno dei post sopra.

Per una generica soluzione per il tuo esempio, si può fare questo:

public static T RetrieveByID<T>(string ID)
{
     var fieldNames = getFieldNamesBasedOnType(typeof(T));
     QueryResult qr = webservice.query("SELECT "+fieldNames + " FROM "
                                     + tyepof(T).Name
                                     +" WHERE Id = '" + ID + "'");
     return (T) qr.records[0];
}

Io personalmente sarebbe forse domanda perché ciascuno dei tipi, è necessario disporre di un metodo statico prima ancora di pensare di più.

Perché non creare una utlity di classe con i metodi statici che hanno bisogno di condividere?(ad es. ClassHelper.RetrieveByID(string id) o ClassHelper<ClassA>.RetrieveByID(string id)

Nella mia esperienza con questo genere di "posti di blocco" il problema non sono i limiti della lingua, ma i limiti di un mio disegno..

Come sono ObjectA e AHelper correlati?È AHelper.RetrieveByID() la stessa logica BHelper.RetrieveByID()

Se Sì, come su di una classe di Utilità che come approccio di base (classe con metodi statici pubblici e non solo di stato)

static [return type] Helper.RetrieveByID(ObjectX x) 

Non è possibile eseguire l'overload di metodi variando il tipo restituito.

È possibile utilizzare diversi nomi:

static AObject GetAObject(string id);
static BObject GetBObject(string id);

Oppure si può creare una classe con colata di operatori:

class AOrBObject
{ 
   string id;
   AOrBObject(string id) {this.id = id;}

   static public AOrBObject RetrieveByID(string id)
   {
        return new AOrBObject(id);
   }

   public static AObject explicit operator(AOrBObject ab) 
    { 
        return AObjectQuery(ab.id);
    }

   public static BObject explicit operator(AOrBObject ab)
    { 
        return BObjectQuery(ab.id);
    } 
}

Poi si può chiamare in questo modo:

 var a = (AObject) AOrBObject.RetrieveByID(5);
 var b = (BObject) AOrBObject.RetrieveByID(5); 

In C# 3.0, i metodi statici possono essere utilizzati su interfacce come se fossero una parte di loro utilizzando i metodi di estensione, come DumpToDatabase() di seguito:

static class HelperMethods
 {  //IHelper h = new HeleperA();
    //h.DumpToDatabase() 
    public static void DumpToDatabase(this IHelper helper) { /* ... */ }

    //IHelper h = a.RetrieveByID(5)
    public static IHelper RetrieveByID(this ObjectA a, int id) 
     { 
          return new HelperA(a.GetByID(id));
     }

    //Ihelper h = b.RetrieveByID(5)       
    public static IHelper RetrieveByID(this ObjectB b, int id)
     { 
          return new HelperB(b.GetById(id.ToString())); 
     }
 }

Come faccio a inviare un feedback su Stack Overflow?Modificare il mio post originale o post di una "risposta"?Comunque, ho pensato che potrebbe aiutare a dare un esempio di quello che sta succedendo in AHelper.RetrieveByID() e BHelper.RetreiveByID()

In sostanza, entrambi questi metodi sono andando contro terzi webservice che restituisce diverse generico (colabile) di un oggetto utilizzando un metodo di Query che prende in una pseudo-stringa SQL come parametri.

Così, AHelper.RetrieveByID(string ID) potrebbe apparire come

public static AObject RetrieveByID(string ID)
{
  QueryResult qr = webservice.query("SELECT Id,Name FROM AObject WHERE Id = '" + ID + "'");

  return (AObject)qr.records[0];
}

public static BObject RetrieveByID(string ID)
{
  QueryResult qr = webservice.query("SELECT Id,Name,Company FROM BObject WHERE Id = '" + ID + "'");

  return (BObject)qr.records[0];
}

Spero che aiuta.Come si può vedere, i due metodi sono simili, ma la query può essere un po ' diverse in base al tipo di oggetto diverso di essere restituito.

Oh, e Rob, sono completamente d'accordo ... questo è più che probabile di una limitazione di progettazione e non la lingua.:)

Stai cercando comportamento polimorfico?Allora ti consigliamo l'interfaccia e normale costruttore.Ciò che è istintivo sulla chiamata di un costruttore?Se non avete bisogno di polimorfismo (suona come voi non la uso ora), quindi si può attaccare con i vostri metodi statici.Se questi sono wrapper attorno a un fornitore di componenti, quindi magari si potrebbe provare a utilizzare un metodo factory per creare loro come VendorBuilder.GetVendorThing("A"), che potrebbe restituire un oggetto di tipo IVendorWrapper.

marxidad Basta un rapido punto da notare, Justin ha già detto che la SQL varia molto a seconda del tipo, ho lavorato sulla base del fatto che potrebbe essere qualcosa di completamente diversi a seconda del tipo, quindi la delega per le sottoclassi in questione.Considerando che la soluzione coppie SQL MOLTO strettamente al Tipo (es.si è SQL).

rptony Buon punto sui possibili problemi di sincronizzazione con la statica, uno che non è riuscito a parlare, quindi grazie :), e la sua Rob Cooper (non di Rame) BTW ;) :D ( EDIT: Solo pensato vorrei ricordare che in caso di non era un errore di battitura, mi aspetto è, quindi nessun problema!)

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top