.NET の属性とは何ですか?
-
09-06-2019 - |
質問
.NET の属性とは何ですか? 何に役立ちますか? 独自の属性を作成するにはどうすればよいですか?
解決
メタデータ。オブジェクト/メソッド/プロパティに関するデータ。
たとえば、次のような属性を宣言するとします。DisplayOrder を使用すると、プロパティが UI に表示される順序を簡単に制御できます。次に、それをクラスに追加し、属性を抽出して UI 要素を適切に順序付けるいくつかの GUI コンポーネントを作成できます。
public class DisplayWrapper
{
private UnderlyingClass underlyingObject;
public DisplayWrapper(UnderlyingClass u)
{
underlyingObject = u;
}
[DisplayOrder(1)]
public int SomeInt
{
get
{
return underlyingObject .SomeInt;
}
}
[DisplayOrder(2)]
public DateTime SomeDate
{
get
{
return underlyingObject .SomeDate;
}
}
}
これにより、カスタム GUI コンポーネントを操作するときに、SomeInt が常に SomeDate の前に表示されるようになります。
ただし、これらは直接コーディング環境の外で最も一般的に使用されることがわかります。たとえば、Windows デザイナーはこれらを広範囲に使用するため、カスタム メイドのオブジェクトの処理方法を知っています。BrowsableAttribute を次のように使用します。
[Browsable(false)]
public SomeCustomType DontShowThisInTheDesigner
{
get{/*do something*/}
}
たとえば、設計時にこれを [プロパティ] ウィンドウの使用可能なプロパティにリストしないように設計者に指示します。
あなた できた また、コード生成、プリコンパイル操作 (Post-Sharp など)、または Reflection.Emit などの実行時操作にも使用します。たとえば、コードが行うすべての呼び出しを透過的にラップして時間を計測する、プロファイリング用のコードを少し書くことができます。特定のメソッドに配置する属性を介してタイミングを「オプトアウト」できます。
public void SomeProfilingMethod(MethodInfo targetMethod, object target, params object[] args)
{
bool time = true;
foreach (Attribute a in target.GetCustomAttributes())
{
if (a.GetType() is NoTimingAttribute)
{
time = false;
break;
}
}
if (time)
{
StopWatch stopWatch = new StopWatch();
stopWatch.Start();
targetMethod.Invoke(target, args);
stopWatch.Stop();
HandleTimingOutput(targetMethod, stopWatch.Duration);
}
else
{
targetMethod.Invoke(target, args);
}
}
宣言は簡単で、Attributeを継承したクラスを作成するだけです。
public class DisplayOrderAttribute : Attribute
{
private int order;
public DisplayOrderAttribute(int order)
{
this.order = order;
}
public int Order
{
get { return order; }
}
}
また、属性を使用する場合は、接尾辞「attribute」を省略しても、コンパイラーがそれを追加することに注意してください。
注記: 属性はそれ自体では何も行いません。属性を使用する他のコードが必要です。そのコードは自動的に書かれている場合もありますが、自分で書かなければならない場合もあります。たとえば、C# コンパイラは、いくつかのフレームワークを考慮し、フレームワークが使用するフレームワーク (例:NUnit は、アセンブリの読み込み時にクラスで [TestFixture] を検索し、テスト メソッドで [Test] を検索します)。
したがって、独自のカスタム属性を作成する場合は、コードの動作にはまったく影響しないことに注意してください。(リフレクション経由で) 属性をチェックし、それに基づいて動作する他の部分を作成する必要があります。
他のヒント
多くの人が答えていますが、これについてはまだ誰も言及していません...
属性はリフレクションで多用されます。反映はすでにかなり遅いです。
それは とても価値のある カスタム属性を次のものとしてマークする sealed
クラスを使用して実行時のパフォーマンスを向上させます。
また、そのような属性をどこに使用するのが適切かを検討し、属性 (!) を使用してこれを示すように属性を設定することもお勧めします。 AttributeUsage
. 。使用可能な属性の使用法のリストを見て驚くかもしれません。
- 組み立て
- モジュール
- クラス
- 構造体
- 列挙型
- コンストラクタ
- 方法
- 財産
- 分野
- イベント
- インターフェース
- パラメータ
- 代表者
- 戻り値
- 汎用パラメータ
- 全て
AttributeUsage 属性が AttributeUsage 属性の署名の一部であることも優れています。おっと、循環依存関係についてです。
[AttributeUsageAttribute(AttributeTargets.Class, Inherited = true)]
public sealed class AttributeUsageAttribute : Attribute
属性はクラスにタグを付けるためのメタデータの一種です。これは、たとえばツールバーからコントロールを非表示にするために WinForms でよく使用されますが、独自のアプリケーションに実装して、さまざまなクラスのインスタンスが特定の方法で動作できるようにすることもできます。
まず属性を作成します。
[AttributeUsage(AttributeTargets.Class, AllowMultiple=false, Inherited=true)]
public class SortOrderAttribute : Attribute
{
public int SortOrder { get; set; }
public SortOrderAttribute(int sortOrder)
{
this.SortOrder = sortOrder;
}
}
すべての属性クラスが有効であるためには、接尾辞「Attribute」が必要です。
これが完了したら、その属性を使用するクラスを作成します。
[SortOrder(23)]
public class MyClass
{
public MyClass()
{
}
}
これで、特定のクラスを確認できるようになりました。 SortOrderAttribute
(存在する場合) 次の手順を実行します。
public class MyInvestigatorClass
{
public void InvestigateTheAttribute()
{
// Get the type object for the class that is using
// the attribute.
Type type = typeof(MyClass);
// Get all custom attributes for the type.
object[] attributes = type.GetCustomAttributes(
typeof(SortOrderAttribute), true);
// Now let's make sure that we got at least one attribute.
if (attributes != null && attributes.Length > 0)
{
// Get the first attribute in the list of custom attributes
// that is of the type "SortOrderAttribute". This should only
// be one since we said "AllowMultiple=false".
SortOrderAttribute attribute =
attributes[0] as SortOrderAttribute;
// Now we can get the sort order for the class "MyClass".
int sortOrder = attribute.SortOrder;
}
}
}
これについてさらに詳しく読みたい場合は、いつでもチェックしてください MSDN かなり良い説明が付いています。
これがお役に立てば幸いです!
属性は、コード内のオブジェクトに適用できる機能の一部を含むクラスです。これを作成するには、System.Attribute を継承するクラスを作成します。
それらが何に良いのかというと…ほぼ無限の用途があります。
属性は、クラス、メソッド、またはアセンブリに適用されるメタデータのようなものです。
これらは、さまざまな用途に適しています (デバッガーの視覚化、古いものとしてマークする、シリアル化可能としてマークするなど、リストは無限にあります)。
独自のカスタムの作成は非常に簡単です。ここから始める:
http://msdn.microsoft.com/en-us/library/sw480ze8(VS.71).aspx
私が現在取り組んでいるプロジェクトには、さまざまな種類の UI オブジェクトのセットと、これらのオブジェクトを組み立ててメイン アプリケーションで使用するページを作成するエディターがあり、DevStudio のフォーム デザイナーに似ています。これらのオブジェクトは独自のアセンブリ内に存在し、各オブジェクトは次から派生したクラスです。 UserControl
カスタム属性を持っています。この属性は次のように定義されます。
[AttributeUsage (AttributeTargets::Class)]
public ref class ControlDescriptionAttribute : Attribute
{
public:
ControlDescriptionAttribute (String ^name, String ^description) :
_name (name),
_description (description)
{
}
property String ^Name
{
String ^get () { return _name; }
}
property String ^Description
{
String ^get () { return _description; }
}
private:
String
^ _name,
^ _description;
};
そしてそれを次のようにクラスに適用します。
[ControlDescription ("Pie Chart", "Displays a pie chart")]
public ref class PieControl sealed : UserControl
{
// stuff
};
これは以前の投稿者が言っていることです。
属性を使用するには、エディターに Generic::List <Type>
コントロールの種類が含まれます。ユーザーがページ上にドラッグ アンド ドロップしてコントロールのインスタンスを作成できるリスト ボックスがあります。リストボックスに値を入力するには、 ControlDescriptionAttribute
コントロールを選択し、リストにエントリを入力します。
// done for each control type
array <Object ^>
// get all the custom attributes
^attributes = controltype->GetCustomAttributes (true);
Type
// this is the one we're interested in
^attributetype = ECMMainPageDisplay::ControlDescriptionAttribute::typeid;
// iterate over the custom attributes
for each (Object ^attribute in attributes)
{
if (attributetype->IsInstanceOfType (attribute))
{
ECMMainPageDisplay::ControlDescriptionAttribute
^description = safe_cast <ECMMainPageDisplay::ControlDescriptionAttribute ^> (attribute);
// get the name and description and create an entry in the list
ListViewItem
^item = gcnew ListViewItem (description->Name);
item->Tag = controltype->Name;
item->SubItems->Add (description->Description);
mcontrols->Items->Add (item);
break;
}
}
注記:上記はC ++/CLIですが、C#に変換することは難しくありません(ええ、C ++/CLIは憎悪ですが、それは私が仕事をしなければならないものです:-()
ほとんどのものに属性を付けることができ、あらゆる範囲の事前定義された属性があります。上記のエディターは、プロパティとその編集方法を説明するプロパティのカスタム属性も検索します。
一度全体のアイデアを理解すると、それらなしでどうやって生きてきたのか疑問に思うでしょう。
前述したように、属性は比較的簡単に作成できます。作業のもう 1 つの部分は、それを使用するコードを作成することです。ほとんどの場合、実行時にリフレクションを使用して、属性またはそのプロパティの存在に基づいて動作を変更します。コンパイルされたコードの属性を検査して、ある種の静的分析を行うシナリオもあります。たとえば、パラメーターが非 null としてマークされている場合、分析ツールはこれをヒントとして使用できます。
属性を使用し、その使用に適したシナリオを知ることが作業の大部分です。
属性は本質的に、ファイルに添付するデータのビットです。 種類 (クラス、メソッド、イベント、列挙型など)
アイデアは、実行時に他のタイプ/フレームワーク/ツールがクエリを実行するということです。 あなたの 属性に情報を入力し、それに基づいて処理します。
したがって、たとえば、Visual Studio はサードパーティ コントロールの属性をクエリして、デザイン時にコントロールのどのプロパティをプロパティ ウィンドウに表示するかを判断できます。
アスペクト指向プログラミングでも属性を使用して、オブジェクトを装飾し、検証やログ記録などを追加する属性に基づいて、実行時にオブジェクトを挿入/操作することができます。オブジェクトのビジネス ロジックに影響を与えることなく、オブジェクトに適用されます。
カスタム属性を使用すると、サブクラスごとに同じコードを何度も記述することなく、サブクラスでタグ値を定義する簡単な方法として使用できます。素敵なものに出会えました John Waters による簡潔な例 独自のコードでカスタム属性を定義して使用する方法について説明します。
にチュートリアルがあります http://msdn.microsoft.com/en-us/library/aa288454(VS.71).aspx
属性の作成を開始するには、C# ソース ファイルを開き、次のように入力します。 attribute
[TAB] を押します。新しい属性のテンプレートに展開されます。
属性はアスペクト指向プログラミングでもよく使用されます。この例については、以下を確認してください。 ポストシャープ プロジェクト。