3

IEnumerable<School>を設定する拡張メソッドに渡されているコレクションがありDropDownListます。DataValueFieldとを引数として渡し DataTextFieldたいのですが、強く型付けしてほしいと思いました。

基本的に、引数にastringを渡したくないので、エラーが発生しやすくなります。DataValueFieldDataTextField

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私の質問は、populateDropDownListに引数としてとDataTextField強く型付けされたものを渡すにはどうすればよいですか?

4

3 に答える 3

5

ジョンの答えとこの投稿に基づいて、それは私にアイデアを与えました. DataValueFieldandDataTextFieldExpression<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);
于 2012-10-25T18:18:31.110 に答える
4

プロパティ チェーンのみを使用しようとしている場合は、パラメーターを に変更して、関連Expression<Func<T, string>>するプロパティ名を抽出することができます。取得したものを分析する必要がありExpression<TDelegate>ます...プロパティ アクセスBodyMemberExpression表す. 複数の ( school.address.FirstLine) がある場合、1 つのメンバー アクセスのターゲット式は別のものになります。

DataValueFieldそこから、 (および)で使用する文字列を作成できますDataTextField。もちろん、発信者はあなたを台無しにすることができます:

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

...しかし、それを検出して例外をスローすることはできます

于 2012-10-25T17:48:25.980 に答える
0

あなたがしようとしていたことで、コンパイル/実行できたとしても、値とテキストフィールドがプロパティ名ではなくリスト内の値に設定されているため、まだ間違っています (つまり、likeDataValueField = "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");
于 2012-10-25T17:49:21.583 に答える