public static void ToGdbObjectMsgList( [NotNull] IEnumerable <Feature> features, [NotNull] ICollection <GdbObjectMsg> resultGdbObjects, [NotNull] ICollection <ObjectClassMsg> resultGdbClasses) { Stopwatch watch = null; if (_msg.IsVerboseDebugEnabled) { watch = Stopwatch.StartNew(); } var classesByClassId = new Dictionary <long, FeatureClass>(); // Optimization (in Pro, the Map SR seems to be generally equal to the FCs SR, if they match) bool omitDetailedShapeSpatialRef = true; foreach (Feature feature in features) { FeatureClass featureClass = feature.GetTable(); Geometry shape = feature.GetShape(); // NOTE: The following calls are expensive: // - Geometry.GetShape() (internally, the feature's spatial creation seems costly) // - FeatureClassDefintion.GetSpatialReference() // In case of a large feature count, they should be avoided on a per-feature basis: if (!classesByClassId.ContainsKey(featureClass.GetID())) { resultGdbClasses.Add(ToObjectClassMsg(featureClass)); classesByClassId.Add(featureClass.GetID(), featureClass); SpatialReference featureClassSpatialRef = featureClass.GetDefinition().GetSpatialReference(); if (!SpatialReference.AreEqual( featureClassSpatialRef, shape.SpatialReference, false, true)) { omitDetailedShapeSpatialRef = false; } } else { // TODO: Better solution: hash class ID with workspace handle in ToObjectClassMsg() // Make sure they are from the same workspace to avoid conflicting class ids Assert.AreEqual(classesByClassId[featureClass.GetID()].GetDatastore().Handle, featureClass.GetDatastore().Handle, "Conflicting class id from different workspaces. Please report."); } resultGdbObjects.Add(ToGdbObjectMsg(feature, shape, omitDetailedShapeSpatialRef)); } _msg.DebugStopTiming(watch, "Converted {0} features to DTOs", resultGdbObjects.Count); }