1

私のC# 4.0コードから、 と でいくつかのクエリを実行したいと思いSybaseますMSSQL。使用されている (または使用される予定の) データベースは、実行時にのみ決定/認識されます。

私は、Sybase と SQL にそれぞれ と をAseCommand使用しています。SqlCommand

次のようなジェネリック メソッドを作成することにしました。

private Department ExecuteCommand<T>(T databaseCommand) where T : class
{
            Department department = new Department ();

            dynamic command = databaseCommand;

            using (dynamic databaseReader = command.ExecuteReader())
            {
                if (databaseReader.HasRows)
                {

                    while (databaseReader.Read())
                    {
                         department.Employees.Add(this.CreateDepartmentInstance(databaseReader));
                    }
                }
            }

            command.Connection.Dispose();

            return department;
        }

質問:

  1. 以外のより良いオプションはありますdynamicか?
  2. 通常、ジェネリック メソッドに渡される引数の型を知る正しい方法は何ですか?
  3. もちろん、Sybase と SQL の 2 つの別々のメソッドを作成できます。dynamicしかし、そのようなものが自由に使えるのに、なぜそうする必要があるのでしょうか?
4

4 に答える 4

11

ここでは必ずしも動的である必要はありません。必要なのは共通のインターフェースだけです (この例では両方が持っています)。

private Department ExecuteCommand<T>(T databaseCommand) where T : IDbCommand

ただし、この例では、型に関して特に興味深いことは何もしていないためT(私が見る限り)、次のメソッド シグネチャで十分です。

private Department ExecuteCommand(IDbCommand databaseCommand)

一般に、共通のインターフェイスがない場合は、ファサード パターンを使用し、メソッド呼び出しを実際の実装の同等のものに委譲することをお勧めします。

于 2013-03-14T12:07:03.763 に答える
2

のように見えAseCommandSqlCommand両方とも実装されIDbCommandているため、型制約を変更する必要があります。

private Department ExecuteCommand<T>(T databaseCommand) where T : IDbCommand
{
    Department department = new Department();

    using (IDataReader databaseReader = databaseCommand.ExecuteReader())
    {
        if (databaseReader.HasRows)
        {

            while (databaseReader.Read())
            {
                department.Employees.Add(
                                 this.CreateDepartmentInstance(databaseReader));
            }
        }
    }

    command.Connection.Dispose();

    return department;
}

まだ受け入れていない場合はCreateDepartmentInstance、受け入れるように変更する必要があると想像してください。IDataReader

rich.okellyが指摘しているように、そもそもここでジェネリックを使用する理由は実際にはないようです。

于 2013-03-14T12:09:34.083 に答える
0

#2 への回答:

if (typeof(T) == typeof(object) ) {
    // Check for IEnumerable
}

オブジェクトをチェックしたいタイプに置き換えます。

于 2013-03-14T12:08:55.963 に答える
0

あなたの場合、共通のインターフェースを使用しても問題ありません。

一般に、オブジェクトのタイプを知りたい場合は、いつでもisand as-Operators を使用できます。

private Department ExecuteCommand<T>(T databaseCommand) where T : class
{
            Department department = new Department ();

            var command = databaseCommand;

            using (var databaseReader = command.ExecuteReader())
            {
                if ((databaseReader as IDataReader).HasRows)
                {

                    while ((databaseReader as IDataReader).Read())
                    {
                          department.Employees.Add(this.CreateDepartmentInstance(databaseReader));
                    }
                }
            }

            command.Connection.Dispose();

            return department;
        }

VS では検証されていませんが、動作するはずです。

于 2013-03-14T12:38:20.477 に答える