2012-10-22 52 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,字符串,整數,枚舉或相應的可空類型」。 –

回答

3

你的switch語句對我來說似乎有點有趣。試試這個:

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

     .... 

正如其他人所建議的,什麼是有,如果你是基於它的類型轉換會泛型方法的意義呢?只是這樣做,而不是:

public DbType GetColumnDbType(Enums.MemberColumn column) 
{ 
    switch(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 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

你不能開啓'類型'的表達式' –

+0

謝謝我'對於泛型還沒那麼好......這就是爲什麼它很時髦:) – PositiveGuy

+0

「正如其他人所說的,如果你要根據類型進行切換,使用通用方法有什麼意義?」因爲這是一個實用程序方法,我在表格列中發送返回關聯的DbType。這個方法就像一個catch all,會根據原來發送的Enum的類型找到正確的case語句。 – 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

在這種情況下,我最終使用'if'而不是'switch'(很好的懲罰我* * * *)。 switch/case控件本質上是處理可能的相等案例列表的一種很好的方式,並且爲了減少重複代碼而引入。但是,如果您沒有比較兼容類型,那麼它只是回到舊方法:

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