Передача функции с параметром в качестве параметра и возвращение типа generi c - PullRequest
1 голос
/ 21 февраля 2020

В приведенном ниже коде я пытаюсь передать функцию func в функцию GetData. Это взяло бы объект читателя и сопоставило бы его с универсальным c объектом.

Я надеялся передать 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
            //  }
        }
    }
}

1 Ответ

0 голосов
/ 21 февраля 2020

Подпись, которую вы ищете, это:

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

Тогда вы можете go вперед и написать свою функцию так:

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

Это возвращает столько строк данные в ответ на ваш запрос.

Если вы знаете, что ваш вызывающий код возвращает только одно значение, то вы можете сбросить .Single() в конце вызова метода, чтобы получить один и только один результат.

...