FAQ
シングルトン オブジェクトの扱いについて

ナレッジ番号:2743 | 登録日:2023/05/29 | 更新日:2023/12/28

トピックの内容


シングルトン オブジェクトについて

"シングルトン" はそのオブジェクトのひとつのインスタンスしかサポートしていないオブジェクトです。
ArcObjects では、シングルトン オブジェクトは Activator クラスを介したインスタンス化が必要であり、ComReleaser クラスを介した明示的な解放が要求されます。さらに、あるスレッド内のすべての ArcObjects 参照は同じスレッド内のオブジェクトとのみ通信することができます。
従って、ArcGIS 10.x ではシングルトン オブジェクトはスレッド単位のシングルトンであり、プロセス単位のシングルトンではありません。このことは  Writing multithreaded ArcObjects code (マルチスレッド ArcObjects コードの書き方)に詳しく述べられています。

シングルトンと System.__COMObject

Using ArcObjects (COM-based) in .NET のトピックでは、"Runtime callable wrappers" と "System.__COMObject type" のセクションで、厳密に型指定されたランタイム呼び出し可能ラッパー(RCW) は、new キーワードでコンポーネント オブジェクト モデル(COM)オブジェクトをインスタンス化した時に作成されることを示しています。一方、オブジェクトが既存の物である場合は、RCW の型は一般的な System.__ComObject です。

COM オブジェクトを new キーワードでインスタンス化すると、時折既存のオブジェクトへの参照を得ることがあります。これは、すでにインスタンス化されているシングルトン クラスをインスタンス化しようとした時に起こります。

.NET Framework は、すでに一般的な System.__ComObject RCW でラップされているオブジェクトのインスタンスを、厳密に型指定された RCW にラップすることはできません。もしこの状況に遭遇した場合、System.__ComObject 型のオブジェクトを型 <型名> にキャストできません といったエラーが出るでしょう。以下のサンプル コードを見てください。

ESRI.ArcGIS.Display.IStyleGallery sg = new ESRI.ArcGIS.Framework.StyleGalleryClass();
Dim sg As ESRI.ArcGIS.Display.IStyleGallery = New ESRI.ArcGIS.Framework.StyleGalleryClass

前述のエラーは、前の例のようにクラス名ではなくインターフェイス名を使用して変数を宣言した場合でも起きます。この問題が起きる理由はコードがオブジェクトをインスタンス化した時、.NET ランタイムは、インターフェイス型にキャストする前に、まず オブジェクトを厳密に型指定されたクラス タイプ(new キーワードの後で宣言された型)でラップしようとします。厳密に型指定された RCW へのキャストは、成功しません。なぜなら COM オブジェクトはすでに一般的な System.__ComObject ラッパーでラップされているからです。これは開発者の制御しきれない状況で起こり得ます。例えばサードパーティによって .NET で書かれたその他の ArcObjects ツールは、オブジェクトを一般的なラッパーでラップするかもしれず、これが失敗を招くのです。

解決先は 最初にシングルトン オブジェクトへの参照を取得する時に、(以下で示すように) Activator クラスを利用して、シングルトン オブジェクトを厳密に型指定された RCW で安全にラップすることです。さらに、たいていの場合クラス型よりもインターフェイスを使用して RCW を保持する変数を常に宣言するべきです。

Activator クラスを使用してシングルトンを作成する

シングルトン オブジェクトをインスタンス化するのに、new キーワードの代わりに Activator クラスの CreateInstance メソッドを使用すると、Activator はキャストを実現するのに必要なメタデータを得ることができるため、前のセクションで説明したようなエラーを避けることができます。以下のコード例を見てください。

Type t = Type.GetTypeFromProgID("esriFramework.StyleGallery");
System.Object obj = Activator.CreateInstance(t);
IStyleGallery sg = obj as IStyleGallery;
Dim t As Type = Type.GetTypeFromProgID("esriFramework.StyleGallery")
Dim obj As System.Object = Activator.CreateInstance(t)
Dim pApp As ESRI.ArcGIS.Display.IStyleGallery = obj

AppRef クラスのインスタンス化

AppRef クラスをインスタンス化するのに前述の技法を使用することができます。しかし、AppRef クラスは ArcGIS アプリケーション(タイプは一般的な System.__ComObject RCW です。)の中でしか作成することができません。以下のコード例をご覧ください。

Type t = Type.GetTypeFromProgID("esriFramework.AppRef");
System.Object obj = Activator.CreateInstance(t);
ESRI.ArcGIS.Framework.IApplication pApp = obj as ESRI.ArcGIS.Framework.IApplication;
Dim t As Type = Type.GetTypeFromProgID("esriFramework.AppRef")
Dim obj As System.Object = Activator.CreateInstance(t)
Dim pApp As ESRI.ArcGIS.Framework.IApplication = obj

ArcObjects におけるシングルトン オブジェクト

以下のテーブルは ArcGIS におけるシングルトン オブジェクトを一覧表示したものです。* のついた型はプロセス単位のシングルトンです(スレッド単位ルールに対する例外です。)

シングルトン オブジェクトの一覧についてはこちらのドキュメントの末尾をご覧ください

参照:

Releasing COM references (COM参照の解放)
Using ArcObjects (COM-based) in .NET (.NET での ArcObjects (COMベース) の使用)

メタデータ

種類

製品