传递带参数的函数,作为参数并返回泛型类型
Passing function with parameter, as a parameter and returning a generic type
在下面的代码中,我试图将函数 func
传递给 GetData
函数。这将采用 reader 对象并将其映射到通用对象。
我希望传递 GetData
一个对象类型以及一个将数据映射到该对象类型的函数,这样我就不必重复打开/关闭/处理连接。
这可行吗?有人有其他建议吗?
public T GetData<T>(string cmdText,Func<T> func)
{
using (SqlConnection conn = new SqlConnection(connectionStringBuilder.ConnectionString))
{
using (SqlCommand cmd = new SqlCommand(cmdText, conn))
{
SqlDataReader reader = cmd.ExecuteReader();
//return func(reader);
// WITHIN THE FUNC FUNCTION:
// while (reader.Read())
// {
// Map function to T e.g
// T.property = reader["column"];
// Return T
// }
}
}
}
您要找的签名是这样的:
T GetData<T>(string cmdText, Func<SqlDataReader, T> func)
然后你可以继续写你的函数:
public T GetData<T>(string cmdText, Func<SqlDataReader, T> func)
{
using (var conn = new SqlConnection(connectionStringBuilder.ConnectionString))
{
using (var cmd = new SqlCommand(cmdText, conn))
{
var reader = cmd.ExecuteReader();
return func(reader);
}
}
}
你会像这样使用它:
var result = GetData("select * from Foo", dr =>
{
while (dr.Read())
{
return new { property = dr["column"] };
}
throw new DataException();
});
现在这取决于你说你想在你的问题中使用它的方式。
但是,您在拆分实现时对自己使用该函数有点困难 - 一部分在 GetData
中,一部分在在调用代码中。
你最好使用这个签名:
IEnumerable<T> GetData<T>(string cmdText, Func<SqlDataReader, T> func)
现在可以这样写方法了:
public IEnumerable<T> GetData<T>(string cmdText, Func<SqlDataReader, T> func)
{
using (var conn = new SqlConnection(connectionStringBuilder.ConnectionString))
{
using (var cmd = new SqlCommand(cmdText, conn))
{
var reader = cmd.ExecuteReader();
while (reader.Read())
{
yield return func(reader);
}
}
}
}
现在的好处是调用代码简单多了:
var results = GetData("select * from Foo", dr => new { property = dr["column"] });
这 returns 行的数据与您的查询 returns 一样多。
如果您知道您的调用代码只有 returns 一个值,那么您可以在方法调用结束时删除一个 .Single()
以确保您得到一个且只有一个结果。
在下面的代码中,我试图将函数 func
传递给 GetData
函数。这将采用 reader 对象并将其映射到通用对象。
我希望传递 GetData
一个对象类型以及一个将数据映射到该对象类型的函数,这样我就不必重复打开/关闭/处理连接。
这可行吗?有人有其他建议吗?
public T GetData<T>(string cmdText,Func<T> func)
{
using (SqlConnection conn = new SqlConnection(connectionStringBuilder.ConnectionString))
{
using (SqlCommand cmd = new SqlCommand(cmdText, conn))
{
SqlDataReader reader = cmd.ExecuteReader();
//return func(reader);
// WITHIN THE FUNC FUNCTION:
// while (reader.Read())
// {
// Map function to T e.g
// T.property = reader["column"];
// Return T
// }
}
}
}
您要找的签名是这样的:
T GetData<T>(string cmdText, Func<SqlDataReader, T> func)
然后你可以继续写你的函数:
public T GetData<T>(string cmdText, Func<SqlDataReader, T> func)
{
using (var conn = new SqlConnection(connectionStringBuilder.ConnectionString))
{
using (var cmd = new SqlCommand(cmdText, conn))
{
var reader = cmd.ExecuteReader();
return func(reader);
}
}
}
你会像这样使用它:
var result = GetData("select * from Foo", dr =>
{
while (dr.Read())
{
return new { property = dr["column"] };
}
throw new DataException();
});
现在这取决于你说你想在你的问题中使用它的方式。
但是,您在拆分实现时对自己使用该函数有点困难 - 一部分在 GetData
中,一部分在在调用代码中。
你最好使用这个签名:
IEnumerable<T> GetData<T>(string cmdText, Func<SqlDataReader, T> func)
现在可以这样写方法了:
public IEnumerable<T> GetData<T>(string cmdText, Func<SqlDataReader, T> func)
{
using (var conn = new SqlConnection(connectionStringBuilder.ConnectionString))
{
using (var cmd = new SqlCommand(cmdText, conn))
{
var reader = cmd.ExecuteReader();
while (reader.Read())
{
yield return func(reader);
}
}
}
}
现在的好处是调用代码简单多了:
var results = GetData("select * from Foo", dr => new { property = dr["column"] });
这 returns 行的数据与您的查询 returns 一样多。
如果您知道您的调用代码只有 returns 一个值,那么您可以在方法调用结束时删除一个 .Single()
以确保您得到一个且只有一个结果。