繁体   English   中英

检查通用方法中使用了哪种枚举

[英]Check what Type of Enum came into the Generic Method

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

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

您的转换声明对我来说似乎有些可笑。 尝试以下方法:

        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

由于您无法打开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;

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

在这种情况下,我最终使用了'if'而不是'switch'(很好的双关语*自己拍拍*)。 开关/大小写控件本质上是一种处理可能的相等大小写列表的好方法,并且为了减少重复的代码而引入。 但是,如果您不比较兼容类型,则可以简单地回到旧方法:

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM