以强类型方式获取属性的 [DisplayName] 属性

2024-02-17

再会!

我有这样的方法来获得[DisplayName]属性的属性值(直接附加或使用[MetadataType]属性)。我在极少数情况下需要使用它[DisplayName]在控制器代码中。

public static class MetaDataHelper
{
    public static string GetDisplayName(Type dataType, string fieldName)
    {       
        // First look into attributes on a type and it's parents
        DisplayNameAttribute attr;
        attr = (DisplayNameAttribute)dataType.GetProperty(fieldName).GetCustomAttributes(typeof(DisplayNameAttribute), true).SingleOrDefault();

        // Look for [MetadataType] attribute in type hierarchy
        // http://stackoverflow.com/questions/1910532/attribute-isdefined-doesnt-see-attributes-applied-with-metadatatype-class
        if (attr == null)
        {
            MetadataTypeAttribute metadataType = (MetadataTypeAttribute)dataType.GetCustomAttributes(typeof(MetadataTypeAttribute), true).FirstOrDefault();
            if (metadataType != null)
            {
                var property = metadataType.MetadataClassType.GetProperty(fieldName);
                if (property != null)
                {
                    attr = (DisplayNameAttribute)property.GetCustomAttributes(typeof(DisplayNameAttribute), true).SingleOrDefault();
                }
            }
        }
        return (attr != null) ? attr.DisplayName : String.Empty;
    }
}

它有效,但有两个缺点:

  • 它需要字段名称作为字符串
  • 如果我想获得房产的产权,这是行不通的

是否可以使用 lambda 来克服这两个问题,就像我们在 ASP.NET MVC 中遇到的那样:

Html.LabelFor(m => m.Property.Can.Be.Very.Complex.But.Strongly.Typed);  

Update

