2011-11-29 71 views
0

我寫了一個擴展方法,它根據作爲索引器傳遞給函數的類型來查找控件。這是我的擴展方法。如何改進我的擴展方法

public static T FindControlByType<T>(this Control childCnt, string Id = "") 
    { 
     foreach (Control item in childCnt.Controls) 
     { 
      if (item is T) 
      { 
       if (Id == "") 
       { 
        return (T)Convert.ChangeType(item, typeof(T)); 
       } 
       if (item.ID.Contains(Id)) 
       { 
        return (T)Convert.ChangeType(item, typeof(T)); 
       } 
      } 
     } 

     //return T 

    } 

我想返回類型T的控制。我如何實現這一目標?

回答

2

如果添加通用約束來限制TControl型的,那麼你不」 t需要撥打ChangeType。演員陣容夠了。

public static T FindControlByType<T>(this Control childCnt, string id = "") 
    where T : Control 
{ 
    foreach (Control item in childCnt.Controls) 
    { 
     if (item is T && ((id == "" || item.ID.Contains(id))) 
     { 
      return (T)item; 
     } 
    } 

    return default(T); 

} 
+0

感謝您的快速響應。不,因爲'typeof(T)'是'System.Type'類型的一個實例,所以你不會返回默認值(T),也就是說,當cnt被nt發現時,返回相同的類型,即typeOf(T)控制 – Tuscan

+0

需要返回一個'T'類型的實例。 –

1

有一件事我發現是沒有必要的

if (Id == "")     
    {      
     return (T)Convert.ChangeType(item, typeof(T));     
    } 

因爲在Asp.net每個控件必須有ID。

你爲什麼不嘗試oftype如下LINQ的方法......(這只是建議)

var checkBoxes = this.GetAllControls().OfType<CheckBox>(); 
+0

Id是一個可選參數。它由用戶決定是否要通過 – Tuscan

+0

if條件是檢查方法的Id參數,而不是Control的Id屬性。 – BACON

+0

我認爲Id可能會或可能不會通過,所以相信這應該在那裏 – V4Vendetta

1

我不知道爲什麼要轉換的值,如果你已經驗證了它is T

這應該是等價的:

public static T FindControlByType<T>(this Control childCnt, string Id = "") 
    where T: Control 
{ 
    return childCnt.Controls.OfType<T>() 
        .FirstOrDefault(item => string.IsNullOrEmpty(Id) || item.ID.Contains(Id)); 

} 
+0

感謝您的快速響應。而不是返回默認(T),即null當cnt是nt找到不能返回相同類型,即typeOf(T)控制 – Tuscan

+0

編號'typeof(T)'是'System.Type'對象。在這個例子中'T'是一個'Control'對象。當方法需要一個Control對象時,你不能返回一個'System.Type'實例。 – smartcaveman

1

我想這應該是足夠了:

public static T FindControlByType<T>(this Control child, string id="") where T: Control 
{ 
    return child.Controls.OfType<T>().FirstOrDefault(x => x.ID.Contains(id));  
} 

順便說一句,你確定要使用x.ID.Contains(id)?爲什麼?

如果ID="indians"id="indian",然後ID.Contains(id)將返回true,即使IDid不一樣的。如果它們不一樣,比較它們的意義是什麼,並假裝它們是相同的?

我認爲你應該使用x.ID.Equals(id)

return child.Controls.OfType<T>().FirstOrDefault(x => x.ID.Equals(id)); 
+1

是的,謝謝你的建議。 – Tuscan

1

如果此方法確實是按類型尋找孩子Control S和不受ID *了這麼多,你可能會考慮返回IEnumerable<T>而不是T。該方法可接着使用LINQ可以輕鬆實現:

public static IEnumerable<T> FindControlsByType<T>(this Control childCnt, string Id = "") 
    where T : Control 
{ 
    var controls = childCnt.Controls.OfType<T>(); 

    return Id == "" ? controls : controls.Where(c => c.ID.Contains(Id)); 
} 

而且,正如其他人所指出的那樣,添加一個類型約束爲T類型參數。

*爲此,FindControl method已經可以滿足您的需求了嗎?但請注意,它將搜索確切的ID而不是子字符串。