2009-12-06 3 views
2

다음보다 나은 방법이 있습니까?DataTable to List <T> 변환

특히 Activator을 다른 것으로 바꿔야합니다. 왜 Activator를 방지하고 싶어 -

public static List<T> ToList<T>(DataTable dt) 
     { 
      Type type = typeof(T); 

      List<T> list = new List<T>(); 

      foreach (DataRow dr in dt.Rows) 
      { 
       object[] args = new object[1]; 

       args[0] = dr; 

       list.Add((T)Activator.CreateInstance(type, args)); 
      } 

      return list; 
     } 
+0

내게 잘 어울리는 군 .. 어떻게 든 당신의 T를 인스턴스화해야 할 것입니다 ... –

답변

6

내가 언급 할 첫번째 일은 당신이 아마 필요가 없다는 것입니다 :

public static List<T> ToList<T>(DataTable dt) 
    where T : IFoo, new() 

는이처럼 메소드의 구현을 변경 목록. 확률은 IEnumerable이면 충분합니다. 목록이 필요하더라도 IEnumerable을 목록으로 변환하는 것은 간단합니다.

public static IEnumerable<T> ToEnumerable<T>(DataTable dt, Func<DataRow, T> translator) 
{ 
    foreach(DataRow dr in dt.Rows) 
    { 
     yield return translator(dr); 
    } 
} 

는 희망이 얼마나 재사용 볼 수 있습니다 염두에두고

,이 코드를 달성 할 수있는 좋은 일반적인 방법입니다. 개별 DataRow를 T 유형으로 변환하는 방법을 알고있는 함수를 제공하면됩니다. 이 함수는 일 수도 있고 일 수도 있지만 Activator를 사용할 필요는 없습니다. 그냥 일반 생성자를 사용하고 몇 가지 속성을 설정할 수 있습니다.

+1

+1, yield를 사용하면 번역자에게 'IEnumerable '항목이 필요한 것처럼 호출 할 것입니다; 일부 논리를 사용하여 목록 처리를 중단하면 일부 프로세서 사이클이 절약됩니다. –

+0

그러나이 방법의 문제점은 .net 2.0과 역 호환되지 않는다는 것입니다. – anonymous

+1

.NET 2.0에서는 할 수 있습니다. 변환을 수행하려면 Func 대신 익명의 대리자를 사용해야합니다. 또는 델리게이트없이 직접 작성하여 결과 클래스 유형에 직접 매핑하고 new() –

2

난 정말이 코드를 개선 할 수있는 방법을 표시되지 않는 이유는 무엇입니까?

interface IFoo 
{ 
    void Initialize(DataRow dr); 
} 

그리고이 메소드에 전달되는 모든 종류의에이 인터페이스를 구현 : 당신이 탐구 할 수

하나의 옵션은 다음과 같이 인터페이스의 일종을 생성하는 것입니다. 그럼 당신은이처럼 제네릭 형식 매개 변수를 제한하는 것입니다 :

public static List<T> ToList<T>(DataTable dt) 
    where T : IFoo, new() 
{ 
    List<T> list = new List<T>(); 

    foreach (DataRow dr in dt.Rows) 
    { 
     T t = new T(); 
     t.Initialize(dr); 
     list.Add(t); 
    } 
    return list; 
} 
0

앤드류의 대답에 추가 할 점은 new() 제약 조건으로 제네릭 메서드를 제한함으로써 Activator 클래스를 피할 수있는 경로를 선택했다는 것입니다.

public static List<T> ToList<T>(DataTable dt) 
    where T : IFoo, new() 
{ 
    ... 
    foreach (...) { 
     var foo = new T(); 
     foo.Initialize(dataRow); 
     list.Add(foo); 
    } 
    ... 
} 

C#을 실제로 단지 어쨌든 컴파일시에 Activator.CreateInstance로 호출에 있음을 컴파일하기 때문에 내가 말하는 이유는 "그렇다고"입니다. 하지만 훨씬 더 깨끗해 보입니다.

+0

Doh를 사용하여 Andrew가 방금 자신의 대답에 추가 한 것처럼 보입니다. – Josh