2

私のアプリケーションでは、Dapper を使用してデータベースにアクセスします。

私は次のサンプルコードを持っています:

public IEnumerable GetByParentId(Type childType, string table) 
{
    IDbConnection _connection = _dbProvider.GetConnection();

    var _sqlString = "select * from " + table;

    IEnumerable _ret = _connection.Query(_sqlString).ToList(); 
    //return IEnumerable<Dapper.SqlMapper.FastExpando> 

    return _ret;
}

FastExpandoアイテムを myにキャストしchildTypeたり、Dapper に強く型付けされたコレクションを返すよう強制したりすることは可能ですか?

メソッドのシグネチャを変更できません!

4

1 に答える 1

3

リフレクションを介して Query メソッドを呼び出し、childType のジェネリック TItem 引数を指定できます。すると、Dapper は IEnumerable を返し、それをキャストできるようになります。また、Dapper をフォークして (それほど大きくはありません)、Query の非常に単純なオーバーロードを作成することもできます。これには (Type childType) 引数が含まれ、内部で適切なメソッドが呼び出されます。

あなたが直面しているのは、ジェネリックを扱う際の C# の問題です。静的に型付けされた言語であるため、C# は動的型の操作には適していません。動的に作業したい場合は、常に反射になります。

型引数を使用してクエリ メソッドを呼び出す方法のサンプルを次に示します。これを少し修正する必要があるかもしれません:

    public IEnumerable GetByParentId(Type childType, string table)
    {
        IDbConnection _connection = _dbProvider.GetConnection();

        var _sqlString = "select * from " + table;

        var t = typeof(SqlMapper);
        var genericQuery = t.GetMethods().Where(x => x.Name == "Query" && x.GetGenericArguments().Length == 1).First(); // You can cache this object.
        var concreteQuery = genericQuery.MakeGenericMethod(childType); // you can also keep a dictionary of these, for speed.
        var _ret = (IEnumerable)concreteQuery.Invoke(null, new object[] { _connection, _sqlString });

        return _ret;
    }

追加:

また、ここにはより一般的な設計上の問題があります。タイプを動的に指定したいが、キャストできる静的に型指定されたオブジェクトを取得したい (私は静的に仮定しますか、それともリフレクションを続行しますか?)。では、なぜ動的インターフェイスを作成するのでしょうか。あなたはインターフェースを変更できないと言っていますが、これは少しばかげているように見えます。すべてのコンテキストが静的に型付けされているように見えますが、何らかの理由で動的に型付けされたメソッドが 1 つあります。コンパイル時に (または実行時にジェネリック引数を介して) 型がわかっている場合は、メソッドを次のように変更するだけです。

    public IEnumerable<T> GetByParentId<T>(string table)
    {
        IDbConnection _connection = _dbProvider.GetConnection();
        var _sqlString = "select * from " + table;
        var _ret = _connection.Query<T>(_sqlString);
        return _ret;
    }
于 2013-01-24T13:12:30.390 に答える