2011-02-24 121 views
2

我有一組方法,它們包含日期和布爾值。然後這些方法使用一些SQL,然後將它傳遞給另一個方法並返回一個列表。每種方法都與返回的SQL和List的例外幾乎相同。現在我知道有更好的方法做這些方法,但我不知道如何。C#抽象方法

有沒有人有任何想法,我可以如何抽象或使用更好的設計,因爲方法幾乎相同?

下面是代碼:

private List<ENT_Message> GetMessageData(DateTime? startDate, DateTime? endDate, bool IsSelectAll) 
{ 
    List<ENT_Message> ret = new List<ENT_Message>(); 
    string sql = ""; 

    if (IsSelectAll) 
    { 
     sql = "select * from tbl_message"; 
    } 
    else 
    { 
     sql = " Select * from tbl_message where created_Date between @start_Date and @end_date"; 
    } 

    return Converter.SerializeToMessageList(this.GetData(startDate, endDate, IsSelectAll, sql));     
} 

private List<ENT_SensorData> GetSensorData(DateTime? startDate, DateTime? endDate, bool IsSelectAll) 
{ 
    List<ENT_SensorData> ret = new List<ENT_SensorData>(); 
    string sql = ""; 

    if (IsSelectAll) 
    { 
     sql = "select * from tbl_sensor_data"; 
    } 
    else 
    { 
     sql = "select * from tbl_sensor_data where Timestamp between @start_date and @end_Date"; 
    } 

    return Converter.SerializeToSensorDataList(this.GetData(startDate, endDate, IsSelectAll, sql)); 
} 

private List<ENT_SensorDataEvent> GetSensorDataEvents(DateTime? startDate, DateTime? endDate, bool IsSelectAll) 
{ 
    List<ENT_SensorDataEvent> ret = new List<ENT_SensorDataEvent>(); 
    string sql = ""; 

    if (IsSelectAll) 
    { 
     sql = "select * from tbl_sensor_data_event"; 
    } 
    else 
    { 
     sql = "select * from tbl_sensor_data_event where start_time between @start_date and @end_Date"; 
    } 

    return Converter.SerializeToSensorEventDataList(this.GetData(startDate, endDate, IsSelectAll, sql)); 
} 

private List<ENT_SensorDataState> GetSensorDataState(DateTime? startDate, DateTime? endDate, bool IsSelectAll) 
{ 
    List<ENT_SensorDataState> ret = new List<ENT_SensorDataState>(); 
    string sql = ""; 

    if (IsSelectAll) 
    { 
     sql = "select * from tbl_sensor_data_state"; 
    } 
    else 
    { 
     sql = "select * from tbl_sensor_data_state where start_time between @start_date and @end_Date"; 
    } 

    return Converter.SerializeToSensorDateStateList(this.GetData(startDate, endDate, IsSelectAll, sql)); 
} 

private List<ENT_WorkOrder> GetWorkOrders(DateTime? startDate, DateTime? endDate, bool IsSelectAll) 
{ 
    List<ENT_WorkOrder> ret = new List<ENT_WorkOrder>(); 
    string sql = ""; 

    if (IsSelectAll) 
    { 
     sql = "select * from tbl_workorder"; 
    } 
    else 
    { 
     sql = "select * from tbl_sensor_data_state where completed_date between @start_date and @end_Date"; 
    } 

    return Converter.SerializeToWorkOrderList(this.GetData(startDate, endDate, IsSelectAll, sql)); 
} 
+3

爲什麼你不只是添加代碼作爲你的問題的一部分? – RQDQ 2011-02-24 16:38:38

+0

@RQDQ:代碼有點長,會使問題變得不可讀。我清楚地看到其他地方沒有問題。 – 2011-02-24 16:40:42

+0

@亨克如果你看看代碼,你會看到返回的列表 – Funky 2011-02-24 16:43:46

回答

2

你可以大大縮短你的功能。例如,而不是

private List<ENT_SensorDataState> GetSensorDataState(DateTime? startDate, DateTime? endDate, bool IsSelectAll) 
{ 
    List<ENT_SensorDataState> ret = new List<ENT_SensorDataState>(); 
    string sql = ""; 

    if (IsSelectAll) 
    { 
     sql = "select * from tbl_sensor_data_state"; 
    } 
    else 
    { 
     sql = "select * from tbl_sensor_data_state where start_time between @start_date and @end_Date"; 
    } 

    return Converter.SerializeToSensorDateStateList(this.GetData(startDate, endDate, IsSelectAll, sql)); 
} 

你可以簡單地寫

