継承
次のコード例では、マネージ コードで継承を使用して WMI 内に継承階層構造を作成する、いくつかのパターンを示します。
BaseEvent の派生クラスのイベント継承
開発者が WMI を通じてアプリケーション イベントを公開しようとするとき、そのイベントは WMI のシステム クラス __ExtrinsicEvent から派生している必要があります。既定では、System.Management.Instrumentation.BaseEvent からクラスを派生するときには、マネージ クラスは __ExtrinsicEvent から派生した WMI クラスを表します。派生クラスからさらにクラスを派生させると、それらのクラスも WMI イベントの継承ツリーに反映されます。
マネージ イベント クラス階層構造内のすべてのイベントは、マネージ コードから発生させることができます。これにより、クライアント アプリケーションを類似したイベントの幅広いセットにサブスクライブすることも、特定の 1 つのイベントに限ってサブスクライブすることもできます。たとえば、MyBaseEvent と派生クラス MyDerivedEvent という 2 つのイベント クラスがあるとします。クライアント アプリケーションが WQL クエリ "SELECT * FROM MyBaseEvent" を実行すると、アプリケーションから発生した MyBaseEvent イベントと MyDerivedEvent イベントの両方を受信できます。これに対して、WQL クエリ "SELECT * FROM MyDerivedEvent" を発行したクライアントは、アプリケーションから MyBaseEvent が発生した場合にはイベントを受信しませんが、アプリケーションから MyDerivedEvent が発生した場合にはイベントを受信します。
次のコード例で、継承を使用して BaseEvent ヘルパ クラスを使用した単純な WMI イベント階層構造を作成する方法を示します。最上位のマネージ イベント クラス TopEvent は、__ExtrinsicEvent から派生した WMI クラス TopEvent によって表されます。TopEvent クラスから、Branch1Event と Branch2Event という 2 つの子クラスを派生させます。最後に、Branch1Event から 2 つの子クラス (Leaf1AEvent と Leaf1BEvent) を、Branch2Event から 1 つの子クラス (Leaf2AEvent) をそれぞれ派生させます。このイベント階層構造は、この例の最初のコメント ブロックにあるダイアグラムで図解されています。階層構造の末端に位置する派生クラス (それ以下の派生クラスを持たない派生クラス) は、リーフ ノードと呼ばれます。イベント階層構造においてはリーフ ノードはあまり重要ではありませんが、リーフ ノードとそれ以外のリーフ ノードの区別は、インスタンスの実装で重要な役割を果たします。
説明を単純化するために、この例のイベントはプロパティを持っていません。しかし実際には、それぞれの子クラスにプロパティを追加して拡張する場合がほとんどです。次のコード例では、例を簡単にするためにプロパティを省略しています。
using System;
using System.Management.Instrumentation;
[assembly:Instrumented]
// A simple tree of events derived from BaseEvent
// TopEvent--Branch1Event--Leaf1AEvent
// \ \-Leaf1BEvent
// \
// Branch2Event--Leaf2AEvent
// Any event in the hierarchy can be raised by the application
// This class inherits the 'InstrumentationType.Event' attribute
// from 'BaseEvent'
public class TopEvent : BaseEvent {
}
// This class inherits the 'InstrumentationType.Event' attribute
public class Branch1Event : TopEvent{
}
// This class inherits the 'InstrumentationType.Event' attribute
public class Leaf1AEvent : Branch1Event {
}
// This class inherits the 'InstrumentationType.Event' attribute
public class Leaf1BEvent : Branch1Event {
}
// This class inherits the 'InstrumentationType.Event' attribute
public class Branch2Event : TopEvent {
}
// This class inherits the 'InstrumentationType.Event' attribute
public class Leaf2AEvent : Branch2Event {
}
class App {
static void Main(string[] args) {
// Raise each type of event
new TopEvent().Fire();
new Branch1Event().Fire();
new Leaf1AEvent().Fire();
new Leaf1BEvent().Fire();
new Branch2Event().Fire();
new Leaf2AEvent().Fire();
}
}
BaseEvent から派生しないクラスのイベント継承
最上位のイベント クラスをヘルパ クラス System.Managment.Instrumentation.BaseEvent から派生させる代わりに、クラスを [InstrumentationClass(InstrumentationType.Event)] 属性でマークすることもできます。この処理が必要なのは、最上位のイベント クラスだけです。この属性を持つクラスから派生したクラスも、実装されたイベント クラスとして解釈されます。技術的に言うと、InstrumentationClass 属性が派生クラスに自動的に継承されるために、そのようなことが起こります。実際には、BaseEvent 自体が、すべての子クラスに継承するされる InstrumentationClass 属性を持つため、この例 (BaseEvent から派生したイベント) でのこの属性の記述は実際には不要です。
前の例と同じタスクを実行する例を次に示します。BaseEvent からの派生ではなく InstrumentationClass 属性を使用します。
using System;
using System.Management.Instrumentation;
[assembly:Instrumented]
// A simple tree of events declared with attributes
// TopEvent2--Branch1Event2--Leaf1AEvent2
// \ \-Leaf1BEvent2
// \
// Branch2Event2--Leaf2AEvent2
// Any event in the hierarchy can be raised by the application
// This is a top-level event class
[InstrumentationClass(InstrumentationType.Event)]
public class TopEvent2 {
}
// This class inherits the 'InstrumentationType.Event' attribute
public class Branch1Event2 : TopEvent2{
}
// This class inherits the 'InstrumentationType.Event' attribute
public class Leaf1AEvent2 : Branch1Event2 {
}
// This class inherits the 'InstrumentationType.Event' attribute
public class Leaf1BEvent2 : Branch1Event2 {
}
// This class inherits the 'InstrumentationType.Event' attribute
public class Branch2Event2 : TopEvent2 {
}
// This class inherits the 'InstrumentationType.Event' attribute
public class Leaf2AEvent2 : Branch2Event2 {
}
class App {
static void Main(string[] args) {
// Raise each type of event
Instrumentation.Fire(new TopEvent2());
Instrumentation.Fire(new Branch1Event2());
Instrumentation.Fire(new Leaf1AEvent2());
Instrumentation.Fire(new Leaf1BEvent2());
Instrumentation.Fire(new Branch2Event2());
Instrumentation.Fire(new Leaf2AEvent2());
}
}
Instance の派生クラスのインスタンス継承
インスタンス階層構造の作成は、多くの点でイベント階層構造の作成と似ています。大きな相違点は、最上位の WMI イベントは WMI クラス __ExtrinsicEvent から派生し、最上位のインスタンスは親クラス (WMI 用語ではスーパークラス) を持たないという点です。ヘルパ クラス System.Management.Instrumentation.Instance から単一のクラスを派生させて単純なインスタンスを実装する場合、WMI クラスは単一の最上位のインスタンス クラスとして表されます。
しかし、インスタンス階層構造はイベント階層構造よりもやや複雑です。現在のバージョンの System.Management では、インスタンス階層構造のリーフ ノードだけがインスタンスのパブリケーションをサポートできます。リーフ ノード以外のノードは、抽象 WMI クラスと見なされます。つまり、BaseInstance と派生クラス DerivedInstance という 2 つのクラスがある場合、DerivedInstance クラスのインスタンスは作成できますが、BaseInstance のインスタンスは作成できません。インスタンスをサポートできるクラスは、通常、具象クラスとも呼ばれます。インスタンスを実装するための継承規則を一言で表すならば、継承階層構造のリーフ ノードだけが具象インスタンス クラスになることができる、と言えます。継承階層構造のそれ以外のすべてのノードは、抽象 WMI クラスとしてマークされる必要があります。
クラスを抽象 WMI 実装クラスとしてマークするためには、そのクラスが [InstrumentationClass(InstrumentationType.Abstract)] 属性を持つ必要があります。ヘルパ クラス Instance は [InstrumentationClass(InstrumentationType.Instance)] でマークされています。既定では、この属性は子クラスに継承されます。1 つの最上位の具象インスタンス クラスしかない場合にはこれで問題ありませんが、さらに複雑な階層構造の場合には、最上位のクラスに Abstract 属性を手動で追加する必要があります。この方法を用いる階層構造の例を次に示します。最上位のクラス TopInstance は Instance から派生し、Abstract で明示的にマークしています。リーフ ノード以外の派生クラスは、この属性を継承します (そして、TopInstance のような抽象 WMI クラスになります)。リーフ ノードは具象インスタンスとしてマークされる必要があり、したがって、クラス定義で Instance 属性を明示的に与えられる必要があります。
using System;
using System.Management.Instrumentation;
[assembly:Instrumented]
// A simple tree of instances derived from Instance
// TopInstance--Branch1Instance--Leaf1AInstance
// \ \-Leaf1BInstance
// \
// Branch2Instance--Leaf2AInstance
// Only the leafs of the tree can be concrete instances.
// All other nodes on the tree must be abstract.
// This is a top-level abstract class. It must have the
// 'InstrumentationType.Abstract' attribute or it would
// inherit the 'Instance' attribute from the base class 'Instance'
[InstrumentationClass(InstrumentationType.Abstract)]
public class TopInstance : Instance {
}
// This class inherits the 'InstrumentationType.Abstract' attribute
public class Branch1Instance : TopInstance {
}
// This is a leaf class which can be concrete
[InstrumentationClass(InstrumentationType.Instance)]
public class Leaf1AInstance : Branch1Instance {
}
// This is a leaf class which can be concrete
[InstrumentationClass(InstrumentationType.Instance)]
public class Leaf1BInstance : Branch1Instance {
}
// This class inherits the 'InstrumentationType.Abstract' attribute
public class Branch2Instance : TopInstance {
}
// This is a leaf class which can be concrete
[InstrumentationClass(InstrumentationType.Instance)]
public class Leaf2AInstance : Branch2Instance {
}
class App {
static void Main(string[] args) {
// Publish an instance of each leaf
Leaf1AInstance leaf1a = new Leaf1AInstance();
Leaf1BInstance leaf1b = new Leaf1BInstance();
Leaf2AInstance leaf2a = new Leaf2AInstance();
leaf1a.Published = true;
leaf1b.Published = true;
leaf2a.Published = true;
// Instances now visible through WMI
Console.WriteLine("Instances now visible through WMI");
Console.ReadLine();
// Revoke all instances
leaf1a.Published = false;
leaf1b.Published = false;
leaf2a.Published = false;
}
}
インスタンスから派生しないクラスのインスタンス継承
インスタンス実装クラスを宣言するために属性だけを使用している場合、階層構造はヘルパ クラス System.Management.Instrumentation.Instance から派生したインスタンス実装クラスに使用されるメソッドと同様に定義されます。この場合も、1 つの最上位の具象インスタンス クラスしか持たない場合を除いては、最上位のインスタンス実装クラスを [InstrumentationClass(InstrumentationType.Abstract)] でマークする必要があります。階層構造のブランチはこの属性を継承するため、ブランチ自体の InstrumentationClass 属性を明示的に宣言する必要はありません。しかし、リーフ ノードは具象 WMI インスタンス クラスとして明示的にマークされる必要があり、[InstrumentationClass(InstrumentationType.Instance)] 属性を必要とします。
前の例と同じ機能を次の例に示しますが、ヘルパ クラス Instance から最上位クラスを派生する代わりに InstrumentationClass 属性だけを使用します。
using System;
using System.Management.Instrumentation;
[assembly:Instrumented]
// A simple tree of instances declared with attributes
// TopInstance2--Branch1Instance2--Leaf1AInstance2
// \ \-Leaf1BInstance2
// \
// Branch2Instance2--Leaf2AInstance2
// Only the leafs of the tree can be concrete instances.
// All other nodes on the tree must be abstract.
// This is a top level abstract class.
[InstrumentationClass(InstrumentationType.Abstract)]
public class TopInstance2 {
}
// This class inherits the 'InstrumentationType.Abstract' attribute
public class Branch1Instance2 : TopInstance2{
}
// This is a leaf class which can be concrete
[InstrumentationClass(InstrumentationType.Instance)]
public class Leaf1AInstance2 : Branch1Instance2 {
}
// This is a leaf class which can be concrete
[InstrumentationClass(InstrumentationType.Instance)]
public class Leaf1BInstance2 : Branch1Instance2 {
}
// This class inherits the 'InstrumentationType.Abstract' attribute
public class Branch2Instance2 : TopInstance2 {
}
// This is a leaf class which can be concrete
[InstrumentationClass(InstrumentationType.Instance)]
public class Leaf2AInstance2 : Branch2Instance2 {
}
class App {
static void Main(string[] args) {
// Publish an instance of each leaf
Leaf1AInstance2 leaf1a = new Leaf1AInstance2();
Leaf1BInstance2 leaf1b = new Leaf1BInstance2();
Leaf2AInstance2 leaf2a = new Leaf2AInstance2();
Instrumentation.Publish(leaf1a);
Instrumentation.Publish(leaf1b);
Instrumentation.Publish(leaf2a);
// Instances now visible through WMI
Console.WriteLine("Instances now visible through WMI");
Console.ReadLine();
// Revoke all instances
Instrumentation.Revoke(leaf1a);
Instrumentation.Revoke(leaf1b);
Instrumentation.Revoke(leaf2a);
}
}
参照
System.Management を使用する .NET Framework アプリケーションの実装 | CLI と WMI におけるクラスとマップ | 管理イベントの公開 | 管理データの公開 | 実装されたアプリケーションのスキーマ登録