私は現在、組み込みのヘルパー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の式関連のコードは、次の場所にある詳細からまとめられています。
- http://blogs.msdn.com/b/csharpfaq/archive/2010/03/11/how-can-i-get-objects-and-property-values-from-expression-trees.aspx
- https://stackoverflow.com/a/672212
ラムダ式に関連して同じ例外について言及している他のいくつかの質問を見つけましたが、それらはすべて、誰かが式ツリーを手動で作成していて、回答の情報が私の場合にどのように適用されるかを理解できなかったコンテキストにありました。
誰かが(a)例外が発生している理由と、(b)それを修正する方法を説明していただければ幸いです。:-)
前もって感謝します。