2

我现在想检查传入的列以查看它是什么类型的枚举,并基于此,我为该列返回正确的数据库类型。我无法让它工作,不知道如何:

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

3 回答 3

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
于 2012-10-22T19:34:10.077 回答
1

由于您无法打开 type 的表达式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;

现在可能唯一缺少的是将对象转换为可以轻松添加的唯一字符串表示形式。

于 2012-10-22T20:27:36.323 回答
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");
    }
}
于 2016-05-25T10:26:43.340 回答