English

How To: Use IFeatureProgress and IReplicaProgress properties in .NET

Summary

The IFeatureProgress and IReplicaProgress interfaces define properties that are not accessible through the .NET interop assembly 'event' interfaces. Instructions provided describe how to create helper classes as a workaround for this limitation.

Procedure

Outbound interfaces in COM libraries (e.g., IFeatureProgress, IObjectClassEvents) may define both methods and properties. When the tlbimp tool generates .NET interop assemblies based on these libraries, '_Event' interfaces are created that expose the methods as events, but discard the properties. In the geodatabase libraries, there are two interfaces affected by this: IFeatureProgress and IReplicaProgress. The IFeatureProgress_Event.Step and IReplicaProgress_Event.Startup events are both available, but of limited use without the additional information provided by the properties.

This article discusses the steps to build an IFeatureProgress helper class, but the steps to build a helper class for IReplicaProgress are very similar.

Note:
To successfully compile the code shown in this article, the following assemblies must be referenced by the solution, and 'using' statements must be added for their corresponding namespaces:
- ESRI.ArcGIS.Display
- ESRI.ArcGIS.Geodatabase
- ESRI.ArcGIS.GeoDatabaseDistributed
- ESRI.ArcGIS.Server
- ESRI.ArcGIS.System

  • Create a FeatureProgressHelper class that implements the IFeatureProgress interface. Implement each of the setter properties and the Step method to create some Console output (at least for the development stage). Have the IsCancelled getter return false for the time being.
    Code:
    private class FeatureProgressHelper : IFeatureProgress
    {
    private int featureCount = 0;

    private int stepValue = 0;

    String IFeatureProgress.FeatureClassName
    {
    set { Console.WriteLine("FeatureClassName: {0}", value); }
    }

    Boolean IFeatureProgress.IsCancelled
    {
    get { return false; }
    }

    int IFeatureProgress.MaxFeatures
    {
    set { Console.WriteLine("MaxFeatures: {0}", value); }
    }

    int IFeatureProgress.MinFeatures
    {
    set { Console.WriteLine("MinFeatures: {0}", value); }
    }

    int IFeatureProgress.Position
    {
    set { Console.WriteLine("Position: {0}", value); }
    }

    void IFeatureProgress.Step()
    {
    // Increment the number of features replicated and display the progress.
    featureCount += stepValue;
    Console.WriteLine("{0} features replicated.", featureCount);
    }

    int IFeatureProgress.StepValue
    {
    set { stepValue = value; }
    }
    }

  • To 'wire' these event handlers into an event source, it is necessary to use the IConnectionPointContainer interface, which is implemented by several classes, including FeatureDataConverter (in the Geodatabase library) and CheckOut (in the Distributed Geodatabase library). Once the correct connection point has been identified by GUID comparison, the connection point can be 'advised' that an instance of the helper class is going to handle events. This implementation demonstrates how to wire the helper class instance into a connection point in the constructor.
    Code:
    public FeatureProgressHelper(IConnectionPointContainer connectionPointContainer)
    {
    // Get the event source's connection points.
    IEnumConnectionPoints enumConnectionPoints = null;
    connectionPointContainer.EnumConnectionPoints(out enumConnectionPoints);
    enumConnectionPoints.Reset();

    // Iterate through the connection points until one for IFeatureProgress is found.
    IConnectionPoint connectionPoint = null;
    Guid featureProgressGuid = typeof(IFeatureProgress).GUID;
    uint pcFetched = 0;
    enumConnectionPoints.RemoteNext(1, out connectionPoint, out pcFetched);
    while (connectionPoint != null)
    {
    Guid connectionInterfaceGuid;
    connectionPoint.GetConnectionInterface(out connectionInterfaceGuid);
    if (connectionInterfaceGuid == featureProgressGuid)
    {
    break;
    }
    enumConnectionPoints.RemoteNext(1, out connectionPoint, out pcFetched);
    }

    // If IFeatureProgress wasn't found, throw an exception.
    if (connectionPoint == null)
    {
    throw new ArgumentException("An IFeatureProgress connection point could not be found.");
    }

    // Tie into the connection point.
    uint connectionPointCookie = 0;
    connectionPoint.Advise(this, out connectionPointCookie);
    }

  • To tie this helper class into an event source, cast the event source to the IConnectionPointContainer interface and create an instance of the helper class, passing the event source as an interface.
    Note:
    The following example uses the ReplicationAgent class. Prior to the 9.3 release, ReplicationAgent did not implement IConnectionPointContainer, meaning that this code fails at run time.


    Code:
    IReplicationAgent replicationAgent = new ReplicationAgentClass();
    IConnectionPointContainer connectionPointContainer = (IConnectionPointContainer)replicationAgent;
    FeatureProgressHelper featureProgressHelper = new FeatureProgressHelper(connectionPointContainer);

    // Create the replica...