まず、この質問が重複しない理由ここにある:マッピング異なる列挙型を一緒
私は別のenum
の変換に関する複数の質問がSOに求められていることを知って、私もone of them自分自身に答えが、すべての質問私は、このトピックでは、名前または値によって異なるenum値を比較するいくつかの方法があることがわかりました。私の特定のケースでは、私は値を知らないし、名前が一致しません。
私は、Ado.Netで作業するときにコードの繰り返しを最小限に抑えるように設計されたADONETHelperというGitHubプロジェクトの一部として、無関係の列挙型の間で値を変換する必要性に直面しました。これは、同じコードをOleDb、Odbc、およびSqlClient(そして今後OracleClientとMySqlClientにもうまくいけばうまくいけばうまくいく)と一緒に使えるようにするためです。
私がしようとしているのは、さまざまな列挙型、特にSQLパラメータデータ型を記述する列挙型の統合を作成することです。 Currntly、私は4つの列挙型サポートしています -
System.Data.DbType
、
System.Data.SqlClient.SqlDbType
、
System.Data.OleDb.OleDbType
、
System.Data.Odbc.OdbcType
を私はOracleClientのかはmysqlclientのサポートを追加したい場合は、私が追加することはかなり難しい作業する必要がありますSystem.Data.OracleClient.OracleType
またはMySql.Data.MySqlClient.MySqlDbType
。 私はこれをやるよりエレガントな方法を探しています。
だから、最初、私は私自身の列挙型は、ADONETType
と呼ばれる定義されています。ここ
は私の現在のコード(それは素晴らしい作品が、私は書いたように、それは新しい列挙型のサポートを追加するのは難しい)です。 Boolean
、Byte
、Binary
、Char
などのエントリがあります。 次に、この列挙型に拡張メソッドを提供するために、DBTypeConverter
という静的クラスを作成しました。その値は他の列挙型に変換できます。 これは、このクラスは次のようになります。あなたが見ることができるように、OracleClientの、たとえば、のためのサポートを提供するために、私は次のことを行う必要があるでしょう、今
internal static class DBTypeConverter
{
#region private members
private static List<DbTypeMap> _Map;
#endregion private members
#region static constructor
static DBTypeConverter()
{
_Map = new List<DbTypeMap>()
{
new DbTypeMap(ADONETType.Boolean, DbType.Boolean, SqlDbType.Bit, OleDbType.Boolean, OdbcType.Bit),
new DbTypeMap(ADONETType.Byte, DbType.Byte, SqlDbType.TinyInt, OleDbType.UnsignedTinyInt , OdbcType.TinyInt),
new DbTypeMap(ADONETType.Binary, DbType.Binary, SqlDbType.Binary, OleDbType.Binary, OdbcType.Binary),
// ... more of the same here ...
new DbTypeMap(ADONETType.Xml, DbType.Xml, SqlDbType.Xml, null, null)
};
}
#endregion static constructor
#region methods
internal static DbType ToDbType(this ADONETType type)
{
return type.ConvertTo<DbType>();
}
internal static SqlDbType ToSqlType(this ADONETType type)
{
return type.ConvertTo<SqlDbType>();
}
internal static OleDbType ToOleDbType(this ADONETType type)
{
return type.ConvertTo<OleDbType>();
}
internal static OdbcType ToOdbcType(this ADONETType type)
{
return type.ConvertTo<OdbcType>();
}
private static dynamic ConvertTo<T>(this ADONETType type)
{
var returnValue = _Map.First(m => m.ADONETType == type).GetValueByType(typeof(T));
if(returnValue != null)
{
return returnValue;
}
throw new NotSupportedException(string.Format("ADONETType {0} is not supported for {1}", type, typeof(T)));
}
#endregion methods
#region private struct
private struct DbTypeMap
{
#region ctor
public DbTypeMap(ADONETType adonetType, DbType? dbType, SqlDbType? sqlDbType, OleDbType? oleDbType, OdbcType? odbcType)
: this()
{
ADONETType = adonetType;
DbType = dbType;
SqlDbType = sqlDbType;
OleDbType = oleDbType;
OdbcType = odbcType;
}
#endregion ctor
#region properties
internal ADONETType ADONETType { get; private set; }
internal DbType? DbType { get; private set; }
internal SqlDbType? SqlDbType { get; private set; }
internal OleDbType? OleDbType { get; private set; }
internal OdbcType? OdbcType { get; private set; }
#endregion properties
#region methods
internal dynamic GetValueByType(Type type)
{
if (type == typeof(ADONETType))
{
return this.ADONETType;
}
if(type == typeof(DbType))
{
return this.DbType;
}
if (type == typeof(SqlDbType))
{
return this.SqlDbType;
}
if (type == typeof(OleDbType))
{
return this.OleDbType;
}
if (type == typeof(OdbcType))
{
return this.OdbcType;
}
return null;
}
#endregion methods
}
#endregion private struct
}
:
- 追加
DbTypeMap
private構造体内のOracleType
のプロパティです。 DbTypeMap
コンストラクタを変更して、oracle型も受け入れるようにします。- 別のケースを
GetValueByType
メソッドのスイッチに追加します。 - 静的コンストラクタにoracle型を
DBTypeConverter
に追加します。 - 方法(
internal static OracleType ToOracleType(this ADONETType type)
)をDBTypeConverter
に追加します。
これは多くの作業であり、これらの列挙型を統合する別の方法を見つけるよりも、新しいクライアントにサポートを追加する方が簡単です。
これはあなたの熟練者が遊びに来たときです。
しかし、 'DbType'の*のポイント*は異なるシステムで抽象化することです。あなたはクライアントがジェネリッククラス*にコードするのではなく、このマッピングをすべて行う必要があります。 –
列挙型が同じシーケンスにある場合や、リフレクションや設定ファイルなどのアプローチを使用している場合など、唯一の方法は、指定された型の各列挙型を取得し、保持している値もう一度値が同じであれば、ある列挙型から他の列挙型へのキャストも同様です。 – Vnvizitiu
--PS:異なるデータベース用に拡張できる仮想メンバを使用してADONETTypeをカスタムクラスにする方法はありますか? – Vnvizitiu