与单例对象的交互
与单例对象的交互
关于单例对象
单例是只支持一个对象实例的对象。在 ArcObjects 中,单例对象需要通过 Activator 类进行实例化,并且需要通过 ComReleaser 类显式释放。 此外,一个线程中的所有 ArcObjects 引用应该只与同一线程中的对象通信。 因此,在 ArcGIS 中,单例对象是每个线程的单例,而不是每个进程的单例,如 Writing multithreaded ArcObjects code。
单例和 System.__COMObject
在主题 【在.net 中对 ArcObjects 的应用 】中,“RCW 类和 System.__COMObject”部分显示,当您使用 new 关键字实例化 COM 对象时,会创建一个强类型 RCW,而如果该对象是已存在的,则 RCW 的类型是一般性的System._ComObject。
然而有的时候,当您使用 new 关键字来实例化 COM 对象时,您却会获得一个对已有对象的引用。当尝试实例化一个已实例化的单例类时,会发生这种情况。
在.NET Framework 中,已包装在一般性的 System._ComObject RCW 中的 COM 对象,无法再被包装到强类型 RCW 中去。如果您的代码遇到这种情况,您可能会收到一个错误,例如:
无法将类型为“System.__ComObject”的对象强制转换为类型 <Typename>
Unable to cast object of type System._ComObject to type <Typename>
请参见以下代码示例:
[C#]
ESRI.ArcGIS.Display.IStyleGallery sg=new ESRI.ArcGIS.Framework.StyleGalleryClass();
[VB.NET]
Dim sg As ESRI.ArcGIS.Display.IStyleGallery=New ESRI.ArcGIS.Framework.StyleGalleryClass
译者自己提供示例:
public static ISpatialReference CreateSpatialReference(int wkid)
{
if (wkid == 0)
{
return null;
}
ISpatialReference spr = null;
ISpatialReferenceFactory3 sprFactory = null;
if (IsGeographic(wkid))
{
//错误:
//在多线程运行环境中,可能招出异常:
// System.InvalidCastException: 无法将类型为“System.__ComObject”的对象强制转换为
// 类型“ESRI.ArcGIS.Geometry.SpatialReferenceEnvironmentClass”。
// --------
//因为这个 SpatialReferenceEnvironmentClass 类实例,需要做到每线程单例;
// 若用 new 语句,则之前已经实例化的、已经包装在 “System.__ComObject”中的这个类实例,
// 会被 .net 运行时尝试包装到 强类型 RCW 中,从而报错
sprFactory = new SpatialReferenceEnvironmentClass();
spr = sprFactory.CreateGeographicCoordinateSystem(wkid);
}
else if (IsProjected(wkid))
{
//错误:同上
sprFactory = new SpatialReferenceEnvironmentClass();
spr = sprFactory.CreateProjectedCoordinateSystem(wkid);
}
AOUtil.Release(sprFactory);
return spr;
}
public class AOUtil
{
/// <summary>
/// 释放AO非托管对象
/// </summary>
public static void Release<T>(T obj)
{
if (obj == null) return;
int refsLeft;
do
{
refsLeft = Marshal.ReleaseComObject(obj);
}
while (refsLeft > 0);
obj = default;
}
}
即使您使用接口名称来声明变量,而不是类名称来声明变量,也可能会发生前面的错误。如上面的示例所示。出现此问题的原因是,当您的代码实例化一个对象时,.NET 运行时首先尝试将对象包装在【强类型的类】的类型(即在 new 关键字之后声明的类型)中,然后再尝试转换为接口类型。 在向强类型 RCW 的强制转换的过程中失败,无法成功,因为 COM 对象先前已包装在一般性的 System._ComObject 包装器中。 这可能发生在您无法控制的情况下。 例如,第三方用 .NET 编写的其他 ArcObjects 工具可能会将对象包装在通用包装器中,从而导致您的代码失败。
解决方案是使用 Activator 类,如下所示,在您第一次获得对单例对象的引用时,将其安全地包装在强类型 RCW 中。 此外,在一般情况下,应该始终使用接口,而不是类的类型来,声明持有 RCW 的变量。
使用 Activator 类创建单例
如果使用 Activator 类的 CreateInstance 方法,而不是 new 关键字来实例化单例,则可以避免上一节中讨论的错误,因为 Activator 可以获得执行转换所需的元数据。
请参见以下代码示例:
[C#]
Type t=Type.GetTypeFromProgID("esriFramework.StyleGallery");
System.Object obj=Activator.CreateInstance(t);
IStyleGallery sg=obj as IStyleGallery;
[VB.NET]
Dim t As Type=Type.GetTypeFromProgID("esriFramework.StyleGallery")
Dim obj As System.Object=Activator.CreateInstance(t)
Dim pApp As ESRI.ArcGIS.Display.IStyleGallery=obj
译者示例的解决办法:
if (IsGeographic(wkid))
{
Type t = Type.GetTypeFromProgID("esriGeometry.SpatialReferenceEnvironment");
object obj = Activator.CreateInstance(t);
sprFactory = obj as ISpatialReferenceFactory3;
spr = sprFactory.CreateGeographicCoordinateSystem(wkid);
}
else if (IsProjected(wkid))
{
Type t = Type.GetTypeFromProgID("esriGeometry.SpatialReferenceEnvironment");
object obj = Activator.CreateInstance(t);
sprFactory = obj as ISpatialReferenceFactory3;
spr = sprFactory.CreateProjectedCoordinateSystem(wkid);
}
实例化 AppRef 类
您可以使用前面的技术,来实例化 AppRef 类; 但是,AppRef 类只能在 ArcGIS 应用程序中创建(类型是一般性的 System._ComObject RCW)。
请参见以下代码示例:
[C#]
Type t=Type.GetTypeFromProgID("esriFramework.AppRef");
System.Object obj=Activator.CreateInstance(t);
ESRI.ArcGIS.Framework.IApplication pApp=obj as ESRI.ArcGIS.Framework.IApplication;
[VB.NET]
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 中的单例对象。 带有星号 (*) 的类型是每个进程的单例(区别于每个线程的单例)。
Class | Library | ProgID | GUID | Location |
---|---|---|---|---|
AccessWorkspaceFactory | DataSourcesGDB | esriDataSourcesGDB.AccessWorkspaceFactory | dd48c96a-d92a-11d1-aa81-00c04fa33a15 | D, E, S |
AMSWorkspaceFactory | TrackingAnalyst | esriTrackingAnalyst.AMSWorkspaceFactory | a677ab59-2fb8-11d5-b7e2-00010265adc5 | D, E, S |
ArcInfoWorkspaceFactory | DataSourcesFile | esriDataSourcesFile.ArcInfoWorkspaceFactory | 1d887452-d9f2-11d1-aa81-00c04fa33a15 | D, E, S |
CadWorkspaceFactory | DataSourcesFile | esriDataSourcesFile.CadWorkspaceFactory | 9e2c27ce-62c6-11d2-9aed-00c04fa33299 | D, E, S |
ExcelWorkspaceFactory | DataSourcesOleDB | esriDataSourcesOleDB.ExcelWorkspaceFactory | 30f6f271-852b-4ee8-bd2d-099f51d6b238 | D, E, S |
FileGDBWorkspaceFactory | DataSourcesGDB | esriDataSourcesGDB.FileGDBWorkspaceFactory | 71fe75f0-ea0c-4406-873e-b7d53748ae7e | D, E, S |
IMSWorkspaceFactory | GISClient | esriGISClient.IMSWorkspaceFactory | bac84d58-fa9d-11d3-9f48-00c04f79927c | D, E, S |
InMemoryWorkspaceFactory | DataSourcesGDB | esriDataSourcesGDB.InMemoryWorkspaceFactory | 7f2bc55c-b902-43d0-a566-aa47ea9fda2c | D, E, S |
NetCDFWorkspaceFactory | DataSourcesNetCDF | esriDataSourcesNetCDF.NetCDFWorkspaceFactory | df61a9e1-b8e2-498f-bde5-98de42e801f9 | D, E, S |
OLEDBWorkspaceFactory | DataSourcesOleDB | esriDataSourcesOleDB.OLEDBWorkspaceFactory | 59158055-3171-11d2-aa94-00c04fa37849 | D, E, S |
PCCoverageWorkspaceFactory | DataSourcesFile | esriDataSourcesFile.PCCoverageWorkspaceFactory | 6de812d2-9ab6-11d2-b0d7-0000f8780820 | D, E, S |
RasterWorkspaceFactory | DataSourcesRaster | esriDataSourcesRaster.RasterWorkspaceFactory | 4c91d963-3390-11d2-8d25-0000f8780535 | D, E, S |
SchematicWorkspaceFactory | Schematic | esriSchematic.SchematicWorkspaceFactory | e18fc71c-fda7-4c7b-a824-c024d7900b5d | D, E, S |
ScratchWorkspaceFactory | DataSourcesGDB | esriDataSourcesGDB.ScratchWorkspaceFactory | 06dc8e4c-951c-11d2-ae75-080009ec732a | D, E, S |
SDCWorkspaceFactory | DataSourcesFile | esriDataSourcesFile.SDCWorkspaceFactory | 34dae34f-dbe2-409c-8f85-ddbb46138011 | D, E, S |
SdeWorkspaceFactory | DataSourcesGDB | esriDataSourcesGDB.SdeWorkspaceFactory | d9b4fa40-d6d9-11d1-aa81-00c04fa33a15 | D, E, S |
ShapefileWorkspaceFactory | DataSourcesFile | esriDataSourcesFile.ShapefileWorkspaceFactory | a06adb96-d95c-11d1-aa81-00c04fa33a15 | D, E, S |
StreetMapWorkspaceFactory | DataSourcesFile | esriDataSourcesFile.StreetMapWorkspaceFactory | ae2469e8-e110-4cd6-b3f4-a756cbf921ca | D, E, S |
TextFileWorkspaceFactory | DataSourcesOleDB | esriDataSourcesOleDB.TextFileWorkspaceFactory | 72ce59ec-0be8-11d4-ae03-00c04fa33a15 | D, E, S |
TinWorkspaceFactory | DataSourcesFile | esriDataSourcesFile.TinWorkspaceFactory | ad4e89d9-00a5-11d2-b1ca-00c04f8edeff | D, E, S |
ToolboxWorkspaceFactory | Geoprocessing | esriGeoprocessing.ToolboxWorkspaceFactory | e9231b31-2a34-4729-8de2-12cf39674b1b | D, E, S |
VpfWorkspaceFactory | DataSourcesFile | esriDataSourcesFile.VpfWorkspaceFactory | 397847f9-c865-11d3-9b56-00c04fa33299 | D, E, S |
WorkspaceFactory | Geodatabase | esriGeodatabase.WorkspaceFactory | FBF5715D-A05D-11D4-A64C-0008C711C8C1 | D, E, S |
AGSServerConnectionFactory | GISClient | esriGISClient.AGSServerConnectionFactory | 7932a86e-f371-4c64-ab84-9e83dda2581b | D, E, S |
WMSConnectionFactory | GISClient | esriGISClient.WMSConnectionFactory | f7c34345-87ce-4ab5-9ca8-2012d7241075 | D, E, S |
GPGlobeFunctionFactory | GlobeCore | esriGlobeCore.GPGlobeFunctionFactory | 9e8cedbd-fd6f-41d8-93a0-35207790ba08 | D, E, S |
GPServerFunctionFactory | Geoprocessing | esriGeoprocessing.GPServerFunctionFactory | f8ac2c04-deec-43f4-86ef-246f91f12856 | D, E, S |
MemoryRelationshipClassFactory | Geodatabase | esriGeodatabase.MemoryRelationshipClassFactory | 2fc5c57b-eb92-4a61-bbc5-434e388bf3b9 | D, E, S |
RelQueryTableFactory | Geodatabase | esriGeodatabase.RelQueryTableFactory | 9b4e4d0c-753a-43bb-83fb-ba16f6652e1c | D, E, S |
ActionEnvironment * | TrackingAnalyst | esriTrackingAnalyst.ActionEnvironment | 1e18428c-86eb-4678-a987-f8157feb77cf | D, E, S |
CommandsEnvironment | Controls | esriControls.CommandsEnvironment | 46d9c72e-4dc2-4589-b809-a51fc4a57684 | D, E, S |
DddEnvironment | 3DAnalystUI | esri3DAnalystUI.DddEnvironment | 94305472-592e-11d4-80ee-00c04fa0adf8 | D |
DddServerEnvironment | Geodatabase | esriGeodatabase.DddServerEnvironment | 3b6c52a4-7231-4189-b341-c30e7fb58bcf | D, E, S |
DDDToolbarEnvironment | 3DAnalystUI | esri3DAnalystUI.DDDToolbarEnvironment | 2d73b143-8f1c-11d4-a10f-00508bd60cb9 | D |
EngineNetworkAnalystEnvironment | Controls | esriControls.EngineNetworkAnalystEnvironment | 7da28a78-4027-4cc8-a8c3-fd31c6f22e9e | E |
EnvironmentManager | System | esriSystem.EnvironmentManager | 8a626d49-5f5e-47d9-9463-0b802e9c4167 | D, E, S |
GMxEffectsToolbarEnvironment | ArcGlobe | esriArcGlobe.GMxEffectsToolbarEnvironment | 3eafa611-dc74-4c29-bab6-c401e7c76ac6 | D |
LabelEnvironment | Carto | esriCarto.LabelEnvironment | 76765b96-ce78-11d2-9f36-00c04f6bc6a5 | D, E, S |
LayerEffectsEnvironment | ArcMapUI | esriArcMapUI.LayerEffectsEnvironment | 377aba22-2019-11d3-9f97-00c04f6bc78e | D |
RasterAnalysisToolbarEnvironment | SpatialAnalystUI | esriSpatialAnalystUI.RasterAnalysisToolbarEnvironment | 89daddfd-79ec-4f5e-8252-ae716a89ac15 | D |
RasterDefaultsEnv | Carto | esriCarto.RasterDefaultsEnv | eb0d0573-c109-11d2-9f43-00c04f8ed21a | D, E, S |
SelectionEnvironment | Carto | esriCarto.SelectionEnvironment | e3875b71-d9f5-11d1-add4-080009ec732a | D, E, S |
SpatialReferenceEnvironment | Geometry | esriGeometry.SpatialReferenceEnvironment | 7b5b7020-c4f6-11d1-bc92-0000f875bcce | D, E, S |
SxAnimationEnvironment | 3DAnalyst | esri3DAnalyst.SxAnimationEnvironment | 592d0b58-82ad-11d5-b29b-00508bcdde28 | D, E, S |
SxEffectsToolbarEnvironment | ArcScene | esriArcScene.SxEffectsToolbarEnvironment | 80e3f11d-c4bb-11d4-b27e-00508bcdde28 | D |
SymbologyEnvironment | Display | esriDisplay.SymbologyEnvironment | 65856cd8-ad04-11d3-9fc2-00c04f6bc8dd | D, E, S |
TrackingEnvironment | TrackingAnalyst | esriTrackingAnalyst.TrackingEnvironment | ef13642c-42da-4095-8a5b-c4f9c6a7bbe3 | D, E, S |
AGAnimationUtils | Animation | esriAnimation.AGAnimationUtils | 2835514b-1a02-4142-8474-31d48d9063a8 | D, E, S |
DEUtilities | Geoprocessing | esriGeoprocessing.DEUtilities | f0c2aa3e-b2f1-4208-9843-6a3c70a4680a | D, E, S |
DEGdbUtilities | Geodatabase | esriGeodatabase.DEGdbUtilities | 48f71b4d-72ce-42aa-a45c-5c180f6e78e8 | D, E, S |
GPUtilities | Geoprocessing | esriGeoprocessing.GPUtilities | 59e42101-2f33-4b6d-8cee-eed9d98d1957 | D, E, S |
GPSAUtil | SpatialAnalyst | esriSpatialAnalyst.GPSAUtil | 0c4404c3-276c-475b-bf33-dd35082e5e3a | D, E, S |
AnimationControlsDialog | AnimationUI | esriAnimationUI.AnimationControlsDialog | 0a44bca2-ec21-4ea3-85d3-a0aae57127e5 | D |
AnimationCreateKeyframeDialog | AnimationUI | esriAnimationUI.AnimationCreateKeyframeDialog | 8c253bb9-4da2-4ab5-aceb-c6686006c37a | D |
AnimationFromPathDialog | AnimationUI | esriAnimationUI.AnimationFromPathDialog | dfde1249-74bb-48d3-aae8-b3155f25fd52 | D |
AnimationLayerGroupDialog | AnimationUI | esriAnimationUI.AnimationLayerGroupDialog | ebf7b926-ee3c-4773-b81e-a7fef23cd7ce | D |
AnimationManagerDialog | AnimationUI | esriAnimationUI.AnimationManagerDialog | f68848ca-f6af-40aa-8eaf-3305890aee5c | D |
ErrorDialog | SystemUtility | esriSystemUtility.ErrorDialog | 40accbda-720a-4b17-980b-b173f791958e | E (C++ only) |
FindDialog | CatalogUI | esriCatalogUI.FindDialog | ad0b37a9-d396-11d3-a6f3-0008c7d3ae50 | D |
GpsPositionDialog | ArcMapUI | esriArcMapUI.GpsPositionDialog | f56723f3-063d-4b4a-89b9-f03afadf2078 | D |
IdentifyDialog | CartoUI | esriCartoUI.IdentifyDialog | f8aab776-8b1e-11d3-9f7a-00c04f6bc886 | D |
NetworkIdentifyDialog | NetworkAnalystUI | esriNetworkAnalystUI.NetworkIdentifyDialog | e4c692c6-f721-4ba4-a000-83893af482ae | D |
AnimationTypeGlobeLayer | GlobeCore | esriGlobeCore.AnimationTypeGlobeLayer | 7ccba704-3933-4d7a-8e89-4dfee88aa937 | D, E, S |
AnimationTypeLayer | 3DAnalyst | esri3DAnalyst.AnimationTypeLayer | 24aa4279-adf3-11d5-b2a0-00508bcdde28 | D, E, S |
AnimationTypeMapLayer | Animation | esriAnimation.AnimationTypeMapLayer | 0a965644-11f1-4901-a0cf-9989bfd27b6d | D, E, S |
AnimationTypeTimeLayer | Animation | esriAnimation.AnimationTypeTimeLayer | a85b10a9-9eab-4f93-9259-5fbae98000eb | D, E, S |
DummyGraduatedMarkerLayer | Carto | esriCarto.DummyGraduatedMarkerLayer | 238ccd1a-7fbc-11d2-87dc-0000f8751720 | D, E, S |
DummyLayer | Carto | esriCarto.DummyLayer | 238ccd19-7fbc-11d2-87dc-0000f8751720 | D, E, S |
AnimationTypeCamera | 3DAnalyst | esri3DAnalyst.AnimationTypeCamera | 500f4707-a798-11d5-b2a0-00508bcdde28 | D, E, S |
AnimationTypeGlobeCamera | GlobeCore | esriGlobeCore.AnimationTypeGlobeCamera | d4565495-e2f9-4d89-a8a7-d0b69fd7a424 | D, E, S |
ExtensionManager | System | esriSystem.ExtensionManager | 6120bc0a-3d90-4274-97ca-713c41f1faff | D, E, S |
LocatorManager | Location | esriLocation.LocatorManager | e0f10b7a-eb7c-11d2-9f47-00c04f8ed1c4 | D, E, S |
NADirectionsWindowManager | NetworkAnalystUI | esriNetworkAnalystUI.NADirectionsWindowManager | bc36cf3b-1fc1-461d-92df-ca51cdc9c84c | D |
RasterAttributeTableManager | DataSourcesRaster | esriDataSourcesRaster.RasterAttributeTableManager | fe143bf3-8d4e-415a-a7e9-a3ac29ab65a7 | D, E, S |
SchematicProjectMgr | Schematic | esriSchematic.SchematicProjectMgr | c578262a-16c2-4f5a-a526-d738addc8208 | D, E, S |
SystemHelper | System | esriSystem.SystemHelper | be49d696-3c46-4b81-960b-f67d1bbd238d | D, E, S |
TMS_MarshalHelper | TrackingAnalyst | esriTrackingAnalyst.TMS_MarshalHelper | 6e5bff39-dcc0-11d6-b861-00010265adc5 | D, E, S |
GeoDatabaseHelper | Geodatabase | esriGeodatabase.GeoDatabaseHelper | 4e35da0b-c5d1-4ac9-bd62-b36b4155ee4b | D, E, S |
GPHolder | Geoprocessing | esriGeoprocessing.GPHolder | 602b0005-0ad2-41f1-a831-c640d8586cad | D, E, S |
MessageLogger | System | esriSystem.MessageLogger | a2e96efd-d501-433b-941f-83447916b8f6 | D, E, S |
XMLTypeMapper | System | esriSystem.XMLTypeMapper | dcb0f748-2d17-40b5-90c2-7d0b39660405 | D, E, S |
MetadataSynchronizer | Geodatabase | esriGeodatabase.MetadataSynchronizer | c10124ee-3648-445e-a16b-9d2755fbd690 | D, E, S |
GxDatabaseExtensions | Catalog | esriCatalog.GxDatabaseExtensions | 27E179F2-4F3E-11D3-9F52-00C04F6BDF06 | D |
SAExtension | SpatialAnalystUI | esriSpatialAnalystUI.SAExtension | 3c5059fe-9f15-401a-94ed-eed914d73e3e | D |
TAExtension | TrackingAnalystUI | esriTrackingAnalystUI.TAExtension | d53bf20f-24fb-11d4-b34c-00104ba2abcc | D |
ServerStyleGallery | Display | esriDisplay.ServerStyleGallery | 9cdcf7da-63b8-4f23-b769-1db1bceadd35 | D, E, S |
StyleGallery | Framework | esriFramework.StyleGallery | ac0e9827-91cb-11d1-8813-080009ec732a | D |
MonitorSettings | Display | esriDisplay.MonitorSettings | 9db25fe0-3c75-11d2-aaf6-00c04fa334b3 | D, E, S |
RasterSettings | SpatialAnalystUI | esriSpatialAnalystUI.RasterSettings | 8ac2f518-ed49-11d2-9f40-00c04f8ed1d7 | D |
AnimationTypeMapView | Animation | esriAnimation.AnimationTypeMapView | fd22a714-0eef-4312-8703-d81e5476e28a | D, E, S |
AnimationTypeScene | 3DAnalyst | esri3DAnalyst.AnimationTypeScene | 24aa427a-adf3-11d5-b2a0-00508bcdde28 | D, E, S |
AppRef * | Framework | esriFramework.AppRef | e1740ec5-9513-11d2-a2df-0000f8774fb5 | D |
CieLabConversion | Display | esriDisplay.CieLabConversion | 137e39dc-3e98-11d2-aaf7-00c04fa334b3 | D, E, S |
EngineEditor | Controls | esriControls.EngineEditor | 4afaf64d-0cb2-4adb-bc88-9fb07548d10d | E |
ErrorMessage | SystemUtility | esriSystemUtility.ErrorMessage | 672fb3aa-c6de-44e0-b767-c53d33ef9879 | E (C++ only) |
FormatList | DataSourcesRaster | esriDataSourcesRaster.FormatList | 53b7c0b9-41fb-4b00-b51a-fa5cc5b785fe | D, E, S |
GxCatalogROT | CatalogUI | esriCatalogUI.GxCatalogROT | 04faa368-046b-4cfe-81cb-1c8201f9cad3 | D |
MyPlaceCollection | Controls | esriControls.MyPlaceCollection | 83307360-8be1-4df2-b301-1e619a965b5c | E |
RasterStatus | DataSourcesRaster | esriDataSourcesRaster.RasterStatus | 83220700-5844-11d4-8d9b-00c04f5b87b2 | D, E, S |
TexturePersistenceProperties | Geometry | esriGeometry.TexturePersistenceProperties | 01cfeaf1-4d26-4084-84f8-7d2fda7c40d9 | D, E, S |
* 每个进程只支持一个对象实例 |
**D=ArcGIS Desktop;E=ArcGIS Engine;S=ArcGIS for Server **