You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何为SystemParameterItemAttribute的Description属性传递动态参数?

关于给SystemParameterItemAttribute的Description传递动态值的解决方案

我来帮你梳理下这个问题——在C#里,特性的构造参数或者属性赋值必须是编译时常量,所以你直接用public static string descriptionC = getDescription();这种动态计算的值是没法直接传给Description属性的,编译器会直接报错。不过有几种变通的方案可以实现类似的动态描述效果,下面给你详细说:

方案1:用资源文件+资源键(最推荐,适合多语言/配置化场景)

这个思路是把动态的描述文本放到资源文件里,特性里只存对应的资源键,等运行时读取特性的时候,再根据键去资源文件里拿最新的描述内容。

步骤:

  1. 先把你的描述文本添加到项目的资源文件(比如Resources.resx)里,键设为Description_C,值设为你动态要获取的内容(或者后续可以通过修改资源文件更新)。
  2. 修改特性的使用方式,把Description设为资源键:
[SystemParameterItemAttribute(Code = "C", Description = "Description_C", OrderBy = 3, UIResourceCd = "EventType_CallEvent")]
public const string ClassToken = "C";
  1. 读取特性的时候,通过资源管理器获取动态描述:
// 获取特性实例
var attr = typeof(YourClassName).GetField(nameof(YourClassName.ClassToken))
                                .GetCustomAttribute<SystemParameterItemAttribute>();
// 根据资源键获取动态描述
var dynamicDescription = Resources.ResourceManager.GetString(attr.Description);

这种方式的好处是支持多语言,而且不需要重新编译代码,只要修改资源文件就能更新描述,非常灵活。

方案2:给特性添加动态描述提供器(适合复杂动态逻辑场景)

如果你的描述需要更复杂的动态计算(比如从数据库读取、根据上下文生成),可以给特性加一个“描述提供器”的类型参数,运行时通过这个类型来生成描述。

步骤:

  1. 先定义一个描述提供器的接口:
public interface IDescriptionProvider
{
    string GetDescription();
}
  1. 修改你的自定义特性类,添加一个DescriptionProviderType属性,再写一个方法来获取动态描述:
public class SystemParameterItemAttribute : Attribute 
{
    public string Code { get; set; }
    public string Description { get; set; } // 保留原属性做兼容
    public Type DescriptionProviderType { get; set; } // 新增的提供器类型
    public short OrderBy { get; set; }
    public string Attributes { get; set; }
    public string UIResourceCd { get; set; }
    public KeywordTarget KeywordTarget = KeywordTarget.Default;

    // 运行时获取动态描述的方法
    public string GetDynamicDescription()
    {
        if (DescriptionProviderType != null && typeof(IDescriptionProvider).IsAssignableFrom(DescriptionProviderType))
        {
            // 实例化提供器并获取描述
            var provider = (IDescriptionProvider)Activator.CreateInstance(DescriptionProviderType);
            return provider.GetDescription();
        }
        // 如果没有指定提供器,就返回原有的硬编码描述
        return Description;
    }
}
  1. 实现一个具体的描述提供器,把你的动态获取逻辑写进去:
public class CallEventDescriptionProvider : IDescriptionProvider
{
    public string GetDescription()
    {
        // 这里写你的动态获取逻辑,比如调用getDescription()
        return getDescription();
    }
}
  1. 使用特性的时候指定提供器类型:
[SystemParameterItemAttribute(Code = "C", DescriptionProviderType = typeof(CallEventDescriptionProvider), OrderBy = 3, UIResourceCd = "EventType_CallEvent")]
public const string ClassToken = "C";
  1. 读取特性的时候调用GetDynamicDescription()
var attr = typeof(YourClassName).GetField(nameof(YourClassName.ClassToken))
                                .GetCustomAttribute<SystemParameterItemAttribute>();
var dynamicDescription = attr.GetDynamicDescription();

方案3:反射读取静态字段(不推荐,仅作妥协方案)

如果你一定要用静态字段的方式,那只能在读取特性之后,手动去反射读取对应的静态字段的值——因为特性本身没法直接引用非编译时常量的静态字段。

示例:

// 定义动态描述的静态字段
public static string descriptionC = getDescription();

// 特性里Description可以留空或者写个占位符
[SystemParameterItemAttribute(Code = "C", Description = "", OrderBy = 3, UIResourceCd = "EventType_CallEvent")]
public const string ClassToken = "C";

读取的时候:

var field = typeof(YourClassName).GetField(nameof(YourClassName.ClassToken));
var attr = field.GetCustomAttribute<SystemParameterItemAttribute>();
// 手动反射读取静态字段的值
var dynamicDescription = (string)typeof(YourClassName).GetField(nameof(YourClassName.descriptionC)).GetValue(null);

这种方式不够优雅,而且静态字段的生命周期、线程安全等问题可能会带来隐患,所以尽量不用。


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

火山引擎 最新活动