我有一个传递给扩展程序的IEnumerable<School>
集合
填充DropDownList
的方法。我也想通过
DataValueField
和DataTextField
作为参数,但我希望它们成为
强烈打字。
基本上,我不想为string
和DataValueField
参数传递DataTextField
,这很容易出错。
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);
我的问题是,如何将DataValueField
和DataTextField
强类型作为参数传递给populateDropDownList?
答案 0 :(得分:4)
如果您只是尝试使用属性链,您可以将参数更改为Expression<Func<T, string>>
,然后提取所涉及的属性名称 - 您需要剖析{{3你得到......你期望Expression<TDelegate>
将成为表示属性访问权限的Body
。如果你有多个(school.address.FirstLine
),那么一个成员访问的目标表达式将是另一个,等等。
由此,您可以构建一个字符串,以便在DataValueField
(以及DataTextField
)中使用。当然,来电者仍然可以搞砸你:
myDropDownList.populateDropDownList(states,
school => school.stateCode.GetHashCode().ToString(),
school => school.stateName);
...但您可以检测到它并抛出异常,并且您仍然可以为好的来电者进行重构验证。
答案 1 :(得分:4)
根据Jon的回答和this帖子,它给了我一个想法。我将DataValueField
和DataTextField
作为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);
答案 2 :(得分:0)
随着你的尝试,即使你确实得到它来编译/运行,它仍然是错的,因为价值&amp;文本字段将被设置为列表中的值而不是属性名称(即,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");