枚举作为它自己的自定义属性构造函数的参数

Fáb*_*nes 4 c# enums custom-attributes

在这里,我花了一些时间来了解有关C#的更多信息,因此我决定研究自定义属性,并且在分配给Enums时发现它们非常有用.

所以我为Enum编写了一些扩展方法来很容易地检索这些属性,比如:DemoEnum.Value1.GetAttribute<EnumNote>().

过了一会儿,我想如果每个自定义属性都有对它所分配的枚举的引用,这将是一个不错的主意.我想是个不错的主意,所以我继续这样做:

首先,我EnumAttribute为自定义属性编写了一个基System.Attribute类,当然继承了该类.这个基类只是第一个草图,我打算将它扩展为特别适合它将接收的每种类型的枚举,但到目前为止这已足够.

public class EnumAttribute : Attribute
{
    public EnumInfo Enum { get; internal set; }

    public EnumAttribute(Enum Enum)
    {
        this.Enum = new EnumInfo(Enum);
    }

    public class EnumInfo
    {
        private Enum _value;
        private Type _type;
        private FieldInfo _details;

        public Enum Value { get { return _value; } }
        public Type Type { get { return _type; } }
        public FieldInfo Details { get { return _details; } }

        public EnumInfo(Enum value)
        {
        _value = value;
        _type = value.GetType();
        _details = _type.GetField(System.Enum.GetName(_type, value));
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

现在每个自定义属性都必须从此类继承EnumAttribute.结果例如在类中EnumNote:

public class EnumNote : EnumAttribute
{
    private string _note = string.Empty;

    public string Note { get { return _note; } }

    public EnumNote(Enum Enum, string Note)
        : base(Enum)
    {
        _note = Note;
    }
}
Run Code Online (Sandbox Code Playgroud)

到目前为止一切都很好,Visual Studio代码分析和编译器报告都没有.

但是当我定义一个Enum时,例如:

public enum DemoEnum
{
    [EnumNote(DemoEnum.Value1, "Some special note about Enum Value1.")]
    Value1 = 1,

    [EnumNote(DemoEnum.Value2, "Some other special note about Enum Value2.")]
    Value2 = 2
}
Run Code Online (Sandbox Code Playgroud)

当我尝试编译它时,VS报告每个EnumNote构造函数的第一个参数如下:

属性参数必须是属性参数类型的常量表达式,typeof表达式或数组创建表达式.

基本上是说DemoEnum.Value1和DemoEnum.Value2不保持常量值.我是对的?

无论如何,这个错误让我感到困惑,因为这个Enum是硬编码的,正如你所看到的,编译器甚至不必为每个枚举分配一个值,因为我已经自己做了.

这当然会带来一个问题,我缺少什么或误解,以及我应该如何实现提供每个EnumNote被分配到的枚举的引用的目标?

谢谢.

更新:

重新审视之后,我理解为什么VS报告枚举不是一个常量表达式,那是因为我指的是某些东西:DemoEnum.Value1在某一点上,他还没有完成对第DemoEnum一个定义的定义Value1地点.但是没有关于如何继续我的这个想法的想法.

更新2:

如果在编译之后重构Enum,那么它可能不应该给出任何错误,除非它不能应用于枚举(不记得重构是否适用于枚举),但如果它可以应用它将会做起来可能很麻烦,慢一点吧?

更新3:属性包含对它们被分配到的枚举的引用的原因.

实际上,这是一个非常简单的原因,假设以下情况.假设我有一组自定义属性,由于某种原因,我需要在某个时候知道给定属性属于哪个枚举.

而不是编写新代码来确定,为什么不简单地在属性本身中引用给定的枚举?这是对内存消耗的微小折衷,而将来它可以节省运行任何所需过程的宝贵时间,以确定每个属性的给定枚举(甚至只有一个).

Cor*_*rey 10

属性参数必须是属性参数类型的常量表达式,typeof表达式或数组创建表达式.

基本上是说DemoEnum.Value1和DemoEnum.Value2不保持常量值.我是对的?

不完全的.

实际问题似乎是使用Enum.虽然它主要用作概念类层次结构的基类,但它似乎是用一些技巧来处理的.对于所有意图和目的,它是一个运行时伪类而不是真正的类.

属性在编译时处理.没有在运行时使用属性装饰对象的机制.因此,引入一些运行时技巧来处理Enum伪类似乎与Attributes函数的方式不兼容.

试试这个:

public class EnumTest : Attribute
{
    public int Value;
    public object Obj;
}

public enum DemoEnum
{
    [EnumTest(Value = (int)DemoEnum.Value1, Obj = DemoEnum.Value1)]
    Value1 = 1,

    [EnumTest(Value = (int)DemoEnum.Value2)]
    Value2 = 2
}
Run Code Online (Sandbox Code Playgroud)

这编译得很好(VS2010中的.NET 4.0),并且属性属性设置正确.我可以检查Obj属性的属性并获得我期望的数据类型.

<意见>
那说......不太确定这会有多大用处.您必须拥有正在装饰的值的实例,因此将值本身存储在属性中似乎有点多余.
</意见>

编辑:可能的解决方案......

让这个渗透了一下(我在睡着的时候做了一些最好的思考),我已经意识到,由于问题在于实际的参数类型(如本问题的答案所述),我们可以解决一下这个问题拳击

public class EnumTest : Attribute
{
    public Enum enum;

    public EnumTest(object e)
    {
        enum = e as Enum;
    }
}
Run Code Online (Sandbox Code Playgroud)

这样你就可以从一个对象初始化属性,C#和CLR看起来很舒服.您在使用Enum初始化时失去了固有的类型检查,但我相信它达到了既定目标.