2009-11-22 2 views
0

나는 아래이 반복되는 코드는 내가이 통합 될 수 있음을 가정하고 있지만 각 사전이 다른 일반적인 사전 예고 경우 :이 반복 코드를 좀 더 우아하게 만들려면 어떻게해야합니까?

dictionary1 유형이다 dictionary2 반면

Dictionary<int, ContinuousIntegrationSolution> 

유형이다 :

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

참고 : 나는 아래에 언급 된 몇 가지 오타를 해결했습니다.

+0

코드에 버그가 있습니까? 3 개의 DataTable (dt, dt1 및 dt2)이 있지만 두 개의 사전 _dictionary1 및 _dictionary2 만 있습니까? –

+0

ContinuousIntegrationSolution, BugTracker 및 SDLCProcess가 이름 멤버를 포함하는 공통 기본 클래스 또는 인터페이스를 갖도록 클래스 계층 구조를 변경할 수 있습니까? –

+0

또한 dt는 스 니펫의 범위 내에서 정의되지 않습니다. –

답변

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

동적 # 4.0 c를 가질 경우 대해서 typesafety의 일부 (작은) 손실을 HAKON의 대답하지만 사전을 노출하지 않고 정맥에서 비슷한

대안을의 INameable을 피할 수는

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; 
} 
입니다

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

또 다른, 더 유연 approac을 : 다음과 같이 소비

시간,하지만 입력으로 인해 호출 사이트에서 사용하는 것이 여전히 합리적으로 간단한 추론은 다음과 같습니다

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

다음과 같이 소비하는 :

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

당신은 람다 접근 방식으로 갈 것 인 경우에 I 후자를 제안 할 것이다.

+0

foreach를 사용하면 더 개선 될 수 있습니다. –

+2

동의 하겠지만, 프로그램의 의미가 바뀌었기 때문에 (필자가 인정하는 미묘한 변화) 필자는 그러한 것들이 불필요 할 때 수정하지 않는 경향이있다. – ShuggyCoUk

+0

이 코드에서 오류가 발생합니다. 오류 제네릭 선언에 제약 조건이 허용되지 않습니다. – leora

0

id 객체를 인스턴스화하는 팩토리 메소드가있는 함수에 넣으십시오. 차라리 람다 함수를 사용하는 것이 제안되었다 같은 인터페이스를 사용하지만하지 않을

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

이런 식으로 뭔가 ...이 유사한 할당해야 할 일 :

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

과 같은 메소드를 호출 이 :

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

이 코드는 작동하지 않습니다. 여기서 "id"는 Action 대리자로 다시 전달됩니까 ?? – leora

+0

방금 ​​초를 알아 냈으므로 지금 업데이트했습니다. – HakonB

관련 문제