private List<ENT_SensorDataState> GetSensorDataState(DateTime? startDate, DateTime? endDate, bool IsSelectAll) 
{ 
    string sql = "select * from tbl_sensor_data_state" 
       + (IsSelectAll ? "" : "where start_time between @start_date and @end_Date"); 

    return Converter.SerializeToSensorDateStateList(this.GetData(startDate, endDate, IsSelectAll, sql)); 
} 

,基本上降低了你的函數真正重要的東西:在SQL和序列化功能的名稱。

+0

我非常喜歡這個! – Funky 2011-02-24 16:49:44

+0

因此,您仍然複製/粘貼每種方法。泛型或抽象方法可以產生重複性較低的結果。 – Abel 2011-02-24 17:13:30

+0

@Abel:沒錯。儘管如此,SQL在每個函數中都有所不同,所以*部分*不能一概而論。 – Heinzi 2011-02-24 23:13:40

1
private List<T> GetData<T>(DateTime? startDate, DateTime? endDate, bool IsSelectAll) 
     { 
      List<T> ret = new List<T>(); 

      string tableName = "";//Select the table name based on T here 
      string sql = ""; 

      if (IsSelectAll) 
      { 
       sql = "select * from tbl_sensor_data"; 
      } 
      else 
      { 
       sql = "select * from tbl_sensor_data where Timestamp between @start_date and @end_Date"; 
      } 
      //Build your list using the appropriate converter based on T here   
      return Converter.SerializeToSensorDataList(this.GetData(startDate, endDate, IsSelectAll, sql)); 
     } 

從這一點上來說,你只

GetData<ENT_whatever>() 

調用。

+0

'tbl_sensor_data'僅與一種方法相關 - 它確實需要依賴於T. – 2011-02-24 16:46:27

0

如果你存儲你的sql語句和一個委託方法在一個映射中的鍵是某種類型T,然後讓你的方法是通用的(方法需要類型T並返回T的List),你可以做一個地圖查找來獲得正確的sql語句和委託方法。

2

看起來你有機會做一個通用的方法。如果我有語法錯誤,我很抱歉。

private List<T> GetData<T>(DateTime? startDate, DateTime? endDate, bool IsSelectAll) where T : ENT_Data 
{ 
    List<T> ret = new List<T>(); 
    string sql = ""; 

    if (IsSelectAll) 
    { 
     sql = "select * from " + T.table; 
    } 
    else 
    { 
     sql = " Select * from " + T.table + " where created_Date between @start_Date and @end_date"; 
    } 

    return Converter.Serialize<T>(this.GetData(startDate, endDate, IsSelectAll, sql));  
} 

注意的幾件事情我做:

  1. 的一般方法具有約束T是ENT_Data,我只是做了一個類型的子類。
  2. 我給了ENT_Data類型一個table字段,用於您的查詢。
  3. Converter.Serialize方法也以類似的方式被製作爲通用的。

如果我錯過了任何重要的事情,請讓我知道。

+0

您不能約束T有一個靜態字段/名爲'table'的屬性。 – 2011-02-24 16:48:48

+0

你說得對,我的不好。你將不得不做一個T的實例,然後獲取表名。 – Tesserex 2011-02-24 16:50:03

+0

只是一個想法,使更通用的(寫一次):使用屬性'表'的父接口'IEnt_Data'。然後讓你的基類具體類「ENT_Data」有一個靜態方法'ENT_Data.Create ',它返回該類型的一個實例。然後你可以用'ENT_Data.Create ().table'來調用它。 – Abel 2011-02-24 17:12:00

1

您可以創建一個SqlRetriever類,然後將每個子類與要發送的特定SQL消息進行子類化。

class SqlRetriever { 
    public abstract void SendSqlCmd(); 
    public ArrayList List { 
     get; set; 
    } 
} 

class SqlRetrieverXXX 
    public const string SqlCmd = " ... "; 
    public override void SendSqlCmd() 
    { 
     /* ... */ 
    } 
} 

另一種可能性,涉及少classses,與不良的設計是以下之一:

class SqlRetriever { 
     public const string SQLCmd1 = "..."; 
     public const string SQLCmd2 = "..."; 

     public void SendSqlCmd(string sqlcmd) 
     { 
      /*Send the SQL Cmd and store the result in the list */ 
     } 

     public ArrayList List { 
      get; set; 
     } 

     public static ArrayList DoSqlCmd(string sqlCmd) 
     { 
      var obj = new SqlRetriever(); 

      obj.SendSqlCmd(sqlCmd); 

      return obj.List; 
     } 
} 
0

你可以有一個基類的所有ENT_ *類繼承。然後製作一個方法列表<ENT_Base> GetData(yourParams)。創建一個工廠方法,根據ENT_Base的類型獲取實體列表。 你的GetData()調用並返回它。 你不會繞過開關盒或者如果然後找出你必須返回哪種實體。