这是来自的更新和检查版本构建开始解决方案。修改为使用DisplayName属性(您可以修改回Display属性(如果您使用它)。并修复了获取嵌套属性的属性的小错误。

public static string GetDisplayName<TModel>(Expression<Func<TModel, object>> expression)
{
    Type type = typeof(TModel);

    string propertyName = null;
    string[] properties = null;
    IEnumerable<string> propertyList;
    //unless it's a root property the expression NodeType will always be Convert
    switch (expression.Body.NodeType)
    {
        case ExpressionType.Convert:
        case ExpressionType.ConvertChecked:
            var ue = expression.Body as UnaryExpression;
            propertyList = (ue != null ? ue.Operand : null).ToString().Split(".".ToCharArray()).Skip(1); //don't use the root property
            break;
        default:
            propertyList = expression.Body.ToString().Split(".".ToCharArray()).Skip(1);
            break;
    }

    //the propert name is what we're after
    propertyName = propertyList.Last();
    //list of properties - the last property name
    properties = propertyList.Take(propertyList.Count() - 1).ToArray(); //grab all the parent properties

    foreach (string property in properties)
    {
        PropertyInfo propertyInfo = type.GetProperty(property);
        type = propertyInfo.PropertyType;
    }

    DisplayNameAttribute attr;
    attr = (DisplayNameAttribute)type.GetProperty(propertyName).GetCustomAttributes(typeof(DisplayNameAttribute), true).SingleOrDefault();

    // Look for [MetadataType] attribute in type hierarchy
    // http://stackoverflow.com/questions/1910532/attribute-isdefined-doesnt-see-attributes-applied-with-metadatatype-class
    if (attr == null)
    {
        MetadataTypeAttribute metadataType = (MetadataTypeAttribute)type.GetCustomAttributes(typeof(MetadataTypeAttribute), true).FirstOrDefault();
        if (metadataType != null)
        {
            var property = metadataType.MetadataClassType.GetProperty(propertyName);
            if (property != null)
            {
                attr = (DisplayNameAttribute)property.GetCustomAttributes(typeof(DisplayNameAttribute), true).SingleOrDefault();
            }
        }
    }
    return (attr != null) ? attr.DisplayName : String.Empty;
}

有两种方法可以做到这一点:

Models.Test test = new Models.Test();
string DisplayName = test.GetDisplayName(t => t.Name);

string DisplayName = Helpers.GetDisplayName<Models.Test>(t => t.Name);

第一个方法的工作原理是为任何 TModel(所有类型)编写通用扩展方法。这意味着它可以在任何对象上使用,而不仅仅是您的模型。不是很推荐,但很好,因为它的语法简洁。

第二种方法要求您传入模型的类型 - 您已经这样做了,但作为参数。该方法需要通过泛型定义类型,因为 Func 需要它。

以下是您检查的方法。

所有对象的静态扩展方法

public static string GetDisplayName<TModel, TProperty>(this TModel model, Expression<Func<TModel, TProperty>> expression) {

    Type type = typeof(TModel);

    MemberExpression memberExpression = (MemberExpression)expression.Body;
    string propertyName = ((memberExpression.Member is PropertyInfo) ? memberExpression.Member.Name : null);

    // First look into attributes on a type and it's parents
    DisplayAttribute attr;
    attr = (DisplayAttribute)type.GetProperty(propertyName).GetCustomAttributes(typeof(DisplayAttribute), true).SingleOrDefault();

    // Look for [MetadataType] attribute in type hierarchy
    // http://stackoverflow.com/questions/1910532/attribute-isdefined-doesnt-see-attributes-applied-with-metadatatype-class
    if (attr == null) {
        MetadataTypeAttribute metadataType = (MetadataTypeAttribute)type.GetCustomAttributes(typeof(MetadataTypeAttribute), true).FirstOrDefault();
        if (metadataType != null) {
            var property = metadataType.MetadataClassType.GetProperty(propertyName);
            if (property != null) {
                attr = (DisplayAttribute)property.GetCustomAttributes(typeof(DisplayNameAttribute), true).SingleOrDefault();
            }
        }
    }
    return (attr != null) ? attr.Name : String.Empty;


}

类型特定方法的签名 - 与上面相同的代码,只是不同的调用

public static string GetDisplayName<TModel>(Expression<Func<TModel, object>> expression) { }

你不能只使用的原因Something.GetDisplayName(t => t.Name)其本身是因为在 Razor 引擎中,您实际上传递的是一个实例化对象HtmlHelper<TModel>这就是为什么第一个方法需要实例化对象 - 这只是编译器推断哪些类型属于哪个通用名称所必需的。

使用递归属性更新

public static string GetDisplayName<TModel>(Expression<Func<TModel, object>> expression) {

    Type type = typeof(TModel);

    string propertyName = null;
    string[] properties = null;
    IEnumerable<string> propertyList;
    //unless it's a root property the expression NodeType will always be Convert
    switch (expression.Body.NodeType) {
        case ExpressionType.Convert:
        case ExpressionType.ConvertChecked:
            var ue = expression.Body as UnaryExpression;
            propertyList = (ue != null ? ue.Operand : null).ToString().Split(".".ToCharArray()).Skip(1); //don't use the root property
            break;
        default:
            propertyList = expression.Body.ToString().Split(".".ToCharArray()).Skip(1);
            break;
    }

    //the propert name is what we're after
    propertyName = propertyList.Last();
    //list of properties - the last property name
    properties = propertyList.Take(propertyList.Count() - 1).ToArray(); //grab all the parent properties

    Expression expr = null;
    foreach (string property in properties) {
        PropertyInfo propertyInfo = type.GetProperty(property);
        expr = Expression.Property(expr, type.GetProperty(property));
        type = propertyInfo.PropertyType;
    }

    DisplayAttribute attr;
    attr = (DisplayAttribute)type.GetProperty(propertyName).GetCustomAttributes(typeof(DisplayAttribute), true).SingleOrDefault();

    // Look for [MetadataType] attribute in type hierarchy
    // http://stackoverflow.com/questions/1910532/attribute-isdefined-doesnt-see-attributes-applied-with-metadatatype-class
    if (attr == null) {
        MetadataTypeAttribute metadataType = (MetadataTypeAttribute)type.GetCustomAttributes(typeof(MetadataTypeAttribute), true).FirstOrDefault();
        if (metadataType != null) {
            var property = metadataType.MetadataClassType.GetProperty(propertyName);
            if (property != null) {
                attr = (DisplayAttribute)property.GetCustomAttributes(typeof(DisplayNameAttribute), true).SingleOrDefault();
            }
        }
    }
    return (attr != null) ? attr.Name : String.Empty;



}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

以强类型方式获取属性的 [DisplayName] 属性 的相关文章

随机推荐

  • 覆盖 jOOQ 对 UpdatableRecords 的异常处理

    我使用的是 jOOQ v2 6 因为我使用的是 SQL Server 2008 R2 并且 jOOQ v3 1 中存在一个错误 导致代码生成失败 我知道这将在 v3 2 中修复 从手册中 Create a new record BookRe
  • scenebulider 无法打开 fxml 文件

    我正在 JavaFX 中创建一个应用程序 我在打开场景构建器时收到此错误 无法打开 Loggin fxml 打开操作失败 请确保所选文件是有效的 fxml 文档 单击 显示详细信息 它向我显示了此错误 java io IOException
  • 如何将二进制值字符串转换回 char

    Example 注意 我只关心字母 所以位集 000001 是a or A 我有一个string named s与价值 abc 我把每一个char of the string并将其转换为二进制值通过 指某东西的用途bitset e g bi
  • (自定义)RestAuthenticationProcessingFilter 排序的异常

    我尝试将令牌的 Rest 身份验证添加到我的应用程序中 我创建了一个简单的过滤器 不执行任何其他操作来打印消息 public class RestAuthenticationProcessingFilter extends GenericF
  • Justadistraction:标记化没有空格的英语。村上羊人

    我想知道如何you如果删除空格 会用英语 或其他西方语言 对字符串进行标记吗 这个问题的灵感来源于村上小说 羊人 中的角色舞蹈 舞蹈 舞蹈 http en wikipedia org wiki Dance Dance Dance 在小说中
  • 如何将本地数据库复制到heroku?

    我正在开发一个简单的 Rails 基于 activeRecord 应用程序 并且正在本地进行测试 现在是时候转移到网上了 但是 我需要在应用程序的数据库中再次插入所有记录吗 我希望不是 你知道是否可以复制我的整个本地数据库并将其导入到her
  • 透明 ViewController 可以看到下面的父级吗?

    我想以模态方式添加一个具有透明背景的视图控制器 以便可以看到下面的父视图控制器 这是适用于 iPhone 的应用程序 不适用于 iPad 我已经尝试过这个 TextFieldViewController vc self storyboard
  • 计算布尔数组中真(或假)元素的数量?

    假设我有一个充满布尔值的数组 我想知道有多少元素为 true private bool testArray new bool 10 true false true true false true true true false false
  • Firebase .get() 与 .once() - 有什么区别?

    文档here https firebase google com docs database web read and write read data once with get但我不明白 get 和 once 有什么区别 我的理解是 ge
  • iPhone - 将选定的单元格移动到 uitableview 的顶部

    我寻找这个问题 但我不相信我能找到答案 我有一个自定义单元格的表格视图 单击该单元格时 所选单元格会推送包含信息的新单元格 我想知道是否有人知道如何将选定的单元格推到 uitableview 的顶部 或者让它填满整个表格视图 我的 uita
  • 将嵌入的视频资源作为流播放

    EDIT 我改变了我的问题以更好地澄清问题 如何使用字节数组 取自嵌入式资源 播放视频DirectShow Net http directshownet sourceforge net about html图书馆 由于我要阻止用户访问视频文
  • CSS Transform Math - 计算倾斜引起的div高度

    我很难弄清楚如何计算因倾斜而导致的 div 容器的额外高度 我正在屏蔽容器内的图像并使用plugin http christianvarga com 2011 05 jquery resize image to parent contain
  • 使用标识符列表格式化 CREATE TABLE 查询

    我想用 Python 编写一个脚本 从 CSV 创建 PostgreSQL 表 而不是使用psycopg2 copy from我想要更个性化 更灵活的东西 显然 我将读取 CSV 文件的第一行并从中获取列名称列表 然后我想将此列表转换为您在
  • apache tomcat 9.x 无法与 eclipse 和 Java 10.0.1 一起使用

    我已经安装了 apache tomcat 9 0 7在我的 Windows 机器上并具有以下环境配置 回显 JAVA HOME C 程序文件 Java jdk 10 0 1 回显 JRE HOME C 程序文件 Java jre 10 0
  • 我可以让节点在数字字符串中输出逗号而不引入 i18n 吗?

    并不是说添加一个需求有什么大不了的 而是节点文档建议您不需要它 http nodemanual org latest js doc Number html Number toLocaleString from the docs var nu
  • Docker 在 Windows 上添加网络驱动器作为卷

    我正在尝试将网络驱动器安装为卷 这是我正在尝试的命令 docker run v NetworkDirectory Folder data alpine ls data 我在 Windows 上运行此命令 数据目录为空 如何将此网络目录作为卷
  • 关于 MVVM 模式和 GUI 中 XAML 动态加载的混淆

    嗯 这个问题与 MVVM 模式相关 我可以在这个论坛上快速得到答案 所以我想询问并消除我对该模式的困惑 我对 MVVM 方法还很陌生 我欣赏这种模式并了解其背后的原理 也许我没有对这个模式进行太多的研究 这就是为什么会有一些困惑 如果有一种
  • 检测java中的回车键

    我尝试使用扫描仪获取用户输入 如果用户按 Enter 键 则继续执行下一个输入语句 但它一次打印全部 public class MainRDS public static void main String args Scanner in n
  • Spring Boot oauth2:如何设置授权请求中的资源参数以使adfs满意?

    我正在尝试设置一个 Spring Boot 应用程序 该应用程序使用 oauth2 和 Active Directory 联合身份验证服务作为身份验证提供程序 我从这里的教程开始 https spring io guides tutoria
  • 以强类型方式获取属性的 [DisplayName] 属性

    再会 我有这样的方法来获得 DisplayName 属性的属性值 直接附加或使用 MetadataType 属性 我在极少数情况下需要使用它 DisplayName 在控制器代码中 public static class MetaDataH