Fix IDE0025 (use expression body for properties)
[mono-project.git] / netcore / System.Private.CoreLib / shared / System / Diagnostics / Tracing / TraceLogging / TraceLoggingTypeInfo.cs
blobb5c0067cbb72cf0e7759ef6c14df8d9f7f10b9f0
1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
5 using System;
6 using System.Collections.Generic;
8 #if !ES_BUILD_AGAINST_DOTNET_V35
9 using Contract = System.Diagnostics.Contracts.Contract;
10 #else
11 using Contract = Microsoft.Diagnostics.Contracts.Internal.Contract;
12 #endif
14 #if ES_BUILD_STANDALONE
15 namespace Microsoft.Diagnostics.Tracing
16 #else
17 namespace System.Diagnostics.Tracing
18 #endif
20 /// <summary>
21 /// TraceLogging: used when implementing a custom TraceLoggingTypeInfo.
22 /// Non-generic base class for TraceLoggingTypeInfo&lt;DataType>. Do not derive
23 /// from this class. Instead, derive from TraceLoggingTypeInfo&lt;DataType>.
24 /// </summary>
25 internal abstract class TraceLoggingTypeInfo
27 private readonly string name;
28 private readonly EventKeywords keywords;
29 private readonly EventLevel level = (EventLevel)(-1);
30 private readonly EventOpcode opcode = (EventOpcode)(-1);
31 private readonly EventTags tags;
32 private readonly Type dataType;
33 private readonly Func<object?, PropertyValue> propertyValueFactory;
35 internal TraceLoggingTypeInfo(Type dataType)
37 if (dataType == null)
39 throw new ArgumentNullException(nameof(dataType));
42 this.name = dataType.Name;
43 this.dataType = dataType;
44 this.propertyValueFactory = PropertyValue.GetFactory(dataType);
47 internal TraceLoggingTypeInfo(
48 Type dataType,
49 string name,
50 EventLevel level,
51 EventOpcode opcode,
52 EventKeywords keywords,
53 EventTags tags)
55 if (dataType == null)
57 throw new ArgumentNullException(nameof(dataType));
60 if (name == null)
62 throw new ArgumentNullException(nameof(name));
65 Statics.CheckName(name);
67 this.name = name;
68 this.keywords = keywords;
69 this.level = level;
70 this.opcode = opcode;
71 this.tags = tags;
72 this.dataType = dataType;
73 this.propertyValueFactory = PropertyValue.GetFactory(dataType);
76 /// <summary>
77 /// Gets the name to use for the event if this type is the top-level type,
78 /// or the name to use for an implicitly-named field.
79 /// Never null.
80 /// </summary>
81 public string Name => this.name;
83 /// <summary>
84 /// Gets the event level associated with this type. Any value in the range 0..255
85 /// is an associated event level. Any value outside the range 0..255 is invalid and
86 /// indicates that this type has no associated event level.
87 /// </summary>
88 public EventLevel Level => this.level;
90 /// <summary>
91 /// Gets the event opcode associated with this type. Any value in the range 0..255
92 /// is an associated event opcode. Any value outside the range 0..255 is invalid and
93 /// indicates that this type has no associated event opcode.
94 /// </summary>
95 public EventOpcode Opcode => this.opcode;
97 /// <summary>
98 /// Gets the keyword(s) associated with this type.
99 /// </summary>
100 public EventKeywords Keywords => this.keywords;
102 /// <summary>
103 /// Gets the event tags associated with this type.
104 /// </summary>
105 public EventTags Tags => this.tags;
107 internal Type DataType => this.dataType;
109 internal Func<object?, PropertyValue> PropertyValueFactory => this.propertyValueFactory;
111 /// <summary>
112 /// When overridden by a derived class, writes the metadata (schema) for
113 /// this type. Note that the sequence of operations in WriteMetadata should be
114 /// essentially identical to the sequence of operations in
115 /// WriteData/WriteObjectData. Otherwise, the metadata and data will not match,
116 /// which may cause trouble when decoding the event.
117 /// </summary>
118 /// <param name="collector">
119 /// The object that collects metadata for this object's type. Metadata is written
120 /// by calling methods on the collector object. Note that if the type contains
121 /// sub-objects, the implementation of this method may need to call the
122 /// WriteMetadata method for the type of the sub-object, e.g. by calling
123 /// TraceLoggingTypeInfo&lt;SubType&gt;.Instance.WriteMetadata(...).
124 /// </param>
125 /// <param name="name">
126 /// The name of the property that contains an object of this type, or null if this
127 /// object is being written as a top-level object of an event. Typical usage
128 /// is to pass this value to collector.AddGroup.
129 /// </param>
130 /// <param name="format">
131 /// The format attribute for the field that contains an object of this type.
132 /// </param>
133 public abstract void WriteMetadata(
134 TraceLoggingMetadataCollector collector,
135 string? name,
136 EventFieldFormat format);
138 /// <summary>
139 /// Refer to TraceLoggingTypeInfo.WriteObjectData for information about this
140 /// method.
141 /// </summary>
142 /// <param name="collector">
143 /// Refer to TraceLoggingTypeInfo.WriteObjectData for information about this
144 /// method.
145 /// </param>
146 /// <param name="value">
147 /// Refer to TraceLoggingTypeInfo.WriteObjectData for information about this
148 /// method.
149 /// </param>
150 public abstract void WriteData(
151 TraceLoggingDataCollector collector,
152 PropertyValue value);
154 /// <summary>
155 /// Fetches the event parameter data for internal serialization.
156 /// </summary>
157 /// <param name="value"></param>
158 /// <returns></returns>
159 public virtual object? GetData(object? value)
161 return value;
164 [ThreadStatic] // per-thread cache to avoid synchronization
165 private static Dictionary<Type, TraceLoggingTypeInfo>? threadCache;
167 public static TraceLoggingTypeInfo GetInstance(Type type, List<Type>? recursionCheck)
169 Dictionary<Type, TraceLoggingTypeInfo> cache = threadCache ?? (threadCache = new Dictionary<Type, TraceLoggingTypeInfo>());
171 TraceLoggingTypeInfo? instance;
172 if (!cache.TryGetValue(type, out instance))
174 if (recursionCheck == null)
175 recursionCheck = new List<Type>();
176 int recursionCheckCount = recursionCheck.Count;
177 instance = Statics.CreateDefaultTypeInfo(type, recursionCheck);
178 cache[type] = instance;
179 recursionCheck.RemoveRange(recursionCheckCount, recursionCheck.Count - recursionCheckCount);
181 return instance;