Dapper collection fortement typée de Type

c# dapper

Question

Dans mon application, j'utilise Dapper pour accéder à la base de données.

J'ai l'exemple de code suivant:

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

Il est possible de FastExpando élément FastExpando en mon childType ou de forcer Dapper à renvoyer une collection fortement typée?

Je ne peux pas changer la signature de ma méthode!

Réponse acceptée

Vous pouvez appeler la méthode Query via la réflexion et fournir l'argument TItem générique de votre childType. Ensuite, Dapper retournera IEnumerable et vous pourrez le lancer. En outre, vous pourriez créer Dapper (ce n'est pas très gros) et créer une surcharge très simple de Query, qui inclurait l'argument (Type childType) et appelle des méthodes appropriées à l'intérieur.

Ce que vous rencontrez est le problème de C # dans le travail avec les génériques. Etant un langage typé statiquement, C # est mauvais pour les types dynamiques. Si vous voulez travailler de manière dynamique, vous vous retrouvez toujours avec une réflexion.

Voici un exemple de la façon dont vous pouvez appeler la méthode de requête avec des arguments de type. Vous devrez peut-être corriger ceci un peu:

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

Ajouter:

En outre, je vois un problème de conception plus général ici. Vous voulez spécifier le type dynamiquement, mais ensuite vous voulez obtenir des objets typés statiquement, que vous pourrez lancer (je suppose que vous voulez statiquement, ou vous voulez continuer avec la réflexion?). Alors ... Pourquoi créez-vous une interface dynamique en premier lieu? Vous dites que vous ne pouvez pas modifier l'interface, mais cela semble un peu stupide. Il semble que tout votre contexte soit statiquement typé, mais pour une raison quelconque, vous avez une méthode typée dynamiquement. Si vous connaissez des types au moment de la compilation (ou via des arguments génériques dans le runtime), vous devez simplement changer votre méthode en quelque chose comme ceci:

    public IEnumerable<T> GetByParentId<T>(string table)
    {
        IDbConnection _connection = _dbProvider.GetConnection();
        var _sqlString = "select * from " + table;
        var _ret = _connection.Query<T>(_sqlString);
        return _ret;
    }



Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Est-ce KB légal? Oui, apprenez pourquoi
Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Est-ce KB légal? Oui, apprenez pourquoi