/// <summary>
        ///     Joins attributes from one feature to another based on the spatial relationship. The target features and the joined
        ///     attributes from the join features are written to the output feature class.
        /// </summary>
        /// <param name="source">
        ///     The source features and the attributes from the joined features are transferred to the output
        ///     feature class. However, a subset of attributes can be defined in the field map parameter.
        /// </param>
        /// <param name="join">The attributes from the join features are joined to the attributes of the source features.</param>
        /// <param name="tableName">A new feature class containing the attributes of the target and join features.</param>
        /// <param name="operation">
        ///     Determines how joins between the target features and join features will be handled in the
        ///     output feature class if multiple join features are found that have the same spatial relationship with a single
        ///     target feature.
        /// </param>
        /// <param name="isOuterJoin">
        ///     if set to <c>true</c> if all target features will be maintained in the output feature class
        ///     (known as outer join), or only those that have the specified spatial relationship with the join features (inner
        ///     join).
        /// </param>
        /// <param name="option">Defines the criteria used to match rows.</param>
        /// <param name="fieldMappings">The attribute fields will be in the output feature class.</param>
        /// <param name="searchRadius">
        ///     Join features within this distance of a target feature will be considered for the spatial
        ///     join.
        /// </param>
        /// <param name="trackCancel">The track cancel.</param>
        /// <param name="eventHandler">The event handler.</param>
        /// <returns>Returns a <see cref="IFeatureClass" /> representing the feature class of the joined data.</returns>
        public static IFeatureClass Join(this IFeatureClass source, IFeatureClass join, string tableName, JoinOperation operation, bool isOuterJoin, SpatialOperation option, IGpFieldMappingsObject fieldMappings, double searchRadius, ITrackCancel trackCancel, IGeoProcessorEvents eventHandler)
        {
            var ds = (IDataset)source;

            SpatialJoin gp = new SpatialJoin();

            gp.join_operation = operation.ToDescription();
            gp.join_type      = isOuterJoin ? "KEEP_ALL" : "KEEP_COMMON";
            gp.match_option   = option.ToDescription();
            gp.field_mapping  = fieldMappings;
            gp.search_radius  = searchRadius;

            gp.target_features   = source;
            gp.join_features     = join;
            gp.out_feature_class = ds.Workspace.GetAbsolutePath(tableName);

            if (gp.Run(trackCancel, eventHandler) == esriJobStatus.esriJobSucceeded)
            {
                return(ds.Workspace.GetFeatureClass(tableName));
            }

            return(null);
        }