2014-12-04 7 views
6

Ich habe viele Methoden, die in großen Teilen den gleichen Algorithmus folgen, und ich möchte idealerweise in der Lage sein, Aufrufe an eine generische Methode, die eine Menge Code-Duplikation beseitigt.Probleme mit viel Code-Duplizierung

Ich habe Tonnen von Methoden wie die unten, würde ich optimal nur in der Lage sein möge, rufen Save<SQLiteLocation>(itemToSave);, aber ich habe sehr viel Mühe, da, dass die Methoden SQLiteConnection.Find<T> wird einen abstrakten Datentyp wie T nicht akzeptieren in Generika.

Gibt es eine Möglichkeit, dies zu umgehen, wenn ich es ich so viele wie 150 Zeilen Code

meinen Code Hier würde repariert könnte sparen:

public bool SaveLocation(ILocation location, ref int primaryKey) 
    { 
     var dbConn = new SQLiteConnection (dbPath); 

     SQLiteLocation itemToSave = new SQLiteLocation(); 
     itemToSave.LocationName = location.LocationName; 
     itemToSave.Latitude = location.Latitude; 
     itemToSave.Longitude = location.Longitude; 
     itemToSave.PrimaryKey = location.PrimaryKey; 

    ---------------------------------------------------------------------------------------- 

     SQLiteLocation storedLocation = dbConn.Find<SQLiteLocation> 
             (x => x.PrimaryKey == location.PrimaryKey); 

     if (storedLocation != null) 
     { 
      dbConn.Update(itemToSave); 
      return true; 
     } 

     else if (storedLocation == null) 
     { 
      dbConn.Insert(itemToSave); 
      primaryKey = itemToSave.PrimaryKey; 
      return true; 
     } 
     return false; 
    } 

Und hier eine andere Methode sehen, wie der Code in beiden Verfahren unter meiner gestrichelte Linie ist im Grunde das gleiche

public bool SaveInvitation(IInvitation invitation, ref int primaryKey) 
    { 
     var dbConn = new SQLiteConnection(dbPath); 

     SQLiteInvitation itemToSave = new SQLiteInvitation(); 
     itemToSave.GroupName = invitation.GroupName; 
     itemToSave.InviterName = invitation.InviterName; 
     itemToSave.ParseID = invitation.ParseID; 
     itemToSave.GroupParseID = invitation.GroupParseID; 
     itemToSave.PrimaryKey = invitation.PrimaryKey; 

--------------------------------------------------------------------------------------- 

     SQLiteInvitation storedInvitation = dbConn.Find<SQLiteInvitation> 
              (x => x.PrimaryKey == invitation.PrimaryKey); 

     if (storedInvitation != null) 
     { 
      dbConn.Update(itemToSave); 
      return true; 
     } 
     else if (storedInvitation == null) 
     { 
      dbConn.Insert(itemToSave); 
      primaryKey = itemToSave.PrimaryKey; 
      return true; 
     } 
     return false; 
    } 
+0

annehmen können Sie AutoMapper oder etwas verwenden, wie es um die Eigenschaften zu bewegen. Wenn Sie 'itemToSave' aus der Methode entfernen und als Parameter übergeben, können Sie den Rest des Codes möglicherweise generisch machen. –

+0

Haben Sie darüber nachgedacht, in Ausdrucksbäume zu suchen, um die 'Find ' Anweisung zu erstellen? –

+0

'storedX' ist entweder 'null' oder nicht, also muss 'else if' nicht verwendet werden. Aus diesem Grund werden Sie niemals false zurückgeben, so dass Sie den Rückgabewert entfernen können. Left is 'if (storedX! = Null) {dbConn.Update (itemToSave); } else {dbConn.Insert (ElementToSave); primaryKey = itemToSave.PrimaryKey; } '. 3 Zeilen entfernt genau dort – Default

Antwort

0

Aus irgendeinem Grund warf eine nicht unterstützte Ausnahme wenn ich verwendet:

T storedItem = dbConn.Find<T>(x => x.PrimaryKey == item.PrimaryKey); 

Der Code unten, obwohl mein Leiden festgelegt, danke für die Hilfe jeder, ich liebe diesen Ort! Auch hinzugefügt ich eine andere Einschränkung auf T da T eine nicht abstrakte Art sein und eine Schnittstelle ist nur, dass ich

private void SaveItem<T>(T item, ref int primaryKey) 
     where T : ISQLiteClass, new() 
    { 
     var dbConn = new SQLiteConnection(dbPath); 

     T storedItem = dbConn.Find<T>(primaryKey); 

     if (storedItem != null) 
     { 
      dbConn.Update(item); 
     } 
     else if (storedItem == null) 
     { 
      dbConn.Insert(item); 
      primaryKey = item.PrimaryKey; 
     } 
    } 
1

Sollten Sie so etwas zu tun, nicht in der Lage: Hinweis: ICoMM onInterface ist alles, was zwischen allen zulässigen Klassen, die Sie als T verwenden möchten, üblich ist. Vorzugsweise betrachten Sie Ihren Code, eine Schnittstelle oder Klasse, die die PrimaryKey-Eigenschaft verfügbar macht.

public bool SaveItem<T>(T item, ref int primaryKey) where T : ICommonInterface, new() 
{ 
    var dbConn = new SQLiteConnection(dbPath); 


    T storedItem = dbConn.Find<T>(x => x.PrimaryKey == item.PrimaryKey); 

    if (storedItem != null) 
    { 
     dbConn.Update(item); 
     return true; 
    } 
    else if (storedItem == null) 
    { 
     dbConn.Insert(item); 
     primaryKey = item.PrimaryKey; 
     return true; 
    } 
    return false; 
} 

EDIT: Die neue() Einschränkung der Methode hinzugefügt.

+0

Sie haben das korrigiert meinen Code und Sie gespeichert meine viele viele Zeilen Code – Guano

+0

Eigentlich scheint es, ich war zu voreilig, bekomme ich diesen Fehler: \t \t \t 'T 'muss ein nicht-abstrakter Typ mit einem öffentlichen parameterlosen Konstruktor sein, um ihn als Parameter' T 'im generischen Typ oder der generischen Methode' SQLite.SQLiteConnection.Find (System.Linq.Expressions.Expression ) '(CS0310) (ShoppingAssistant) – Guano

+0

Siehe die modifizierte Antwort. Fügen Sie der Methode eine neue() Einschränkung hinzu. Beispiel: wo T: ICommonInterface, new() – gmiley