/// <summary>
        /// Create a new metric packet with the specified unique name.
        /// </summary>
        /// <remarks>At any one time there should only be one metric with a given name.
        /// This name is used to correlate metrics between sessions.</remarks>
        /// <param name="metricDefinitionPacket">The metric definition to create a metric instance for.</param>
        /// <param name="instanceName">The name of the metric instance, or an empty string ("") to create a default instance.</param>
        protected MetricPacket(MetricDefinitionPacket metricDefinitionPacket, string instanceName)
            : base(false)
        {
            //verify our input.  instance name can be null or an empty string; we'll coalesce all those cases to null
            if (metricDefinitionPacket == null)
            {
                throw new ArgumentNullException(nameof(metricDefinitionPacket));
            }

            DefinitionId = metricDefinitionPacket.ID; //it's really important we set this and not rely on people just picking up the metric packet for some of our other code

            if (string.IsNullOrEmpty(instanceName) == false)
            {
                InstanceName = instanceName.Trim();
            }

            //force empty strings to null.
            if (string.IsNullOrEmpty(InstanceName))
            {
                InstanceName = null;
            }

            //process setting our definition through the common routine.  This has to be AFTER we set our definition ID and instance name above.
            DefinitionPacket = metricDefinitionPacket;

            Persisted = false; // we haven't been written to the log yet.
        }
        /// <summary>
        /// Compares the current object with another object of the same type.
        /// </summary>
        /// <param name="other">The object to compare this object with.</param>
        /// <returns>Zero if the objects are equal, less than zero if this object is less than the other, more than zero if this object is more than the other.</returns>
        public int CompareTo(MetricDefinitionPacket other)
        {
            //quick identity comparison based on guid
            if (ID == other.ID)
            {
                return(0);
            }

            //Now we try to stort by name.  We already guard against uniqueness
            int compareResult = string.Compare(Name, other.Name, StringComparison.OrdinalIgnoreCase);

            return(compareResult);
        }
        /// <summary>
        /// Determines if the provided object is identical to this object.
        /// </summary>
        /// <param name="other">The object to compare this object to</param>
        /// <returns>True if the objects represent the same data.</returns>
        public bool Equals(MetricDefinitionPacket other)
        {
            //Careful - can be null
            if (other == null)
            {
                return(false); // since we're a live object we can't be equal.
            }

            return((MetricTypeName == other.MetricTypeName) &&
                   (CategoryName == other.CategoryName) &&
                   (CounterName == other.CounterName) &&
                   (SampleType == other.SampleType) &&
                   (Caption == other.Caption) &&
                   (Description == other.Description) &&
                   (Interval == other.Interval) &&
                   (base.Equals(other)));
        }
        public IPacket CreatePacket(PacketDefinition definition, IFieldReader reader)
        {
            IPacket packet;

            if (definition.TypeName == m_SampledMetricDefinitionPacketType)
            {
                //sampled metrics can't be created directly - they're an abstract class.
                throw new ArgumentOutOfRangeException(nameof(definition), definition.TypeName, "Sampled Metric objects can't be created, only derived classes can.");
            }

            //what we create varies by what specific definition they're looking for
            if (definition.TypeName == m_MetricDefinitionPacketType)
            {
                packet = new MetricDefinitionPacket(m_Session);
            }
            else if (definition.TypeName == m_EventMetricDefinitionPacketType)
            {
                packet = new EventMetricDefinitionPacket(m_Session);
            }
            else if (definition.TypeName == m_EventMetricValueDefinitionPacketType)
            {
                packet = new EventMetricValueDefinitionPacket(m_Session);
            }
            else if (definition.TypeName == m_CustomSampledMetricDefinitionPacketType)
            {
                packet = new CustomSampledMetricDefinitionPacket(m_Session);
            }
            else
            {
                //crap, we don't know what to do here.
                throw new ArgumentOutOfRangeException(nameof(definition), definition.TypeName, "This packet factory doesn't undersatnd how to create packets for the provided type.");
            }

            //this feels a little crazy, but you have to do your own read call here - we aren't just creating the packet
            //object, we actually have to make the standard call to have it read data...
            definition.ReadFields(packet, reader);

            return(packet);
        }