在这里,我花了一些时间来了解有关 C# 的更多信息,因此我决定研究自定义属性,我发现它们在分配给枚举时非常有用。
因此,我为 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));
}
}
}
现在每个自定义属性都必须从此类继承 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;
}
}
到目前为止,一切都很好,Visual Studio 代码分析和编译器没有报告任何内容。
但是当我定义一个枚举时,例如:
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
}
当我尝试编译它时,VS 报告每个 EnumNote
的第一个参数构造函数如下:
An attribute argument must be a constant expression, typeof expression or array creation expression of an attribute parameter type.
基本上是说 DemoEnum.Value1 和 DemoEnum.Value2 不保存常量值。我说得对吗?
无论如何,这个错误让我感到困惑,因为这个枚举是硬编码的,正如你所看到的,编译器甚至不必为每个枚举分配一个值,因为我自己已经这样做了。
这当然带来了一个问题,我遗漏或误解了什么,以及我应该如何实现提供对枚举的引用的目标,其中每个 EnumNote
被分配给?
谢谢。
更新:
重新审视后,我明白为什么 VS 报告枚举不是常量表达式,那是因为我指的是:DemoEnum.Value1
在某一点上,他还没有完成DemoEnum
给Value1
下定义首先。然而,不知道如何继续我的这个想法。
更新2:
在编译后重构枚举怎么样,它可能不会给出任何错误,除非它不能应用于枚举(不记得重构是否适用于枚举),但如果可以的话应用它可能会很麻烦并且很慢,对吗?
更新 3:属性包含对其分配到的枚举的引用的原因。
实际上这是一个非常简单的原因,假设以下场景。假设我有一个自定义属性的集合,出于某种原因,我需要在某些时候知道给定属性属于哪个枚举。
为什么不简单地在属性本身中引用给定的枚举,而不是编写新的代码来确定这一点?这是对内存消耗的一个微小妥协,而在未来,它将节省运行任何所需进程来确定每个属性(甚至只是一个属性)的给定枚举的宝贵时间。
最佳答案
An attribute argument must be a constant expression, typeof expression or array creation expression of an attribute parameter type.
基本上是说 DemoEnum.Value1 和 DemoEnum.Value2 不保存常量值。我说得对吗?
block 引用>不完全是。
实际问题似乎是
Enum
的使用。虽然它的功能主要是作为概念类层次结构的基类,但它的处理似乎有一些技巧。出于所有意图和目的,它是一个运行时伪类,而不是一个真正的类。属性在编译时处理。没有在运行时用属性修饰对象的机制。因此,引入一些运行时技巧来处理
Enum
伪类似乎与属性功能的方式不兼容。试试这个:
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 }
编译良好(VS2010 中的 .NET 4.0),并且 Attribute 属性设置正确。我可以检查属性的
Obj
属性并获取我期望的数据类型。<罢工><意见>
也就是说……不太确定这会有多大用处。您已经必须拥有要装饰的值的实例,因此将值本身存储在属性中似乎有点多余。
意见>罢工>编辑:可能的解决方案...
在让这个渗透一点之后(我在 sleep 时做了一些最好的思考),我意识到问题出在实际的参数类型上(如 this question 的答案中所述)我们可以通过一些拳击来解决这个问题。
public class EnumTest : Attribute { public Enum enum; public EnumTest(object e) { enum = e as Enum; } }
通过这种方式,您可以从对象初始化属性,C# 和 CLR 似乎可以轻松完成此操作。您失去了使用枚举初始化时固有的类型检查,但我相信它实现了既定的目标。
关于c# - 枚举作为其自己的自定义属性构造函数的参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14867793/