2013-03-01 24 views
0

我有一個過濾/搜索方法現在每寫Windows Form提供搜索。我試圖在基類中創建一個通用方法,這樣我就可以避免大量的重複代碼。制定一個通用的方法

這裏是我要修改原來的代碼:

private void LoadData() 
{ 
    GridFilter filter = new GridFilter(); 
    filter.AddRule(dgvColDescription.DataPropertyName, txtDescription.Text); 

    if (cboColor.SelectedIndex != -1) 
    { 
     filter.AddRule(dgvColMaterialColorId.DataPropertyName, cboColor.SelectedValue.ToString()); 
    } 
    ... 
    //a lot more of this filter.AddRule stuff 
    ... 
} 

有兩件事情在這裏,我想 - 爲GridFilter和需要情況下的兩種類型的控制,我需要使用。

說了,這裏是我的一個通用的方法試試:

protected virtual void AddFilterRules<T>(Control ctrl, String str) where T : GridFilter 
{ 
    T filter; 
    if (ctrl is ComboBox) 
    { 
     if ((ctrl as ComboBox).SelectedIndex != -1) 
     { 
      filter.AddRule(/*dgvColMaterialColorId.DataPropertyName*/ str, (ctrl as ComboBox).SelectedValue.ToString()); 
     } 
    } 

    if (ctrl is TextBox) 
    { 
     filter.AddRule(/*dgvColCode.DataPropertyName*/str, ctrl.Text); 
    } 
} 

有一些意見,因爲我不知道如果我可以通過註釋的一部分字符串,但對我來說,更大的問題是,我從IDE獲得有關filter變量,它的錯誤:

使用未分配的局部變量的「過濾器」

畢竟有可能制定一個通用的方法,我該怎麼做?

+0

IDE錯誤是指它看不到創建該對象實例的行。 – 2013-03-01 14:47:01

+0

從代碼中,它看起來像你想做一個擴展方法,所以你可以調用myGridFilterVar.AddFilterRules。要做到這一點,從身體刪除T過濾器並定義方法爲AddFilterRules (此T篩選器,控制ctrl,字符串str)其中...擴展方法也必須是靜態的。 – 2013-03-01 14:56:41

回答

2

new() contraint添加到您的方法中。

protected virtual void AddFilterRules<T>(Control ctrl, String str) where T : GridFilter, new() 

然後

T filter = new T(); 

如果不是這樣,在通過T作爲一個參數:

protected virtual void AddFilterRules<T>(T filter, Control ctrl, String str) where T : GridFilter 
+0

當我需要通過10-15個控件時,我不確定這會起作用。爲每個人創建一個新的過濾器似乎是一個問題,但我可能是錯的? – Leron 2013-03-01 14:49:19

+0

@Lonon'new()'約束簡單地表明泛型必須有無參數的構造函數。 – Romoku 2013-03-01 14:50:23

+0

泛型類型參數就是一個_type_。如果你想使用一個特定的_instance_的GridFilter,你需要把它作爲一個常規的參數傳入。 – RoadieRich 2013-03-01 14:52:25

1

你的語法是正確的,但您有其他兩個問題:

  1. 您尚未初始化T任何事情。這是一個null參考您嘗試使用它的點。你打算通過T嗎?

  2. 你不是做任何事情T。你應該返回T?或將其分配給其他對象的屬性?

如果您在參考傳遞給T,然後在方法中修改它,那麼這兩個問題都解決了:

protected virtual void AddFilterRules<T>(T filter, Control ctrl, String str) 
    where T : GridFilter 
{ 
    ... 
} 

然而,在這種情況下,你的方法並不需要是通用在所有:

protected virtual void AddFilterRules(GridFilter filter, Control ctrl, String str) 
{ 
    ... 
} 
+0

我想使用'DataFilter'的單個實例,這樣我就可以將所有過濾器脈衝添加到同一個對象。這就是爲什麼我想在我的LoadData()方法中實例化'GridFilter',然後在調用'AddFilterRules '時傳遞這個對象實例是否這是考慮泛型方法的錯誤方法? – Leron 2013-03-01 14:51:13

0

您應該創建T的實例:

T filter = new GridFilter(); 

如果T總是將是一個GridFilter,你不妨通過GridFilter替換T:

protected virtual void AddFilterRules<GridFilter>(Control ctrl, String str) 
{ 
    GridFilter filter = new GridFilter(); 
    ... 
} 

不過,我不認爲你應該在所有使用一個通用的方法。您應該創建一個返回GridFilter的方法:

protected virtual GridFilter AddFilterRules(Control ctrl, String str) 
{ 
    GridFilter filter = new GridFilter(); 
    ... 

    return filter; 
} 
1

你爲什麼要使用一個通用的方法是什麼?

如果你的過濾器總是一個GridFilter你可以在你的方法中使用該類型。即使你使用像SpecialGridFilter這樣的派生類,它仍然可以工作。事實上,在您的原始方法中,您每創建一個新的GridFilter就意味着您可以在新方法中這樣做。因此,儘管事實上您現在已經傳遞了一些值,但並不需要新的方法。

它看起來像混淆了類型參數與普通參數。有一個類型參數並不意味着你得到了這種類型的實例。這隻意味着您可以對不同類型使用相同的算法,而無需爲每種類型明確編碼。

如果您確實需要泛型實現,則可以在通用參數where T : GridFilter, new()上使用類型約束。這使您可以在您的通用方法中創建new T()

新方法將在哪裏實施?

我不知道GridFilter現在如何實現,但它看起來像AddRule修改它。如果是這樣,您不應每次創建一個新實例,因爲所有更改都會丟失。因此,AddFilterRules也應該是GridFilter類的成員,並且每個表單應具有GridFilter的實例。

如果您無法更改GridFilter的實施,您仍然可以使用擴展方法。如果每次創建新的GridFilter是正確的,那麼您可以在Form類型上使用擴展方法。這取決於GridFilter的工作方式。

+0

非常有用,謝謝。 – Leron 2013-03-01 15:33:01

相關問題