About the Server spatial query server object extension Sample
[C#]
Extension.cs
using System; using System.Runtime.InteropServices; using System.EnterpriseServices; namespace SpatialQuerySOE { /// <summary> /// Implementation of the Spatial Query SOE. /// </summary> [AutomationProxy(true), ClassInterface(ClassInterfaceType.None), GuidAttribute("1932805D-7266-41a2-9428-0421A5617436")] public class Extension : ServicedComponent, SpatialQuerySOE.Interfaces.IExtension, ESRI.ArcGIS.Server.IServerObjectExtension, ESRI.ArcGIS.esriSystem.IObjectConstruct, ESRI.ArcGIS.esriSystem.ILogSupport, ESRI.ArcGIS.esriSystem.IObjectActivate { #region Member Variables private ESRI.ArcGIS.Server.IServerObjectHelper m_ServerObjectHelper; private ESRI.ArcGIS.Carto.IFeatureLayer m_featureLayer; private string m_layerName; private string m_fieldName; private ESRI.ArcGIS.esriSystem.ILog m_log; #endregion #region IServerObjectExtension Members public void Init(ESRI.ArcGIS.Server.IServerObjectHelper pSOH) { m_ServerObjectHelper = pSOH; m_log.AddMessage(3,8000,"SpatialQuerySOE custom message. Init called"); } public void Shutdown() { m_log.AddMessage(3, 8000, "SpatialQuerySOE custom message. Shutdown called"); m_ServerObjectHelper = null; m_featureLayer = null; m_log = null; } #endregion #region SpatialQuerySOE.Interfaces.IExtension Members public SpatialQuerySOE.Interfaces.IResults QueryPoint(ESRI.ArcGIS.Geometry.IPoint point, double distance) { if (m_featureLayer == null) { m_log.AddMessage(1, 8000, "SpatialQuerySOE custom error: layer not found"); return null; } ESRI.ArcGIS.Geodatabase.IFeatureClass featureClass = m_featureLayer.FeatureClass; // buffer the point ESRI.ArcGIS.Geometry.ITopologicalOperator topologicalOperator = (ESRI.ArcGIS.Geometry.ITopologicalOperator)point; ESRI.ArcGIS.Geometry.IGeometry queryGeometry = topologicalOperator.Buffer(distance); // query the feature class ESRI.ArcGIS.Geodatabase.ISpatialFilter spatialFilter = new ESRI.ArcGIS.Geodatabase.SpatialFilter(); spatialFilter.Geometry = queryGeometry; spatialFilter.SpatialRel = ESRI.ArcGIS.Geodatabase.esriSpatialRelEnum.esriSpatialRelIntersects; spatialFilter.GeometryField = featureClass.ShapeFieldName; ESRI.ArcGIS.Geodatabase.IFeatureCursor resultsFeatureCursor = featureClass.Search(spatialFilter, true); // loop thourgh the features, clip each geometry to the buffer // and total areas by attribute value topologicalOperator = (ESRI.ArcGIS.Geometry.ITopologicalOperator)queryGeometry; int classFieldIndex = featureClass.FindField(m_fieldName); System.Collections.Specialized.ListDictionary summaryStatsDictionary = new System.Collections.Specialized.ListDictionary(); // create the symbol and graphic elements collection for the graphics ESRI.ArcGIS.Display.ISimpleFillSymbol simpleFillSymbol = createFillSymbol(); ESRI.ArcGIS.Carto.IGraphicElements resultsGraphics = new ESRI.ArcGIS.Carto.GraphicElements(); ESRI.ArcGIS.Geodatabase.IFeature resultsFeature; while ((resultsFeature = resultsFeatureCursor.NextFeature()) != null) { // create the graphic ESRI.ArcGIS.Carto.IFillShapeElement fillShapeElement = new ESRI.ArcGIS.Carto.PolygonElement() as ESRI.ArcGIS.Carto.IFillShapeElement; ESRI.ArcGIS.Carto.IElement element = fillShapeElement as ESRI.ArcGIS.Carto.IElement; // clip the geometry ESRI.ArcGIS.Geometry.IGeometry clippedResultsGeometry = topologicalOperator.Intersect(resultsFeature.Shape, ESRI.ArcGIS.Geometry.esriGeometryDimension.esriGeometry2Dimension); element.Geometry = clippedResultsGeometry; fillShapeElement.Symbol = simpleFillSymbol; ESRI.ArcGIS.Carto.IGraphicElement resultsGraphicElement = fillShapeElement as ESRI.ArcGIS.Carto.IGraphicElement; resultsGraphics.Add(resultsGraphicElement); // get statistics and add to dictionary ESRI.ArcGIS.Geometry.IArea area = clippedResultsGeometry as ESRI.ArcGIS.Geometry.IArea; string resultsClass = resultsFeature.get_Value(classFieldIndex) as string; // If the class is already in the dictionary, add the current feature's area to the existing entry if (summaryStatsDictionary.Contains(resultsClass)) summaryStatsDictionary[resultsClass] = (double)summaryStatsDictionary[resultsClass] + area.Area; else summaryStatsDictionary[resultsClass] = area.Area; } // create the summary statistics recordset ESRI.ArcGIS.Geodatabase.IRecordSet summaryStatsRecordSet = createSummaryRecordSet(summaryStatsDictionary); // create the results object SpatialQuerySOE.Interfaces.IResults results = new Results(); results.ResultsGraphics = resultsGraphics; results.SummaryStatistics = summaryStatsRecordSet; return results; } private ESRI.ArcGIS.Geodatabase.IRecordSet createSummaryRecordSet( System.Collections.Specialized.ListDictionary summaryStatsDictionary) { // initialize the summary statistics record set ESRI.ArcGIS.Geodatabase.IRecordSet summaryStatsRecordSet = new ESRI.ArcGIS.Geodatabase.RecordSet(); ESRI.ArcGIS.Geodatabase.IRecordSetInit recordSetInit = summaryStatsRecordSet as ESRI.ArcGIS.Geodatabase.IRecordSetInit; ESRI.ArcGIS.Geodatabase.IFields summaryFields = new ESRI.ArcGIS.Geodatabase.Fields(); ESRI.ArcGIS.Geodatabase.IFieldsEdit summaryFieldsEdit = summaryFields as ESRI.ArcGIS.Geodatabase.IFieldsEdit; summaryFieldsEdit.FieldCount_2 = 2; ESRI.ArcGIS.Geodatabase.IField field = new ESRI.ArcGIS.Geodatabase.Field(); ESRI.ArcGIS.Geodatabase.IFieldEdit fieldEdit = field as ESRI.ArcGIS.Geodatabase.IFieldEdit; fieldEdit.Name_2 = "Type"; fieldEdit.Type_2 = ESRI.ArcGIS.Geodatabase.esriFieldType.esriFieldTypeString; fieldEdit.Length_2 = 50; summaryFieldsEdit.set_Field(0, field); field = new ESRI.ArcGIS.Geodatabase.Field(); fieldEdit = field as ESRI.ArcGIS.Geodatabase.IFieldEdit; fieldEdit.Name_2 = "Area"; fieldEdit.Type_2 = ESRI.ArcGIS.Geodatabase.esriFieldType.esriFieldTypeDouble; summaryFieldsEdit.set_Field(1, field); recordSetInit.CreateTable(summaryFields); ESRI.ArcGIS.Geodatabase.ICursor cursor = recordSetInit.Insert(); ESRI.ArcGIS.Geodatabase.IRowBuffer rowBuffer = recordSetInit.CreateRowBuffer(); // Copy the summary stats to the record set System.Collections.IDictionaryEnumerator summaryStatsEnumerator = summaryStatsDictionary.GetEnumerator(); while (summaryStatsEnumerator.MoveNext()) { rowBuffer.set_Value(0, summaryStatsEnumerator.Key); rowBuffer.set_Value(1, summaryStatsEnumerator.Value); cursor.InsertRow(rowBuffer); } return summaryStatsRecordSet; } private ESRI.ArcGIS.Display.ISimpleFillSymbol createFillSymbol() { ESRI.ArcGIS.Display.ISimpleLineSymbol simpleLineSymbol = new ESRI.ArcGIS.Display.SimpleLineSymbol(); ESRI.ArcGIS.Display.IRgbColor rgbColor = new ESRI.ArcGIS.Display.RgbColor(); rgbColor.Red = 0; rgbColor.Green = 255; rgbColor.Blue = 0; simpleLineSymbol.Color = rgbColor; simpleLineSymbol.Style = ESRI.ArcGIS.Display.esriSimpleLineStyle.esriSLSSolid; simpleLineSymbol.Width = 2; ESRI.ArcGIS.Display.ISimpleFillSymbol simpleFillSymbol = new ESRI.ArcGIS.Display.SimpleFillSymbol(); simpleFillSymbol.Outline = simpleLineSymbol; simpleFillSymbol.Style = ESRI.ArcGIS.Display.esriSimpleFillStyle.esriSFSHollow; return simpleFillSymbol; } #endregion #region IObjectConstruct Members public void Construct(ESRI.ArcGIS.esriSystem.IPropertySet props) { try { m_layerName = props.GetProperty("LayerName") as string; m_fieldName = props.GetProperty("FieldName") as string; } catch (Exception ex) { m_log.AddMessage(1, 8000, "SpatialQuerySOE custom error. Error reading properties: " + ex.Message + " " + props.Count.ToString()); return; } try { // Get the map underlying the map service and the IGeoFeatureLayers contained in the map ESRI.ArcGIS.Carto.IMapServer mapServer = (ESRI.ArcGIS.Carto.IMapServer) m_ServerObjectHelper.ServerObject; ESRI.ArcGIS.Carto.IMapServerObjects mapServerObjects = (ESRI.ArcGIS.Carto.IMapServerObjects) mapServer; ESRI.ArcGIS.Carto.IMap map = mapServerObjects.get_Map(mapServer.DefaultMapName); ESRI.ArcGIS.esriSystem.UID layerTypeID = new ESRI.ArcGIS.esriSystem.UIDClass(); layerTypeID.Value = "{E156D7E5-22AF-11D3-9F99-00C04F6BC78E}"; ESRI.ArcGIS.Carto.IEnumLayer enumLayer = map.get_Layers(layerTypeID, true); enumLayer.Reset(); // Get the layer specified as the SOE layer while ((m_featureLayer = enumLayer.Next() as ESRI.ArcGIS.Carto.IFeatureLayer) != null) { if (m_featureLayer.Name == m_layerName) break; } if (m_featureLayer == null) { m_log.AddMessage(1, 8000, "SpatialQuerySOE custom error: Layer " + m_layerName + " not found."); return; } // Make sure the layer contains the field specified by the SOE's configuration if (m_featureLayer.FeatureClass.FindField(m_fieldName) == -1) m_log.AddMessage(1, 8000, "SpatialQuerySOE custom error: Field " + m_fieldName + " not found in layer " + m_layerName); else m_log.AddMessage(3, 8000, "SpatialQuerySOE successfully initialized."); } catch (Exception ex) { m_log.AddMessage(1, 8000, "SpatialQuerySOE custom error: Failed to initialize extension: " + ex.Message + "::" + ex.StackTrace.Length.ToString()); } } #endregion #region ILogSupport Members public void InitLogging(ESRI.ArcGIS.esriSystem.ILog log) { m_log = log; } #endregion #region IObjectActivate Members void ESRI.ArcGIS.esriSystem.IObjectActivate.Activate() { m_log.AddMessage(3, 8000, "SpatialQuerySOE custom message. Activate called"); } void ESRI.ArcGIS.esriSystem.IObjectActivate.Deactivate() { m_log.AddMessage(3, 8000, "SpatialQuerySOE custom message. Deactivate called"); } #endregion } }
[Visual Basic .NET]
Extension.vb
Imports Microsoft.VisualBasic Imports System Imports System.Runtime.InteropServices Imports System.EnterpriseServices Namespace SpatialQuerySOE_VBNet ''' <summary> ''' Implementation of the Spatial Query SOE. ''' </summary> <AutomationProxy(True), ClassInterface(ClassInterfaceType.None), Guid("3896A0F5-1028-489c-81CD-F7757D117C9E")> _ Public Class Extension Inherits ServicedComponent Implements SpatialQuerySOE.Interfaces_VBNet.IExtension, ESRI.ArcGIS.Server.IServerObjectExtension, ESRI.ArcGIS.esriSystem.IObjectConstruct, ESRI.ArcGIS.esriSystem.ILogSupport, ESRI.ArcGIS.esriSystem.IObjectActivate #Region "Member Variables" Private m_ServerObjectHelper As ESRI.ArcGIS.Server.IServerObjectHelper Private m_featureLayer As ESRI.ArcGIS.Carto.IFeatureLayer Private m_layerName As String Private m_fieldName As String Private m_log As ESRI.ArcGIS.esriSystem.ILog #End Region #Region "IServerObjectExtension Members" Public Sub Init(ByVal pSOH As ESRI.ArcGIS.Server.IServerObjectHelper) Implements ESRI.ArcGIS.Server.IServerObjectExtension.Init m_ServerObjectHelper = pSOH m_log.AddMessage(3, 8000, "SpatialQuerySOE custom message. Init called") End Sub Public Sub Shutdown() Implements ESRI.ArcGIS.Server.IServerObjectExtension.Shutdown m_log.AddMessage(3, 8000, "SpatialQuerySOE custom message. Shutdown called") m_ServerObjectHelper = Nothing m_featureLayer = Nothing m_log = Nothing End Sub #End Region #Region "SpatialQuerySOE.Interfaces_VBNet.IExtension Members" Public Function QueryPoint(ByVal point As ESRI.ArcGIS.Geometry.IPoint, ByVal distance As Double) As SpatialQuerySOE.Interfaces_VBNet.IResults Implements SpatialQuerySOE.Interfaces_VBNet.IExtension.QueryPoint If m_featureLayer Is Nothing Then m_log.AddMessage(1, 8000, "SpatialQuerySOE custom error: layer not found") Return Nothing End If Dim featureClass As ESRI.ArcGIS.Geodatabase.IFeatureClass = m_featureLayer.FeatureClass ' buffer the point Dim topologicalOperator As ESRI.ArcGIS.Geometry.ITopologicalOperator = CType(point, ESRI.ArcGIS.Geometry.ITopologicalOperator) Dim queryGeometry As ESRI.ArcGIS.Geometry.IGeometry = topologicalOperator.Buffer(distance) ' query the feature class Dim spatialFilter As ESRI.ArcGIS.Geodatabase.ISpatialFilter = New ESRI.ArcGIS.Geodatabase.SpatialFilter() spatialFilter.Geometry = queryGeometry spatialFilter.SpatialRel = ESRI.ArcGIS.Geodatabase.esriSpatialRelEnum.esriSpatialRelIntersects spatialFilter.GeometryField = featureClass.ShapeFieldName Dim resultsFeatureCursor As ESRI.ArcGIS.Geodatabase.IFeatureCursor = featureClass.Search(spatialFilter, True) ' loop thourgh the features, clip each geometry to the buffer ' and total areas by attribute value topologicalOperator = CType(queryGeometry, ESRI.ArcGIS.Geometry.ITopologicalOperator) Dim classFieldIndex As Integer = featureClass.FindField(m_fieldName) Dim summaryStatsDictionary As New System.Collections.Specialized.ListDictionary() ' create the symbol and graphic elements collection for the graphics Dim simpleFillSymbol As ESRI.ArcGIS.Display.ISimpleFillSymbol = createFillSymbol() Dim resultsGraphics As ESRI.ArcGIS.Carto.IGraphicElements = New ESRI.ArcGIS.Carto.GraphicElements() Dim resultsFeature As ESRI.ArcGIS.Geodatabase.IFeature resultsFeature = resultsFeatureCursor.NextFeature() Do While resultsFeature IsNot Nothing ' create the graphic Dim fillShapeElement As ESRI.ArcGIS.Carto.IFillShapeElement = TryCast(New ESRI.ArcGIS.Carto.PolygonElement, ESRI.ArcGIS.Carto.IFillShapeElement) Dim element As ESRI.ArcGIS.Carto.IElement = TryCast(fillShapeElement, ESRI.ArcGIS.Carto.IElement) ' clip the geometry Dim clippedResultsGeometry As ESRI.ArcGIS.Geometry.IGeometry = topologicalOperator.Intersect(resultsFeature.Shape, ESRI.ArcGIS.Geometry.esriGeometryDimension.esriGeometry2Dimension) element.Geometry = clippedResultsGeometry fillShapeElement.Symbol = simpleFillSymbol Dim resultsGraphicElement As ESRI.ArcGIS.Carto.IGraphicElement = TryCast(fillShapeElement, ESRI.ArcGIS.Carto.IGraphicElement) resultsGraphics.Add(resultsGraphicElement) ' get statistics and add to dictionary Dim area As ESRI.ArcGIS.Geometry.IArea = TryCast(clippedResultsGeometry, ESRI.ArcGIS.Geometry.IArea) Dim resultsClass As String = TryCast(resultsFeature.Value(classFieldIndex), String) ' If the class is already in the dictionary, add the current feature's area to the existing entry If summaryStatsDictionary.Contains(resultsClass) Then summaryStatsDictionary(resultsClass) = CDbl(summaryStatsDictionary(resultsClass)) + area.Area Else summaryStatsDictionary(resultsClass) = area.Area End If resultsFeature = resultsFeatureCursor.NextFeature() Loop ' create the summary statistics recordset Dim summaryStatsRecordSet As ESRI.ArcGIS.Geodatabase.IRecordSet = createSummaryRecordSet(summaryStatsDictionary) ' create the results object Dim results As SpatialQuerySOE.Interfaces_VBNet.IResults = New Results() results.ResultsGraphics = resultsGraphics results.SummaryStatistics = summaryStatsRecordSet Return results End Function Private Function createSummaryRecordSet(ByVal summaryStatsDictionary As System.Collections.Specialized.ListDictionary) As ESRI.ArcGIS.Geodatabase.IRecordSet ' initialize the summary statistics record set Dim summaryStatsRecordSet As ESRI.ArcGIS.Geodatabase.IRecordSet = New ESRI.ArcGIS.Geodatabase.RecordSet() Dim recordSetInit As ESRI.ArcGIS.Geodatabase.IRecordSetInit = TryCast(summaryStatsRecordSet, ESRI.ArcGIS.Geodatabase.IRecordSetInit) Dim summaryFields As ESRI.ArcGIS.Geodatabase.IFields = New ESRI.ArcGIS.Geodatabase.Fields() Dim summaryFieldsEdit As ESRI.ArcGIS.Geodatabase.IFieldsEdit = TryCast(summaryFields, ESRI.ArcGIS.Geodatabase.IFieldsEdit) summaryFieldsEdit.FieldCount_2 = 2 Dim field As ESRI.ArcGIS.Geodatabase.IField = New ESRI.ArcGIS.Geodatabase.Field() Dim fieldEdit As ESRI.ArcGIS.Geodatabase.IFieldEdit = TryCast(field, ESRI.ArcGIS.Geodatabase.IFieldEdit) fieldEdit.Name_2 = "Type" fieldEdit.Type_2 = ESRI.ArcGIS.Geodatabase.esriFieldType.esriFieldTypeString fieldEdit.Length_2 = 50 summaryFieldsEdit.Field_2(0) = field field = New ESRI.ArcGIS.Geodatabase.Field() fieldEdit = TryCast(field, ESRI.ArcGIS.Geodatabase.IFieldEdit) fieldEdit.Name_2 = "Area" fieldEdit.Type_2 = ESRI.ArcGIS.Geodatabase.esriFieldType.esriFieldTypeDouble summaryFieldsEdit.Field_2(1) = field recordSetInit.CreateTable(summaryFields) Dim cursor As ESRI.ArcGIS.Geodatabase.ICursor = recordSetInit.Insert() Dim rowBuffer As ESRI.ArcGIS.Geodatabase.IRowBuffer = recordSetInit.CreateRowBuffer() ' Copy the summary stats to the record set Dim summaryStatsEnumerator As System.Collections.IDictionaryEnumerator = summaryStatsDictionary.GetEnumerator() Do While summaryStatsEnumerator.MoveNext() rowBuffer.Value(0) = summaryStatsEnumerator.Key rowBuffer.Value(1) = summaryStatsEnumerator.Value cursor.InsertRow(rowBuffer) Loop Return summaryStatsRecordSet End Function Private Function createFillSymbol() As ESRI.ArcGIS.Display.ISimpleFillSymbol Dim simpleLineSymbol As ESRI.ArcGIS.Display.ISimpleLineSymbol = New ESRI.ArcGIS.Display.SimpleLineSymbol() Dim rgbColor As ESRI.ArcGIS.Display.IRgbColor = New ESRI.ArcGIS.Display.RgbColor() rgbColor.Red = 0 rgbColor.Green = 255 rgbColor.Blue = 0 simpleLineSymbol.Color = rgbColor simpleLineSymbol.Style = ESRI.ArcGIS.Display.esriSimpleLineStyle.esriSLSSolid simpleLineSymbol.Width = 2 Dim simpleFillSymbol As ESRI.ArcGIS.Display.ISimpleFillSymbol = New ESRI.ArcGIS.Display.SimpleFillSymbol() simpleFillSymbol.Outline = simpleLineSymbol simpleFillSymbol.Style = ESRI.ArcGIS.Display.esriSimpleFillStyle.esriSFSHollow Return simpleFillSymbol End Function #End Region #Region "IObjectConstruct Members" Public Overloads Sub Construct(ByVal props As ESRI.ArcGIS.esriSystem.IPropertySet) Implements ESRI.ArcGIS.esriSystem.IObjectConstruct.Construct Try m_layerName = TryCast(props.GetProperty("LayerName"), String) m_fieldName = TryCast(props.GetProperty("FieldName"), String) Catch ex As Exception m_log.AddMessage(1, 8000, "SpatialQuerySOE custom error. Error reading properties: " & ex.Message & " " & props.Count.ToString()) Return End Try Try ' Get the map underlying the map service and the IGeoFeatureLayers contained in the map Dim mapServer As ESRI.ArcGIS.Carto.IMapServer = CType(m_ServerObjectHelper.ServerObject, ESRI.ArcGIS.Carto.IMapServer) Dim mapServerObjects As ESRI.ArcGIS.Carto.IMapServerObjects = CType(mapServer, ESRI.ArcGIS.Carto.IMapServerObjects) Dim map As ESRI.ArcGIS.Carto.IMap = mapServerObjects.Map(mapServer.DefaultMapName) Dim layerTypeID As ESRI.ArcGIS.esriSystem.UID = New ESRI.ArcGIS.esriSystem.UIDClass() layerTypeID.Value = "{E156D7E5-22AF-11D3-9F99-00C04F6BC78E}" Dim enumLayer As ESRI.ArcGIS.Carto.IEnumLayer = map.Layers(layerTypeID, True) enumLayer.Reset() ' Get the layer specified as the SOE layer m_featureLayer = TryCast(enumLayer.Next(), ESRI.ArcGIS.Carto.IFeatureLayer) Do While m_featureLayer IsNot Nothing If m_featureLayer.Name = m_layerName Then Exit Do End If m_featureLayer = TryCast(enumLayer.Next(), ESRI.ArcGIS.Carto.IFeatureLayer) Loop If m_featureLayer Is Nothing Then m_log.AddMessage(1, 8000, "SpatialQuerySOE custom error: Layer " & m_layerName & " not found.") Return End If ' Make sure the layer contains the field specified by the SOE's configuration If m_featureLayer.FeatureClass.FindField(m_fieldName) = -1 Then m_log.AddMessage(1, 8000, "SpatialQuerySOE custom error: Field " & m_fieldName & " not found in layer " & m_layerName) Else m_log.AddMessage(3, 8000, "SpatialQuerySOE successfully initialized.") End If Catch ex As Exception m_log.AddMessage(1, 8000, "SpatialQuerySOE custom error: Failed to initialize extension: " & ex.Message & "::" & ex.StackTrace.Length.ToString()) End Try End Sub #End Region #Region "ILogSupport Members" Public Sub InitLogging(ByVal log As ESRI.ArcGIS.esriSystem.ILog) Implements ESRI.ArcGIS.esriSystem.ILogSupport.InitLogging m_log = log End Sub #End Region #Region "IObjectActivate Members" Private Sub IObjectActivate_Activate() Implements ESRI.ArcGIS.esriSystem.IObjectActivate.Activate m_log.AddMessage(3, 8000, "SpatialQuerySOE custom message. Activate called") End Sub Private Sub Deactivate() Implements ESRI.ArcGIS.esriSystem.IObjectActivate.Deactivate m_log.AddMessage(3, 8000, "SpatialQuerySOE custom message. Deactivate called") End Sub #End Region End Class End Namespace