Enums的自定义属性是否危险?

时间:2012-03-07 16:43:41

标签: c# attributes enums

我正在构建一个大量使用Enum s用于自定义数据的应用程序。实质上,对象存储在数据库中,具有大约28个单独的属性。每个属性都是一个双字符字段,从SQL直接转换为Enum

不幸的是,我还需要将这些值转换为两个不同的人类可读值。一个用于数据表上的图例,另一个用于CSS类,用于在Web应用程序前端设置图像样式。

为此,我设置了两个自定义属性,并在必要时将其应用于Enum。例如:

自定义属性界面

public interface IAttribute<T>
{
    T Value { get; }
}

自定义属性示例

public sealed class AbbreviationAttribute: Attribute, IAttribute<string>
{
    private readonly string value;

    public AbbreviationAttribute(string value)
    {
        this.value = value;
    }

    public string Value
    {
        get { return this.value; }
    }
}

Enum

中检索自定义属性的方法
public static R GetAttributeValue<T, R>(IConvertible @enum)
{
    R attributeValue = default(R);

    if (@enum != null)
    {
        FieldInfo fi = @enum.GetType().GetField(@enum.ToString());

        if (fi != null)
        {
            T[] attributes = fi.GetCustomAttributes(typeof(T), false) as T[];

            if (attributes != null && attributes.Length > 0)
            {
                IAttribute<R> attribute = attributes[0] as IAttribute<R>;

                if (attribute != null)
                {
                    attributeValue = attribute.Value;
                }
            }
        }
    }

    return attributeValue;
}

示例Enum使用此模式

public enum Download
{
    [Abbreviation("check")]
    [Description("Certified")]
    C = 1,

    [Abbreviation("no-formal")]
    [Description("No formal certification")]
    NF = 2,

    [Abbreviation("cert-prob")]
    [Description("Certified with potential problems")]
    CP = 3
}

AbbreviationDescription都是实现IAttribute<T>的自定义属性。我的实际Enum有11个可能的值,正如我之前提到的,它在我的自定义对象中的28个单独属性中使用。使用自定义属性似乎是来回映射此信息的最佳方式。

现在提出问题,这是实现此目的的最佳方法吗?我将Enum值(“C”,“NF”或“CP”存储在上面的代码段中)在数据库中,但我需要在我的代码中的缩写和描述的值。另外,我怀疑这将是我需要的最后一组自定义属性。

在我继续推进这种模式之前... 这是正确的做事方式吗?我宁愿用这种方法修复潜在的问题,而不是后来追踪和重构。

3 个答案:

答案 0 :(得分:15)

这与我使用的方法相同。一个缺点是序列化。自定义属性值不会序列化。

我喜欢数据库方法的自定义属性方法,因为它将属性数据绑定到枚举,而不必使用查找表或类等。

答案 1 :(得分:2)

我可能会为这样的东西构建一个哈希表和一个特殊类型。你可能因为某种原因已经放弃了这个想法,但这就是我不知道你的应用程序的具体细节。

class SpecialType {
  // include the fields and all attributes that you need to reference, ToString method for debugging, and any serialization you need
  public string foo { get; set; }
  public string bar { get; set; }
  public ToString() { return "SpecialType with foo '" + foo + "' and bar '" + bar + "'"; }
}

Dictionary<int, SpecialType> myDict = new Dictionary<int, SpecialType> {
   { 1, new SpecialType { foo = "XA1B2", bar = "XC3D4" } },
   { 2, new SpecialType { foo = "ZA1B2", bar = "ZC3D4" } },
   { 3, new SpecialType { foo = "YA1B2", bar = "YC3D4" } },
}

然后我可以轻松地在我的其他类中保持内存以节省内存,通过检查字典键中的存在来查明特定值是否有效,所有爵士乐。如果您最终要使用WPF或读/写磁盘,那么进行数据绑定可能要容易得多。

答案 2 :(得分:1)

你可以改变数据库吗?我认为最好的选择是创建一个表(或表)来容纳枚举的可能值和主要对象的外键(而不是使用char代码 - 这使得更容易拉动它并使数据库规范化) 。为表格提供AbbreviationDescription列,然后将其拉入并按键引用它们,如果查找速度很慢,则将其缓存。

关于这些属性的一个危险是,如果这些字符串中的任何一个必须改变,那么它就是对应用程序的完全重新部署。如果您将它们设为数据库值,则可以使用简单的UPDATE更改它们。