I am currently writing a set of batch processing jobs using ArcObjects in C#.NET. I noticed that a lot of ESRI examples pile the code into one static class with each member declared inside each method scope.
I am considering using either a factory pattern or a singleton pattern for processing features. The intent is to wrap the unmanaged interfaces in instance classes to compartmentalize the code a bit and help with re-usability. These classes implement the IDisposable interface to help make sure everything is properly cleaned up after use.
Considering what you know about COM objects, could you please let me know if the following class looks effective? Is my expectation of reusability reasonable considering how COM works? I.e., If I encapsulate a COM member, will it provide the same benefit as a manged type, or is this adding unnecessary overhead? As far as I know, the only managed type I am using is the Geoprocessor class, IFeatureClass is unmanaged.
public class FeatureProcessing : ProcessBase, IDisposable
{
#region Fields
private IFeatureClass _FeatureClassObj;
private ITrackCancel2 _GPTrackCancel;
private Geoprocessor _GeoProcessor;
private bool _IsRunning = false;
#endregion Fields
#region Properties
public IFeatureClass FeatureClassObj
{
get
{
return _FeatureClassObj;
}
private set
{
_FeatureClassObj = value;
}
}
public bool IsRunning
{
get
{
return _IsRunning;
}
}
#endregion Properties
#region Constructor
public FeatureProcessing(IFeatureClass feature)
{
_FeatureClassObj = feature;
}
#endregion Constructor
#region Methods
public void Simplify(int footTollerance = 5, SimplifyAlgorithmTypes algorythmType = SimplifyAlgorithmTypes.POINT_REMOVE)
{
//FeatureClass tmpFeatureClass = new FeatureClass(null);
ESRI.ArcGIS.CartographyTools.SimplifyLine lineSimplify = new ESRI.ArcGIS.CartographyTools.SimplifyLine();
lineSimplify.in_features = _FeatureClassObj;
lineSimplify.out_feature_class = $"{_FeatureClassObj.AliasName}_Simplified";
lineSimplify.tolerance = footTollerance;
lineSimplify.algorithm = algorythmType.ToString();
RunGeoprocessingOperation(lineSimplify);
}
private void RunGeoprocessingOperation(IGPProcess gpProc)
{
_GeoProcessor = new Geoprocessor();
_GeoProcessor.OverwriteOutput = true;
_GeoProcessor.ToolExecuting += Gp_ToolExecuting;
_GeoProcessor.ToolExecuted += Gp_ToolExecuted;
_GeoProcessor.ProgressChanged += Gp_ProgressChanged;
IGeoProcessorResult2 gpResult = _GeoProcessor.Execute(gpProc, _GPTrackCancel) as
IGeoProcessorResult2;
}
private void Gp_ToolExecuting(object sender, ToolExecutingEventArgs e)
{
if (e.GPResult == null) return;
_IsRunning = true;
IGeoProcessorResult2 result = e.GPResult as IGeoProcessorResult2;
base.RaiseProcessEvent(ProcessEventTypes.INFO, $"GPTool: {result.Process.ToolName} started");
}
private void Gp_ToolExecuted(object sender, ToolExecutedEventArgs e)
{
_IsRunning = false;
}
private void Gp_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
base.RaiseProcessEvent(ProcessEventTypes.INFO, e.Message);
}
public void CancelRunningTask()
{
if (_IsRunning != false && _GPTrackCancel != null)
{
_GPTrackCancel.Cancel();
_IsRunning = false;
}
}
public void Dispose()
{
CancelRunningTask();
ReleaseCOMObj();
}
private void ReleaseCOMObj()
{
int refsLeft = 0;
if (_FeatureClassObj != null)
{
do { refsLeft = Marshal.ReleaseComObject(_FeatureClassObj); }
while (refsLeft > 0);
}
}
#endregion Methods
}