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;
            }
    }
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、次のようにメソッドを構成できます。

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

このタイプのケースでは、'switch' の代わりに 'if' を使用することになりました (いい駄洒落 * 自分の背中をなでる *)。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 に答える