C# 将强类型属性名作为参数传递
我有一个C# 将强类型属性名作为参数传递,c#,lambda,strong-typing,C#,Lambda,Strong Typing,我有一个IEnumerable集合,该集合正在传递给扩展 方法填充下拉列表。我也想通过考试 DataValueField和DataTextField作为参数,但我希望它们是 强类型 基本上,我不想为DataValueField和DataTextField参数传递string,这很容易出错 public static void populateDropDownList<T>(this DropDownList source, IEnumerable<T> d
IEnumerable
集合,该集合正在传递给扩展
方法填充下拉列表
。我也想通过考试
DataValueField
和DataTextField
作为参数,但我希望它们是
强类型
基本上,我不想为DataValueField
和DataTextField
参数传递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();
}
我的问题是,如何将强类型的DataValueField
和DataTextField
作为参数传递给populateDropDownList?如果您只尝试使用属性链,可以将参数更改为表达式
,然后提取所涉及的属性名称-您需要解析您得到的属性名。。。您可能希望,将是表示属性访问的。如果您有多个(school.address.FirstLine
),则一个成员访问的目标表达式将是另一个,以此类推
由此,您可以构建一个字符串,用于DataValueField
(以及DataTextField
)。当然,打电话的人仍然可以欺骗你:
myDropDownList.populateDropDownList(states,
school => school.stateCode.GetHashCode().ToString(),
school => school.stateName);
。。。但是您可以检测到它并抛出异常,并且您仍然可以为好的调用者提供重构证明。对于您所尝试的,即使您确实让它编译/运行了,它仍然是错误的,因为Value&Text字段将被设置为列表中的一个值,而不是属性名称(即,
DataValueField=“TX”;DataTextField=“Texas”
而不是您真正想要的DataValueField=“stateCode”DataTextField=“stateName”
)
public static void populateDropDownList(此DropDownList源,
IEnumerable数据源,
Func dataValueField,
Func数据文本字段){
source.DataValueField=DataValueField();
source.DataTextField=DataTextField();
source.DataSource=数据源;
source.DataBind();
}
myDropDownList.populateDropDownList(州、,
“州代码”,
“州名”);
基于Jon的回答和帖子,它给了我一个想法。我将数据值字段
和数据文本字段
作为表达式
传递给我的扩展方法。我创建了一个方法,该方法接受该表达式并返回该属性的成员信息
。然后,我只需调用。Name
,我已经获取我的字符串
哦,我把扩展方法的名称改为填充
,太难看了
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.");
}
我不明白这些字段是string类型的。我只是想让您知道,在惯用C语言中,您可以使用PascalCase将方法命名为
Populate
。
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");
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);