2012-10-25 125 views
3

我有一個IEnumerable<School>的集合正在傳遞給擴展 方法,該方法將填充DropDownList。我還想通過 DataValueFieldDataTextField作爲參數,但我希望它們是 強類型。將強類型屬性名稱作爲參數傳遞

基本上,我不想爲DataValueFieldDataTextField參數傳遞string,這很容易出錯。

public static void populateDropDownList<T>(this DropDownList source, 
     IEnumerable<T> dataSource, 
     Func<T, string> dataValueField, 
     Func<T, string> dataTextField) { 
    source.DataValueField = dataValueField; //<-- this is wrong 
    source.DataTextField = dataTextField; //<-- this is wrong 
    source.DataSource = dataSource; 
    source.DataBind(); 
} 

調用是這樣的...

myDropDownList.populateDropDownList(states, 
     school => school.stateCode, 
     school => school.stateName); 

我的問題是,我怎麼能傳遞DataValueFieldDataTextField強類型作爲參數傳遞給populateDropDownList?

+0

我不明白這些字段類型的字符串。 – jfin3204

回答

4

基於Jon的回答和this後,它給了我一個主意。我將DataValueFieldDataTextField作爲Expression<Func<TObject, TProperty>>傳遞給我的擴展方法。我創建了一個接受該表達式的方法,並返回該屬性的MemberInfo。然後,我要撥打的電話是.Name,我有我的string

呵呵,我把擴展方法的名字改成了populate,它很醜。

public static void populate<TObject, TProperty>(
     this DropDownList source, 
     IEnumerable<TObject> dataSource, 
     Expression<Func<TObject, TProperty>> dataValueField, 
     Expression<Func<TObject, TProperty>> dataTextField) { 
    source.DataValueField = getMemberInfo(dataValueField).Name; 
    source.DataTextField = getMemberInfo(dataTextField).Name; 
    source.DataSource = dataSource; 
    source.DataBind(); 
} 

private static MemberInfo getMemberInfo<TObject, TProperty>(Expression<Func<TObject, TProperty>> expression) { 
    var member = expression.Body as MemberExpression; 
    if(member != null) { 
     return member.Member; 
    } 
    throw new ArgumentException("Member does not exist."); 
} 

調用是這樣的...

myDropDownList.populate(states, 
    school => school.stateCode, 
    school => school.stateName); 
4

如果你只是想用財產鏈,可以將參數改爲Expression<Func<T, string>>然後提取屬性名參與 - 你需要解剖Expression<TDelegate>你......你會想到, Body將代表一個MemberExpression代表一個屬性訪問。如果你有一個以上的(school.address.FirstLine),然後是一個成員訪問的對象表現將是一個又一個,等

從這一點,你可以建立一個字符串中的DataValueField(和DataTextField)使用。當然,調用者仍然可以擰你過來:

myDropDownList.populateDropDownList(states, 
    school => school.stateCode.GetHashCode().ToString(), 
    school => school.stateName); 

...但你可以檢測到它,並拋出一個異常,而你還在重構,證明了呼叫者。

0

即使您嘗試將它編譯/運行,它仍會出錯,因爲值文本字段將被設置爲列表中的值而不是屬性名稱(即,DataValueField = "TX"; DataTextField = "Texas";而不是像你真正想要的DataValueField = "stateCode"; DataTextField = "stateName";)。

public static void populateDropDownList<T>(this DropDownList source, 
     IEnumerable<T> dataSource, 
     Func<string> dataValueField, 
     Func<string> dataTextField) { 
    source.DataValueField = dataValueField(); 
    source.DataTextField = dataTextField(); 
    source.DataSource = dataSource; 
    source.DataBind(); 
} 

myDropDownList.populateDropDownList(states, 
     "stateCode", 
     "stateName");