In meiner Anwendung verwende ich Dapper, um auf die Datenbank zuzugreifen.
Ich habe den folgenden Beispielcode:
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;
}
Es ist möglich, das FastExpando
Objekt in meinen childType
oder Dapper zu zwingen, eine stark typisierte Sammlung zurückzugeben?
Ich kann meine Methodensignatur nicht ändern!
Sie können die Query-Methode über Reflection aufrufen und das generische TItem-Argument Ihres childType angeben. Dann wird Dapper IEnumerable zurückgeben und Sie können es umsetzen. Sie können auch Dapper (es ist nicht sehr groß) forkieren und eine sehr einfache Überladung von Query durchführen, die (Type childType) -Argument enthält und die richtigen Methoden aufruft.
Was Sie vor sich haben, ist das Problem von C # bei der Arbeit mit Generika. Als statisch typisierte Sprache ist C # schlecht mit dynamischen Typen zu arbeiten. Wenn Sie dynamisch arbeiten wollen, enden Sie immer mit Reflexion.
Hier ist ein Beispiel, wie Sie die Abfrage-Methode mit Typargumenten aufrufen können. Möglicherweise müssen Sie das ein wenig korrigieren:
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;
}
Anhängen:
Außerdem sehe ich hier ein allgemeineres Konstruktionsproblem. Sie möchten den Typ dynamisch angeben, möchten aber dann statisch getippte Objekte erhalten, die Sie umsetzen können (ich gehe davon aus, dass Sie statisch vorgehen oder mit der Spiegelung fortfahren möchten?). Dann ... Warum erstellen Sie überhaupt eine dynamische Schnittstelle? Sie sagen, dass Sie die Schnittstelle nicht ändern können, aber das sieht ein bisschen dumm aus. Es scheint, dass all Ihr Kontext statisch typisiert ist, aber aus irgendeinem Grund haben Sie eine dynamisch typisierte Methode. Wenn Sie Typen während der Kompilierungszeit (oder über generische Argumente in der Laufzeit) kennen, sollten Sie Ihre Methode einfach so ändern:
public IEnumerable<T> GetByParentId<T>(string table)
{
IDbConnection _connection = _dbProvider.GetConnection();
var _sqlString = "select * from " + table;
var _ret = _connection.Query<T>(_sqlString);
return _ret;
}