2009-11-22 9 views
0

J'ai ce code répété ci-dessous et je suppose que cela peut être consolidée mais si vous remarquez chaque dictionnaire est différent dictionnaire générique:Comment rendre ce code répété plus élégant?

dictionary1 est de type

Dictionary<int, ContinuousIntegrationSolution> 

alors dictionary2 est de type:

Dictionary<int, BugTracker> 

     DataTable dt = GetDataTable("CI"); 
     for (int i = 0; i < dt.Rows.Count; i++) 
     { 
      DataRow dr = dt.Rows[i]; 
      int id = Convert.ToInt32(dr["id"]); 
      string name = dr["name"].ToString(); 
      _dictionary1[id] = new ContinuousIntegrationSolution(){Name = name}; 
     } 

     DataTable dt1 = GetDataTable("Bug_Tracking"); 

     for (int i = 0; i < dt1.Rows.Count; i++) 
     { 
      DataRow dr = dt1.Rows[i]; 
      int id = Convert.ToInt32(dr["id"]); 
      string name = dr["name"].ToString(); 
      _dictionary2[id] = new BugTracker() { Name = name }; 
     } 

     DataTable dt2 = GetDataTable("SDLC"); 

     for (int i = 0; i < dt2.Rows.Count; i++) 
     { 
      DataRow dr = dt2.Rows[i]; 
      int id = Convert.ToInt32(dr["id"]); 
      string name = dr["name"].ToString(); 
      _dictionary3[id] = new SDLCProcess() { Name = name }; 
     } 

NOTE: Je fixe les quelques fautes de frappe qui ont été mentionnés ci-dessous.

+0

Y at-il un bug dans votre code? Vous avez 3 DataTables (dt, dt1 et dt2), mais seulement 2 Dictionnaires _dictionary1 et _dictionary2? –

+0

Sommes-nous autorisés à modifier la hiérarchie de classe afin que ContinuousIntegrationSolution, BugTracker et SDLCProcess aient une classe de base commune ou une interface contenant le membre Name? –

+0

De plus, dt n'est pas défini dans la portée de l'extrait. –

Répondre

13
public interface INameable 
{ 
    string Name {get;set;} 
} 

public static IDictionary<int, T> ReadTable<T>(string tableName) 
    where T : INameable, new() 
{ 
    DataTable dt = GetDataTable(tableName); 
    var dictionary = new Dictionary<int, T>(); 

    for (int i = 0; i < dt.Rows.Count; i++) 
    { 
     DataRow dr = dt.Rows[i]; 
     int id = Convert.ToInt32(dr["id"]); 
     string name = dr["name"].ToString(); 
     dictionary[id] = new T() { Name = name }; 
    } 
    return dictionary; 
} 

Si vous avez C# 4.0 dynamique, vous pouvez éviter le INameable pour certains (mineur) perte de Sûreté du typage

Un autre, semblable dans la veine à la réponse de Hakon mais sans exposer le dictionnaire est

public IDictionary<int,T> ReadTable<T>(
    string tableName, Action<T, string> onName) 
    where T : new() 
{ 
    var dictionary = new Dictionary<int,T>(); 
    DataTable table = GetDataTable(tableName); 
    foreach (DataRow row in table.Rows) 
    { 
     int id = Convert.ToInt32(row["id"]); 
     string name = row["name"].ToString(); 
     var t = new T(); 
     onName(t, name); 
     dictionary[id] = t; 
    } 
    return dictionary; 
} 

qui est ensuite consommé comme ceci:

var ci = ReadTable<ContinuousIntegrationSolution>("CI", 
       (t, name) => t.Name = name); 
var bt = ReadTable<BugTracker >("Bug_Tracking", 
       (t, name) => t.Name = name); 
var sdlc = ReadTable<SDLCProcess>("SDLC", 
       (t, name) => t.Name = name); 

Un autre, approac plus souple h, mais encore assez simple à utiliser sur le site d'appel en raison de inférence de type serait:

public IDictionary<int,T> ReadTable<T>(string tableName, Func<string,T> create) 
{ 
    DataTable table = GetDataTable(tableName); 
    var dictionary = new Dictionary<int,T>() 
    foreach (DataRow row in table.Rows) 
    { 
     int id = Convert.ToInt32(row["id"]); 
     string name = row["name"].ToString(); 
     dictionary[id] = create(name); 
    } 
    return dictionary; 
} 

qui est ensuite consommé comme ceci:

var ci = ReadTable("CI", 
       name => new ContinuousIntegrationSolution() {Name = name}); 
var bt = ReadTable("Bug_Tracking", 
       name => new BugTracker() {Name = name}); 
var sdlc = ReadTable("SDLC", 
       name => new SDLCProcess() {Name = name}); 

Si vous deviez aller avec l'approche lambda I suggérerait le dernier.

+0

Il pourrait être encore amélioré en utilisant un foreach. –

+2

Je suis d'accord, mais cela changerait la sémantique du programme tel qu'il est fourni (un changement subtil que j'admets) donc j'ai tendance à ne pas * corriger de telles choses quand c'est inutile. – ShuggyCoUk

+0

Je reçois une erreur avec ce code en disant: Erreur Les contraintes ne sont pas autorisées sur les déclarations non génériques – leora

0

Mettez-le dans une fonction avec une méthode usine pour instancier l'objet ID. Quelque chose comme ça ...

public delegate T CreateObjectDelegate<T>(string name); 
public static void ProcessDataTable<T>(DataTable dt, Dictionary<int, T> dictionary, CreateObjectDelegate<T> createObj) 
{ 
    for (int i = 0; i < dt.Rows.Count; i++) 
    { 
     DataRow dr = dt.Rows[i]; 
     int id = Convert.ToInt32(dr["id"]); 
     string name = dr["name"].ToString(); 
     dictionary[id] = createObj(name); 
    } 
} 

static void Main(string[] args) 
{ 
    var dt = new DataTable(); 
    var dictionary = new Dictionary<int, BugTracker>(); 
    ProcessDataTable<BugTracker>(dt, dictionary, (name) => { return new BugTracker() { Name = name }; }); 
} 
3

Je ne voudrais pas utiliser une interface comme il a été suggéré, mais plutôt utiliser une fonction lambda pour faire la mission semblable à ceci:

public void ReadTable(string tableName, Action<int, string> _setNameAction) { 
    DataTable table = GetDataTable(tableName); 
    foreach (DataRow row in table.Rows) { 
     int id = Convert.ToInt32(row["id"]); 
     string name = row["name"].ToString(); 
     _setNameAction(id, name); 
    } 
} 

Et appelez la méthode comme ceci:

ReadTable("CI", (id, name) 
    => _dictionary1[id] = new ContinuousIntegrationSolution{Name = name}); 
ReadTable("Bug_Tracking", (id, name) 
    => _dictionary2[id] = new BugTracker { Name = name }); 
ReadTable("SDLC", (id, name) 
    => _dictionary3[id] = new SDLCProcess { Name = name }); 
+0

ce code ne fonctionne pas. où "id" est-il renvoyé dans le délégué d'action ?? – leora

+0

Je viens de le comprendre il y a quelques secondes et l'ai mis à jour maintenant – HakonB

Questions connexes