You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多
文档控制台
免费开始使用

C# DataAnnotations:带显示名称的属性模型及相关内容的翻译与技术改写

C# 数据注解:基于字符串列表设置模型属性的显示名称

问题描述

我目前有一个继承自BaseViewData的C#模型类TVSystemViewData,每个属性都通过[Display]特性硬编码了显示名称。同时我手头有一个包含对应属性显示名称的字符串列表,想请教如何通过这个列表来设置模型属性的Display(Name)值,替代当前逐个硬写的方式?

我的模型代码如下:

public class TVSystemViewData : BaseViewData 
{ 
    [Display(Name = "AccountId", Description = "")] 
    public String AccountId { get; set; } 

    [Display(Name = "AllocatedManagedMemory", Description = "")] 
    public String AllocatedManagedMemory { get; set; } 

    [Display(Name = "AllocatedPhysicalMemory", Description = "")] 
    public String AllocatedPhysicalMemory { get; set; } 

    [Display(Name = "AudioMute", Description = "")] 
    public String AudioMute { get; set; } 
    // 其他属性省略...
}

解决方案

嘿,这个需求我之前做项目时也碰到过,刚好有几个实用的方案可以分享给你,你可以根据自己的场景来选:

方案一:反射动态修改特性值

DisplayAttributeName属性是可写的,所以我们可以通过反射遍历模型的所有属性,找到对应的Display特性,再从字符串列表里匹配对应名称赋值。这种方式是运行时动态修改,只会影响当前应用域内的特性实例,适合需要根据不同环境/配置切换显示名称的场景。

示例代码:

// 假设你的字符串列表用字典存储,键是属性名,值是目标显示名称
var displayNameMap = new Dictionary<string, string>
{
    {"AccountId", "账户ID"},
    {"AllocatedManagedMemory", "已分配托管内存"},
    {"AllocatedPhysicalMemory", "已分配物理内存"},
    {"AudioMute", "音频静音状态"}
    // 其他属性的对应名称
};

// 获取模型类型
var modelType = typeof(TVSystemViewData);
foreach (var property in modelType.GetProperties())
{
    // 获取属性上的Display特性实例
    var displayAttr = property.GetCustomAttribute<DisplayAttribute>();
    if (displayAttr != null && displayNameMap.TryGetValue(property.Name, out var newDisplayName))
    {
        // 替换显示名称
        displayAttr.Name = newDisplayName;
    }
}

方案二:自定义动态显示特性

如果需要更灵活的全局控制,可以自定义一个继承自DisplayAttribute的特性,让它支持从外部数据源读取显示名称。这种方式扩展性更强,适合需要统一管理显示名称的场景。

首先定义自定义特性:

public class DynamicDisplayAttribute : DisplayAttribute
{
    private readonly string _propertyKey;
    private static Dictionary<string, string> _displayNameStore;

    // 静态初始化方法,用来传入你的显示名称列表
    public static void Initialize(Dictionary<string, string> displayNameMap)
    {
        _displayNameStore = displayNameMap;
    }

    public DynamicDisplayAttribute(string propertyKey)
    {
        _propertyKey = propertyKey;
    }

    public override string Name
    {
        get
        {
            // 如果找到对应名称就返回,否则返回默认键
            if (_displayNameStore != null && _displayNameStore.TryGetValue(_propertyKey, out var displayName))
            {
                return displayName;
            }
            return _propertyKey;
        }
    }
}

然后修改模型类,替换原有[Display]特性:

public class TVSystemViewData : BaseViewData 
{ 
    [DynamicDisplay("AccountId")] 
    public String AccountId { get; set; } 

    [DynamicDisplay("AllocatedManagedMemory")] 
    public String AllocatedManagedMemory { get; set; } 

    [DynamicDisplay("AllocatedPhysicalMemory")] 
    public String AllocatedPhysicalMemory { get; set; } 

    [DynamicDisplay("AudioMute")] 
    public String AudioMute { get; set; } 
    // 其他属性...
}

最后在应用启动时初始化特性:

var displayNameMap = new Dictionary<string, string>
{
    {"AccountId", "账户ID"},
    // 其他对应项
};
DynamicDisplayAttribute.Initialize(displayNameMap);

方案三:使用资源文件(官方推荐)

如果你的显示名称需要支持多语言或者集中管理,官方最推荐的方式是使用资源文件。这种方式不仅能轻松修改显示名称,还天然支持多语言切换,完全符合.NET的设计规范。

步骤如下:

  1. 新建一个资源文件(比如ModelResources.resx),添加键值对:
    • 键:AccountId,值:账户ID
    • 键:AllocatedManagedMemory,值:已分配托管内存
    • 其他属性的键值对以此类推
  2. 修改模型的Display特性,指定资源类型和资源键:
public class TVSystemViewData : BaseViewData 
{ 
    [Display(Name = nameof(ModelResources.AccountId), ResourceType = typeof(ModelResources))] 
    public String AccountId { get; set; } 

    [Display(Name = nameof(ModelResources.AllocatedManagedMemory), ResourceType = typeof(ModelResources))] 
    public String AllocatedManagedMemory { get; set; } 
    // 其他属性...
}

之后只要修改资源文件的内容,就能动态更新模型属性的显示名称,非常方便。


内容的提问来源于stack exchange,提问作者Fabio Santos

火山引擎 最新活动