0

私は現在、組み込みのヘルパーLabelFor <>、DisplayFor <>、EditorFor <>などと同じ種類の式を取り込むが、特に列挙型用のHtmlHelperを作成しようとしています。

例えばmodel => model.MyEnumProperty

私はラムダ式全体に不慣れで、これまでは多かれ少なかれ大丈夫でしたが(SackOverflowコミュニティによる他の回答からの多くの助けを借りて)、オブジェクトを取得しようとしているときに次の例外が発生します(すなわち、model)式で:

"タイプ'WCSFAMembershipDatabase.Models.Address'の変数'model'がスコープ''から参照されていますが、定義されていません"

public static MvcHtmlString EnumDisplayFor<TModel, TEnum>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TEnum>> expression)
{
    // memberExp represents "model.MyEnumProperty"
    MemberExpression memberExp = (MemberExpression)expression.Body;
    if (memberExp == null)
    {
        throw new ArgumentException(string.Format(
            "Expression '{0}' refers to a method, not a property.",
            expression.ToString()));
    }

    // modelExp represents "model"
    Expression modelExp = memberExp.Expression;

    // Convert modelExp to a Lambda Expression that can be compiled into a delegate that returns a 'model' object
    Expression<Func<TModel>> modelLambda = Expression.Lambda<Func<TModel>>(modelExp);

    // Compile modelLambda into the delegate
    // The next line is where the exception occurs...
    Func<TModel> modelDel = modelLambda.Compile();

    // Retrieve the 'model' object
    TModel modelVal = modelDel();

    // Compile the original expression into a delegate that accepts a 'model' object and returns the value of 'MyEnumProperty'
    Func<TModel, TEnum> valueDel = expression.Compile();

    // Retrieve 'MyEnumProperty' value
    TEnum value = valueDel(modelVal);

    // return the description or string value of 'MyEnumProperty'
    return MvcHtmlString.Create(GetEnumDescription(value));
}

// Function returns the Description Attribute (if one exists) or the string 
// representation for the specified enum value.
private static string GetEnumDescription<TEnum>(TEnum value)
{
    FieldInfo fi = value.GetType().GetField(value.ToString());

    DescriptionAttribute[] attributes = (DescriptionAttribute[])fi.GetCustomAttributes(typeof(DescriptionAttribute), false);

    if ((attributes != null) && (attributes.Length > 0))
        return attributes[0].Description;
    else
        return value.ToString();
}

EnumDisplayForの式関連のコードは、次の場所にある詳細からまとめられています。

ラムダ式に関連して同じ例外について言及している他のいくつかの質問を見つけましたが、それらはすべて、誰かが式ツリーを手動で作成していて、回答の情報が私の場合にどのように適用されるかを理解できなかったコンテキストにありました。

誰かが(a)例外が発生している理由と、(b)それを修正する方法を説明していただければ幸いです。:-)

前もって感謝します。

4

2 に答える 2

1

あなたがやろうとしていることは意味がありません。ラムダ式のみに基づいて (私が見る限り)モデルオブジェクトを見つけようとしています。

より具体的に言えば、enum 側を無視して、Expression<string, int>構築された fromを指定した場合、参照する特定の文字列はありませんが、コードはfrom そのラムダ式text => text.Lengthを構築して実行しようとします。Func<string>それは単に機能しません。

基本的に、提供されているプロジェクションを適用するには、モデル オブジェクトが必要です。そのモデル オブジェクトをどこから取得したいのか(おそらく、HtmlHelper現在無視しているパラメーターですか?) はわかりませんが、投影から取得することはできません。

于 2012-08-01T06:15:53.867 に答える
0

ジョンが言ったように、式からモデル パラメータを抽出しようとしてもうまくいきません。式には単にそのパラメータがないからです。

lambda model => model.Property を作成するとき、メソッド本体をどのようにしたいのかを言っているだけです。そのラムダはデリゲート Func にコンパイルされます。つまり、1 つのパラメーターを必要とし、 value を返すメソッドです

したがって、Func を呼び出すには、 1 つのパラメーター(この場合はモデル パラメーター)を渡す必要があります。

あなたの例では、メソッドは「式」を呼び出して戻り値を取得する前に、どこかからモデルを取得する必要があります。次のように、HtmlHelper パラメーターから現在のモデルを取得できます。

public static MvcHtmlString EnumDisplayFor<TModel, TEnum>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TEnum>> expression)
    {
        //Get the model
        TModel model = htmlHelper.ViewData.Model;

        //Compile expression as Func
        Func<TModel, TEnum> method = expression.Compile();

        //Calling compiled expression return TEnum
        TEnum enumValue = method(model);

        return MvcHtmlString.Create(GetEnumDescription(enumValue));
    }
于 2012-08-01T07:37:46.807 に答える