简体   繁体   English

传递带参数的函数,作为参数并返回泛型类型

[英]Passing function with parameter, as a parameter and returning a generic type

In the code below I am trying to pass a function func in to the GetData function.在下面的代码中,我试图将函数func传递给GetData函数。 This would take the reader object and map it to a generic object.这将获取读取器对象并将其映射到通用对象。

I was hoping to pass GetData an object type along with a function to map data to that object type so I didn't have to repeatedly open / close / dispose the connection.我希望通过GetData一个对象类型以及一个将数据映射到该对象类型的函数,这样我就不必重复打开/关闭/处理连接。

Is this possible or does anyone have any alternative suggestions?这是可能的还是有人有任何其他建议?

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

The signature that you're looking for is this:您正在寻找的签名是这样的:

T GetData<T>(string cmdText, Func<SqlDataReader, T> func)

Then you can go ahead and write your function as this:然后你可以继续编写你的函数:

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

And you would use it like this:你会像这样使用它:

var result = GetData("select * from Foo", dr =>
{
    while (dr.Read())
    {
        return new { property = dr["column"] };
    }
    throw new DataException();
});

Now that's based on how you said you'd like to use it in your question.现在这是基于你说你想在你的问题中使用它的方式。

However , you've made the use of the function a bit hard on yourself as you've split the implementation - part is in GetData and part is in the calling code.但是,在拆分实现时,您对自己使用该函数有点困难——一部分在GetData ,另一部分在调用代码中。

You're better off using this signature:你最好使用这个签名:

IEnumerable<T> GetData<T>(string cmdText, Func<SqlDataReader, T> func)

Now you can write the method like this:现在你可以像这样编写方法:

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

The advantage now is that the calling code is much simpler:现在的好处是调用代码简单多了:

var results = GetData("select * from Foo", dr => new { property = dr["column"] });

This returns as many rows of data as your query returns.这将返回与您的查询返回的数据行一样多的数据行。

If you know that your calling code only returns a single value, then you can drop a .Single() at the end of the method call to ensure you get one and only one result.如果您知道您的调用代码只返回一个值,那么您可以在方法调用结束时删除.Single()以确保您获得一个且只有一个结果。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM