2012-10-25 93 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");