/// <summary>Registers all event metric definitions defined by attributes on the provided object or Type, /// and registers metric instances where EventMetricInstanceName attribute is also found (with a live object).</summary> /// <param name="metricData">An object or Type defining event metrics via attributes on itself or on its base types or interfaces.</param> /// <remarks> /// <para> /// This call ensures that the reflection scan of all members looking for /// attributes across the entire inheritance of an object instance or Type has been /// done (e.g. outside of a critical path) so that the first call to <see cref="Write(object)">Write</see> will not have to do that work within a critical path. /// Results are cached internally, so redundant calls to this method will not /// repeat the scan for types already scanned (including as part of a different /// top-level type). /// </para> /// <para> /// If a live object is given (not just a Type) then the member(s) decorated with /// an <see cref="EventMetricInstanceNameAttribute">EventMetricInstanceNameAttribute Class</see> /// will be queried and used to also register an event metric instance with the /// returned name /// </para> /// <para>If a Type is given instead of a live object, it can't be queried for instance /// name(s) and will only register the event metric definitions. Metric instances will /// still be created automatically as needed when Write is called.</para> /// </remarks> /// <seealso cref="Write(object)">Write Method</seealso> /// <exception caption="" cref="ArgumentNullException">Thrown if metricData is null.</exception> /// <exception caption="" cref="ArgumentException">The specified metricDataObjectType does not have an EventMetric attribute <br /> /// <br /> /// -or- <br /> /// <br /> /// The specified Type does not have a usable EventMetric attribute, so it can't be used to define an event metric.<br /> /// <br /> /// -or- <br /> /// <br /> /// The specified Type's EventMetric has an empty metric namespace which is not allowed, so no metric can be defined.<br /> /// <br /> /// -or- <br /> /// <br /> /// The specified Type's EventMetric has an empty metric category name which is not allowed, so no metric can be defined.<br /> /// <br /> /// -or- <br /> /// <br /> /// The specified Type's EventMetric has an empty metric counter name which is not allowed, so no metric can be defined.<br /> /// <br /> /// -or- <br /> /// <br /> /// The specified Type's EventMetric attribute's 3-part Key is already used for a metric definition which is not an event metric.</exception> /// <example> /// See the <see cref="EventMetric">EventMetric Class Overview</see> for an example. /// <code title="" description="" lang="neutral"></code></example> public static void Register(object metricData) { //we need a live object, not a null object or we'll fail if (metricData == null) { throw new ArgumentNullException(nameof(metricData)); } // Register all of the event metric definitions it contains, object or Type: EventMetricDefinition[] definitions = EventMetricDefinition.RegisterAll(metricData); if ((metricData is Type) == false) { // They gave us a live object, not just a Type, so see if there are metric instances we can register. foreach (EventMetricDefinition definition in definitions) { if (definition.IsBound && definition.NameBound) { string instanceName = definition.InvokeInstanceNameBinding(metricData); if (instanceName != null) // null means it didn't find one, so we won't register an instance. { // An empty string (meaning the found value was null or empty) will be registered (same as null). Register(definition, instanceName); } } } } }