来自Type的Dapper强类型集合

时间:2013-01-24 12:16:50

标签: c# dapper

在我的应用程序中,我使用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项投射到我的childType或强制Dapper返回强类型集合吗?

我无法更改我的方法签名!

1 个答案:

答案 0 :(得分: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;
    }

附加:

另外,我在这里看到了更普遍的设计问题。你想动态指定类型,但是想要获得静态类型的对象,你将能够投射(我假设是静态的,或者你想继续反射?)。然后......为什么你首先创建动态界面?你说,你不能改变界面,但这看起来有点愚蠢。似乎所有上下文都是静态类型的,但是,出于某种原因,你有一个动态类型的方法。 如果您在编译期间(或通过运行时中的泛型参数)知道类型,那么您应该简单地将方法更改为:

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