2012-10-22 3 views
2

들어오는 열을 확인하여 그 열거 형의 유형을 확인하고이를 기반으로 열에 올바른 DB 유형을 반환합니다. 나는이 방법을 잘하지, 동작하지 않습니다 :어떤 유형의 열거 형이 일반 메서드로 들어 왔는지 확인

public DbType GetColumnDbType<T>(T column) where T: IComparable, IFormattable, IConvertible 
     { 
      if (!typeof(T).IsEnum) throw new ArgumentException("the object passed in must an enum type"); 


      switch (column) 
      { 
       case (Enums.MemberColumn)column: 
        switch (Enums.MemberColumn) 
        { 
         case Enums.MemberColumn.Address1: 
          return DbType.String; 
          break; 
         case Enums.MemberColumn.City: 
          return DbType.String; 
          break; 
         case Enums.MemberColumn.State: 
          return DbType.String; 
          break; 
        } 
      } 
    ..... 

여기

업데이트하는 것은 내가 노력 무엇하지만 컴파일러는

"일체형의 가치도 예상"라는 첫 번째 줄에 불평
switch(typeof(T)) 
    { 
     case (typeof (Enums.MemberColumn)): 
      switch ((Enums.MemberColumn) column) 
      { 
       case Enums.MemberColumn.Address1: 
        return DbType.String; 
        break; 
       case Enums.MemberColumn.City: 
        return DbType.String; 
        break; 
       case Enums.MemberColumn.State: 
        return DbType.String; 
        break; 
       default: 
        throw new ArgumentException("Unsupported enum type.", "MemberColumn"); 
        break; 
      } 
    } 
+2

유형에 따라 전환하는 경우 유형별 오버로드를 실제로 고려해야합니다. – cadrell0

+0

정확히 작동하지 않는 것은 무엇입니까? –

+1

아래에서 지적했듯이 'Type'유형의 표현식을 켤 수 없습니다. 컴파일러에서 : "스위치 식 또는 대소 문자 레이블은 bool, char, string, integral, enum 또는 해당 nullable 유형이어야합니다." –

답변

3

스위치 설명문이 나에게 다소 재미있을 것 같습니다. 대신 다음을 시도하십시오 :

 if (typeof(T) == typeof(Enums.MemberColumn)) 
     { 
      switch ((Enums.MemberColumn)column) 
      { 
       case Enums.MemberColumn.Address1: 

     .... 

다른 사람들이 제안했듯이 유형에 따라 전환 할 경우 일반적인 방법이 필요합니다. 그냥이 대신 수행

public DbType GetColumnDbType(Enums.OtherMemberColumn column) 
{ 
    switch(column) 
    { 
      ..... 
    } 

} 

또는 ... 내가 이것을하는 방법 :

[AttributeUsage(AttributeTargets.Field, AllowMultiple = false)] 
public class DbTypeAttribute : Attribute 
{ 
    public DbType DbType { get; private set; } 

    public DbTypeAttribute(DbType dbType) 
    { 
     this.DbType = dbType; 
    } 
} 

public static class DbHelper<T> where T : IComparable, IFormattable, IConvertible, struct 
{ 
    private static Dictionary<long, DbType> _dbTypeLookup = CreateLookup(); 

    public static DbType GetColumnType(T column) 
    { 
     return _dbTypeLookup[(long)(object)column]; 
    } 

    private static Dictionary<long, DbType> CreateLookup() 
    { 
     if (!typeof(T).IsEnum) 
      throw new InvalidOperationException("T must be an enum type."); 

     var dbTypeLookup = new Dictionary<long, DbType>(); 

     foreach (var name in Enum.GetNames(typeof(T))) 
     { 
      var enumMember = typeof(T).GetMember(name).Single(); 
      var dbTypeAttr = (DbTypeAttribute)enumMember.GetCustomAttributes(typeof(DbTypeAttribute), false).Single(); 

      dbTypeLookup.Add((long)Enum.Parse(typeof(T), name), dbTypeAttr.DbType); 
     } 

     return dbTypeLookup; 
    } 
} 

다음
public DbType GetColumnDbType(Enums.MemberColumn column) 
{ 
    switch(column) 
    { 
     case (Enums.MemberColumn.Address1): 

     .... 

} 

과는 또 다른 과부하 다른 열거 유형에 대한 방법을 만들 수 위의 코드를 사용하면 다음을 수행 할 수 있습니다.

public enum MemberColumn 
{ 
    [DbType(DbType.String)] Address1, 
    [DbType(DbType.String)] Address2, 
    [DbType(DbType.String)] FirstName, 
    [DbType(DbType.String)] LastName, 
    [DbType(DbType.DateTime)] DateOfBirth, 
} 


// ... later, in some method somewhere: 

MemberColumn c = MemberColumn.Address1; 

DbType dbType = DbHelper<MemberColumn>.GetColumnType(c); // sets dbType to DbType.String 
+2

'Type'유형의 표현식을 전환 할 수 없습니다. –

+0

감사합니다. 제네릭으로는별로 좋지는 않지만 ... 그래서 펑키 한 이유가 무엇입니까 :) – PositiveGuy

+0

"다른 사람들이 제안했듯이 이것이 유형이기 때문에 전환 할 경우 일반적인 방법이 필요한 이유는 무엇입니까?"왜냐하면 이것이 유틸리티이기 때문입니다 메서드를 사용하여 관련 DbType을 다시 가져 오려면 Table 열을 보냅니다. 이 메소드는 모두 캐치와 같을 것이고 원래 보낸 Enum 유형을 기반으로 올바른 케이스 문을 찾을 수 있습니다. – PositiveGuy

1

당신이 유형 Type의 표현에 전환 할 수 있기 때문에,이 같은 방법을 구성 할 수 있습니다

public DbType GetColumnDbType<T>(T column) where T: IComparable, IFormattable, IConvertible, struct // Note you can add struct constraint here as well. 
{ 
    if (!typeof(T).IsEnum) throw new ArgumentException("the object passed in must an enum type"); 

    var type = typeof(T); 
    if (t == typeof(Enums.MemberColumn)) 
    { 
     switch((Enums.MemberColumn)column) 
     { 
       // case statements 
     } 
    } 
    else if (t == typeof(Enums.OtherColumn)) 
    { 
    } 
    else 
    { 
     throw new NotSupportedException(); 
    }  

} 

는 그러나, 나는 각 enum 유형에 대한 과부하가 읽기 쉽고 유지 관리가 될 것이라고 생각합니다. 각각의 enum 값과 연관시켜야하는 다른 메타 데이터가 있다면 더 나은 디자인은 객체를 사용한다고 생각합니다. 당신은 개체를 만드는 싱글로 의미처럼 열거 형 줄 수 :

public class MemberColumn 
{ 
    private MemberColumn(DbType columnType) { ColumnType = columnType; } 

    public DbType ColumnType { get; private set; } 

    private readonly static MemberColumn _address1 = new MemberColumn(DbType.String); 
    public static Address1 { get { return _address1; } } 

    private readonly static MemberColumn _city = new MemberColumn(DbType.String); 
    public static City { get { return _city; } } 

    private readonly static MemberColumn _state = new MemberColumn(DbType.String); 
    public static State { get { return _state; } } 

} 

샘플 사용 :

DbType addressColumnType = MemberColumn.Address1.ColumnType; 

아마 지금 부족한 유일한 것은 쉽게 추가 할 수있는 고유 한 문자열 표현으로 개체를 변환됩니다.

0

'switch'대신 'if'를 사용하는 경우가 있습니다. 스위치/케이스 컨트롤은 본질적으로 가능한 동등성 사례 목록을 처리하는 좋은 방법이며 반복 코드를 줄이기 위해 도입되었습니다. 그러나 호환 가능한 유형을 비교하지 않으면 이전 방법으로 돌아갑니다.

var memberColumnEnum = column as Enums.MemberColumn 
if(memberColumnEnum != null) 
{ 
    switch (memberColumnEnum) 
    { 
     case Enums.MemberColumn.Address1: 
      return DbType.String; 
     case Enums.MemberColumn.City: 
      return DbType.String; 
     case Enums.MemberColumn.State: 
      return DbType.String; 
     default: 
      throw new ArgumentException("Unsupported enum type.", "MemberColumn"); 
    } 
} 
관련 문제