ここで、C# の詳細を学ぶために時間を費やしていたので、カスタム属性を調べることにしました。Enum に割り当てると非常に役立つことがわかりました。
そのため、Enum がそのような属性を非常に簡単に取得できるように、次のようないくつかの拡張メソッドを作成しましたDemoEnum.Value1.GetAttribute<EnumNote>()
。
しばらくして、すべてのカスタム属性が、割り当てられた Enum への参照を持っていればいいと思いました。私が考えた悪い考えではないので、私はこれを進めました:
最初に、もちろんクラスEnumAttribute
を継承するカスタム属性の基本クラスを作成しました。System.Attribute
この基本クラスは最初のスケッチに過ぎず、受信する Enum のすべてのタイプに特に適合するように拡張するつもりですが、今のところこれで十分です。
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 のコード分析とコンパイラは何も報告しません。
しかし、次のように 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
}
コンパイルしようとすると、VS は各EnumNote
コンストラクターの最初の引数について次のように報告します。
属性引数は、定数式、typeof 式、または属性パラメーター タイプの配列作成式である必要があります。
基本的に、DemoEnum.Value1 と DemoEnum.Value2 は定数値を保持しないと言っています。私はそうですよね?
いずれにせよ、この Enum はハードコードされているため、このエラーには困惑しています。ご覧のとおり、既に自分で行っているため、コンパイラは各列挙型に値を割り当てる必要さえありません。
もちろん、これは私が欠けているものや誤解しているもの、そしてそれぞれEnumNote
が割り当てられている列挙型への参照を提供するという目標を達成するにはどうすればよいのでしょうか?
ありがとうございました。
アップデート:
それを再確認した後、VSが列挙型が定数式ではないことを報告する理由を理解しました。それは、私が何かを参照しているためDemoEnum.Value1
ですDemoEnum
。Value1
場所。しかし、私のこのアイデアをどのように進めるかについてのアイデアはありません。
更新 2:
コンパイル後に列挙型をリファクタリングすることについてはどうですか。列挙型に適用できない場合を除き(リファクタリングが列挙型で機能するかどうか思い出せません)、おそらくエラーは発生しないはずですが、適用できる場合はおそらく面倒で遅くなりますよね?
更新 3:属性に割り当てられた Enum への参照が含まれている理由。
実際には非常に単純な理由です。次のシナリオを想定してください。カスタム属性のコレクションがあり、何らかの理由で、ある時点で、特定の属性がどの Enum に属しているかを知る必要があるとします。
それを判断するために新しいコードを書く代わりに、属性自体で特定の Enum を参照するだけではどうですか? これは消費されるメモリのわずかな妥協ですが、将来的には、各属性 (または 1 つだけ) の指定された Enum を決定するために必要なプロセスを実行するための貴重な時間を節約できます。