2014-03-19 4 views
3

아래에는 모의 데이터베이스 호출 및 해당 목록을 가져 와서 DataTable로 변환하는 작은 프로그램 목록이 있습니다. 이 예제에서는 열 이름에 대한 변수를 사용하여 해당 열 값에 액세스하고 평균값을 구합니다. 그러나 Field 메서드를 호출하여 int 유형을 지정했습니다. 일반 Field 메서드에 변수를 전달할 수있는 것으로 보이지 않습니다. DataTable의 열 값에 액세스하고 런타임까지 열의 유형을 모른 채 평균과 같은 값을 반환하는 또 다른 방법이 있습니까? 업데이트LINQ 필드 메서드에 매개 변수로 형식을 전달

public class Icd 
{ 
    public int ConditionCode { get; set; } 
    public string ConditionName { get; set; } 

    public static List<Icd> GetIcdList() 
    { 
     return new List<Icd>() 
     { 
      new Icd() { ConditionCode = 111, ConditionName = "Condition 1" }, 
      new Icd() { ConditionCode = 222, ConditionName = "Condition 2" }, 
     }; 
    } 
} 
var icdList = Icd.GetIcdList(); 
var columnName = "ConditionCode"; 
DataTable dt = new DataTable(); 

dt = icdList.ToList().ListToDataTable(); 
var avg = dt.AsEnumerable().Where(x => x[columnName] != DBNull.Value) 
          //possible to pass a variable to the field method? 
          .Average(x => x.Field<int>(columnName)); 
Console.WriteLine(avg); //<-- correct answer 

: 나는 추가하려고 :

Type t = typeof(int) 

x => x.Field<t>(columnName) 

을하지만 그건 나에게 오류 제공 :

The type or namespace 't' could not be found

ListToDataTable helpe을 r 메소드 :

public static DataTable ListToDataTable<T>(this IList<T> data) 
{ 
    DataTable dt = new DataTable(); 
    PropertyDescriptorCollection props = TypeDescriptor.GetProperties(typeof(T)); 
    for (int i = 0; i < props.Count; i++) 
    { 
     PropertyDescriptor prop = props[i]; 
     dt.Columns.Add(prop.Name, prop.PropertyType); 
    } 
    object[] values = new object[props.Count]; 
    foreach (T t in data) 
    { 
     for (int i = 0; i < values.Length; i++) 
     { 
      values[i] = props[i].GetValue(t); 
     } 
     dt.Rows.Add(values); 
    } 
    return dt; 
} 
+0

오류가 발생합니까? 그것을 우리와 공유하십시오. –

+0

@LucMorin – wootscootinboogie

+0

[This] (http://msdn.microsoft.com/en-us/library/bb396189%28v=vs.110%29.aspx) 편집 내용을 참조하십시오. – abatishchev

답변

1

일반 유형은 컴파일시 알려야합니다. 난 당신이 여기에 dynamic 유형을 사용할 수 있습니다 생각

// Get the method information 
MethodInfo method = typeof(T).GetMethod("Field"); 

// here hardcoded for int, but you could use any type 
var types = new Type[] {typeof(int)}; 

// Create a generic instance of that method 
MethodInfo genericMethod = method.MakeGenericMethod(types); 

var avg = dt.AsEnumerable().Where(x => x[columnName] != DBNull.Value) 
         // Use the generic method with target x and parameter columnName 
         .Average(x => genericMethod.Invoke(x, columnName); 
+0

얼마나 많은 반사가 실제로 느려질 지 확신 할 수 없습니다 것들을 아래로,하지만 내가 할거라고 생각하는 것은 동적으로 열 유형을 캐스팅하고 모든 값이 int, double, float 등일 경우 실행될 'TryGetAverage'를 사용합니다. – wootscootinboogie

2

: 당신이 그 변수를 확인하려면 당신은 반사를 사용해야합니다. 예를 들어

:

var avg = dt.AsEnumerable().Where(x => x[columnName] != DBNull.Value) 
          //possible to pass a variable to the field method? 
          .Average(x => x.Field<dynamic>(columnName)); 

나는 최소한의 테스트를 완료했으며, 작동하는 것 같다. 다른 사람들은 이에 대해 의견을 환영합니다.

환호

+0

같은 생각 :) try 메소드가 float, double, int 등의 타입 인 경우 GetAverage를 호출하는 TryGetAverage 메소드를 작성하려고합니다. – wootscootinboogie

관련 문제