it-swarm.dev

Какой самый простой способ получить значение свойства из переданного лямбда-выражения в методе расширения для HtmlHelper?

Я пишу грязный метод расширения для HtmlHelper, чтобы я мог сказать что-то вроде HtmlHelper.WysiwygFor (lambda) и отобразить CKEditor.

У меня это работает в настоящее время, но это кажется немного более громоздким, чем я бы предпочел. Я надеюсь, что есть более прямой способ сделать это.

Вот что у меня так далеко.

public static MvcHtmlString WysiwygFor<TModel, TProperty>(this HtmlHelper<TModel> helper, Expression<Func<TModel, TProperty>> expression)
{
    return MvcHtmlString.Create(string.Concat("<textarea class=\"ckeditor\" cols=\"80\" id=\"",
                                        expression.MemberName(), "\" name=\"editor1\" rows=\"10\">", 
                                        GetValue(helper, expression),
                                        "</textarea>"));
}

private static string GetValue<TModel, TProperty>(HtmlHelper<TModel> helper, Expression<Func<TModel, TProperty>> expression)
{
    MemberExpression body = (MemberExpression)expression.Body;
    string propertyName = body.Member.Name;
    TModel model = helper.ViewData.Model;
    string value = typeof(TModel).GetProperty(propertyName).GetValue(model, null).ToString();
    return value;
}

private static string MemberName<T, V>(this Expression<Func<T, V>> expression)
{
    var memberExpression = expression.Body as MemberExpression;
    if (memberExpression == null)
            throw new InvalidOperationException("Expression must be a member expression");

    return memberExpression.Member.Name;
}

Спасибо!

53
Andrew Siemer

Попробуйте вот так:

public static MvcHtmlString Try<TModel, TProperty>(
    this HtmlHelper<TModel> htmlHelper, 
    Expression<Func<TModel, TProperty>> expression
)
{
    var builder = new TagBuilder("textarea");
    builder.AddCssClass("ckeditor");
    builder.MergeAttribute("cols", "80");
    builder.MergeAttribute("name", "editor1");
    builder.MergeAttribute("id", expression.Name); // not sure about the id - verify
    var value = ModelMetadata.FromLambdaExpression(
        expression, htmlHelper.ViewData
    ).Model;
    builder.SetInnerText(value.ToString());
    return MvcHtmlString.Create(builder.ToString());
}
80
Darin Dimitrov
ModelMetadata metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
Object value = metadata.Model;
String name = metadata.PropertyName;
25
Peter Hedberg

Я знаю, что это старый поток, но на тот случай, если кто-то его ищет, способ создания атрибута id/name также:

System.Web.Mvc.ExpressionHelper.GetExpressionText(expression);

Я использую это в своих расширениях и никогда не было проблем с этим. Он также прекрасно работает с вложенными свойствами.

10
Ales Potocnik Hahonina

Самый простой способ - обернуть все это в метод расширения:

public static class ExtensionMethods
{   

    public static object Value<TModel, TProperty>(this Expression<Func<TModel, TProperty>> expression, ViewDataDictionary<TModel> viewData)
    {
        return ModelMetadata.FromLambdaExpression(expression, viewData).Model;
    }  

}

Итак, вызывающий синтаксис:

expression.Value(htmlHelper.ViewData)
5
BigMomma

ASP.NET MVC 3 Futures для этого есть помощник.

2
user571646

Это не отражено ни в ответе Питера, ни в BigMomma, но объединяет оба. Если вы вызываете это из метода контроллера, где у вас нет доступа к экземпляру HtmlHelper, просто создайте метод базового контроллера следующим образом:

public ModelMetadata GetModelMetadata<TModel, TProperty>( TModel model, Expression<Func<TModel, TProperty>> expression )
{
    ViewData.Model = model; //model is null in Controller; you must set it here (or earlier) in order to extract values from the returned ModelMetadata.
    return ModelMetadata.FromLambdaExpression( expression, new ViewDataDictionary<TModel>( ViewData ) );
}

Затем вы можете читать то, что вам нужно, из метаданных модели, как обычно;

var mm = GetModelMetaData( model, m => m.SomeProperty );
string name = mm.PropertyName;
object value = mm.Model;
1
Triynko