2013-12-19 23 views
7

我們知道「Action,Func和Predicate是預定義的通用代理,因此作爲委託他們可以指向具有指定簽名的函數。」使用通用代理

我有以下數據訪問方案,其中Func<T,R>幫助avoiding a foreach loop在調用方法。方法2沒有循環。這裏Func<T,R>有助於避免循環。

通用委託的其他場景可以節省大量代碼行嗎?

參考文獻

  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

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



} 

方法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(); 
     } 


    } 

其他代碼所需

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

「通用代表的其他最重要的5種使用場景是什麼?」 - 當然這是主觀的? – Nathan

+1

當然,沒問題 - 但應該可以在http://programmers.stackexchange.com/上查看。 – Nathan

+1

@Nathan:我想即使[程序員.se]也會拒絕這個。這是純粹的意見,沒有別的。 –

回答

1

在解析/查找XML/HTML文檔中的節點並將值分配給屬性時,我使用泛型委託。我寫了a blog post about it,它顯示了重構代碼以傳遞一個通用委託,以及刪除了多少代碼。