Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Use of Generic Delegates

We know that "Action, Func and Predicate are pre-defined Generic delegates. So as delegate they can point to functions with specified signature."

I have following data-access scenario in which Func<T,R> helps in avoiding a foreach loop in the calling method. The approach 2 doesn’t have looping. Here Func<T,R> helped to avoid loop.

What are the other scenarios for generic delegates in which it can save lots of lines of code?

REFERENCES

  1. Dynamically Composing Expression Predicates
  2. Advanced C#
  3. C#/.NET Little Wonders: The Predicate, Comparison, and Converter Generic Delegates
  4. Func vs. Action vs. Predicate
  5. What is Func, how and when is it used
  6. How can I pass in a func with a generic type parameter?

CODE

Approach 1

public class MyCommonDAL
{

    public static IEnumerable<IDataRecord> ExecuteQueryWithTextCommandType(string commandText, List<SqlParameter> commandParameters)
    {
        using (SqlConnection connection = new SqlConnection(connectionString))
        {
            using (SqlCommand command = new SqlCommand())
            {
                command.Connection = connection;
                command.CommandType = CommandType.Text;
                command.CommandText = commandText;
                command.CommandTimeout = 0;
                command.Parameters.AddRange(commandParameters.ToArray());

                connection.Open();
                using (var rdr = command.ExecuteReader())
                {
                    while (rdr.Read())
                    {
                        yield return rdr;
                    }
                    rdr.Close();
                }
            }
        }
    }

}


public class MyLogDAL
{
    public List<LogSeverityType> GetLogSeveritiesFirstApproach(LogSeverityType logSeverityType)
    {


        List<SqlParameter> commandParameters = new List<SqlParameter>()
                                                {
                                                    new SqlParameter {ParameterName = "@CreatedDateTime", 
                                                                      Value = logSeverityType.CreatedDateTime, 
                                                                      SqlDbType = SqlDbType.DateTime}
                                                };


        string commandText = @"SELECT * FROM dbo.LogSeverityType WHERE CreatedDateTime > @CreatedDateTime";
        var results = MyCommonDAL.ExecuteQueryWithTextCommandType(commandText, commandParameters);

        List<LogSeverityType> logSeverities = new List<LogSeverityType>();

 //LOOP
        foreach (IDataRecord rec in results)
        {
            LogSeverityType objLogSeverityType = LogSeverityType.LogSeverityTypeFactory(rec);
            logSeverities.Add(objLogSeverityType);
        }


        return logSeverities;
    }



}

Approach 2

    public class MyCommonDAL
    {

        public static IEnumerable<T> ExecuteQueryGenericApproach<T>(string commandText, List<SqlParameter> commandParameters, Func<IDataRecord, T> factoryMethod)
        {

            //Action, Func and Predicate are pre-defined Generic delegates.
            //So as delegate they can point to functions with specified signature.

            using (SqlConnection connection = new SqlConnection(connectionString))
            {
                using (SqlCommand command = new SqlCommand())
                {
                    command.Connection = connection;
                    command.CommandType = CommandType.Text;
                    command.CommandText = commandText;
                    command.CommandTimeout = 0;
                    command.Parameters.AddRange(commandParameters.ToArray());

                    connection.Open();
                    using (var rdr = command.ExecuteReader())
                    {
                        while (rdr.Read())
                        {
                            yield return factoryMethod(rdr);
                        }
                        rdr.Close();
                    }
                }
            }
        }


    }


    public class MyLogDAL
    {

        public List<LogSeverityType> GetLogSeveritiesSecondApproach(LogSeverityType logSeverityType)
        {


            List<SqlParameter> commandParameters = new List<SqlParameter>()
                                                    {
                                                        new SqlParameter {ParameterName = "@CreatedDateTime", 
                                                                          Value = logSeverityType.CreatedDateTime, 
                                                                          SqlDbType = SqlDbType.DateTime}
                                                    };


            string commandText = @"SELECT * FROM dbo.LogSeverityType WHERE CreatedDateTime > @CreatedDateTime";
            //var results = MyCommonDAL.ExecuteQueryWithTextCommandType(commandText, commandParameters);

            IEnumerable<LogSeverityType> logSeverities = MyCommonDAL.ExecuteQueryGenericApproach<LogSeverityType>(commandText, commandParameters, LogSeverityType.LogSeverityTypeFactory);

            //foreach (IDataRecord rec in results)
            //{
            //    LogSeverityType objLogSeverityType = LogSeverityType.LogSeverityTypeFactory(rec);
            //    logSeverities.Add(objLogSeverityType);
            //}


            return logSeverities.ToList();
        }


    }

Other Code Required

    public class LogSeverityType
    {
        public int LogSeverityTypeID { get; set; }
        public string Name { get; set; }
        public string Description { get; set; }
        public DateTime CreatedDateTime { get; set; }

        public static LogSeverityType LogSeverityTypeFactory(IDataRecord record)
        {
            return new LogSeverityType
            {
                LogSeverityTypeID = (int)record[0],
                Name = (string) record[1],
                Description = (string)record[2],
                CreatedDateTime = (DateTime) record[3]
            };
        }
    }

        static void Main(string[] args)
        {
            MyLogDAL logDAL = new MyLogDAL();
            LogSeverityType logSeverityType = new LogSeverityType();
            logSeverityType.CreatedDateTime = Convert.ToDateTime("1/1/2000");

            List<LogSeverityType> logSeverities = logDAL.GetLogSeveritiesSecondApproach(logSeverityType);
        }
like image 338
LCJ Avatar asked Dec 19 '13 12:12

LCJ


People also ask

What is the purpose of using generic in C#?

Generics allow you to define the specification of the data type of programming elements in a class or a method, until it is actually used in the program. In other words, generics allow you to write a class or method that can work with any data type.

What is the benefit of having a generic collection?

Generic collection types generally perform better for storing and manipulating value types because there is no need to box the value types. Generic delegates enable type-safe callbacks without the need to create multiple delegate classes.

What is the advantage of using delegates in C#?

Advantages to using them in design:Allow you to develop libraries and classes that are easily extensible, since it provides an easy way to hook in other functionality (for example, a where clause in LINQ can use a delegate [Func<T,bool>] to filter on, without having to write new code in the Where method.

What are the three types of generic delegates in C#?

Func, Action and Predicate are generic inbuilt delegates present in System namespace. All three can be used with method, anonymous method and lambda expression.


1 Answers

I use generic delegates when parsing / finding nodes in XML / HTML documents, and assigning the values to properties. I wrote a blog post about it, which shows refactoring the code to pass in a generic delegate, and how much code was removed.

like image 84
harriyott Avatar answered Oct 12 '22 02:10

harriyott