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

是否可以将FastExpandoitem 强制转换为 mychildType或强制 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;
    }

附加:

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

    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 回答