【问题标题】:Unable to get custom attributes for model properties other than string无法获取除字符串以外的模型属性的自定义属性
【发布时间】:2011-11-15 16:03:32
【问题描述】:

我有一个这样的模型(为相关性而简化):

public abstract class TitleCreateModel : ICreateModel
{
    [Required]
    [MaxLength(400)]
    public string TitleName { get; set; }

    [Required]
    [MaxLength(4)]
    public DateTime ReleaseDate { get; set; }

    [Required]
    [MaxLength(5)]
    public string Test { get; set; }

    [Required]
    [MaxLength(2)]
    public int Wut { get; set; }
}

然后我有一个自定义 HTML 帮助类和一个表达式扩展类(都是未删节的):

public class InputHelper
{
    public static HtmlString Input<T>(Expression<Func<T, Object>> expression, string id, string label)
    {
        var req = expression.GetAttribute<T, Object, RequiredAttribute>();
        var max = expression.GetAttribute<T, Object, MaxLengthAttribute>();
        var required = "";
        var maxlength = "";
        if(req!=null)
        {
            required = "req";
        }
        if(max!=null)
        {
            maxlength = "maxlength='" + max.Length + "'";
        }
        return new HtmlString("<div class=\"clearfix\"><label for=\""+id+"\">" + label + "</label>" +
                              "<div class=\"input\"><input id=\""+id+"\" class=\""+required+"\" type=\"text\" "+maxlength+"/></div></div>");
    }
}

public static class ExpressionExtensions
{
    public static TAttribute GetAttribute<TIn, TOut, TAttribute>(this Expression<Func<TIn, TOut>> expression) where TAttribute : Attribute
    {
        var memberExpression = expression.Body as MemberExpression;
        if (memberExpression != null)
        {
            var attributes = memberExpression.Member.GetCustomAttributes(typeof(TAttribute), true);
            return attributes.Length > 0 ? attributes[0] as TAttribute : null;
        }
        return null;
    }
}

在我的 Razor 脚本中,我进行了以下调用:

@(InputHelper.Input<string>(m => Model.Title.TitleName, "titlename", "Title Name"))

@(InputHelper.Input<string>(m => Model.Title.Test, "testfield", "Test Field"))

@(InputHelper.Input<int>(m => Model.Title.Wut, "tester", "Test Field 2"))

@(InputHelper.Input<DateTime>(m => Model.Title.ReleaseDate, "release_year", "Release Year"))

由于某种原因,GetAttribute 方法只查找 TitleName 和 Test 的属性,这两个属性都是 TitleCreateModel 的字符串属性。找不到 ReleaseDate 和 Wut 的属性,我也不知道为什么。

【问题讨论】:

    标签: asp.net asp.net-mvc-3


    【解决方案1】:

    Input方法中使用的表达式修改为Expression&lt;Func&lt;T, TOut&gt;&gt; expression

    public static HtmlString Input<T, TOut>(Expression<Func<T, TOut>> expression, string id, string label)
    {
        var req = expression.GetAttribute<T, TOut, RequiredAttribute>();
        var max = expression.GetAttribute<T, TOut, MaxLengthAttribute>();
        var required = "";
        var maxlength = "";
        if(req!=null)
        {
            required = "req";
        }
        if(max!=null)
        {
            maxlength = "maxlength='" + max.Length + "'";
        }
        return new HtmlString("<div class=\"clearfix\"><label for=\""+id+"\">" + label + "</label>" +
                              "<div class=\"input\"><input id=\""+id+"\" class=\""+required+"\" type=\"text\" "+maxlength+"/></div></div>");
    }
    

    【讨论】:

    • 这行得通,但我不知道为什么会这样。有没有关于表达式的好资源可以链接到?
    【解决方案2】:

    使用 DateTime 和 int,Expression 不是 MemberExpression 类型,因为我相信是装箱,所以这一行:

    var memberExpression = expression.Body as MemberExpression;
    

    将返回一个空值。

    关于这个主题here 有一个很好的问答,它只涉及按照指定将您的Func 泛型修改为Eranga。

    【讨论】:

    • 那么为什么当我在 Func 中泛化 TResult 时它会起作用?我对表达式完全陌生,这一切对我来说似乎都是黑魔法。
    • 因为您声明该函数必须返回泛型 Object 类型,这将需要对值类型进行额外操作以将类型装箱为 Object(请参阅boxing documentation),因此表达式具有包括那个额外的步骤。如果您使用泛型类型,则无需将其显式返回为 Object 并且删除该步骤。
    猜你喜欢
    • 2015-01-19
    • 2011-03-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-20
    • 2012-10-13
    相关资源
    最近更新 更多