| File: System\Diagnostics\TraceUtils.cs | Web Access |
| Project: src\runtime\src\libraries\System.Configuration.ConfigurationManager\src\System.Configuration.ConfigurationManager.csproj (System.Configuration.ConfigurationManager) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.Collections; using System.Collections.Specialized; using System.Configuration; using System.Globalization; using System.IO; using System.Reflection; using System.Runtime.Versioning; namespace System.Diagnostics { internal static class TraceUtils { private const string SystemDiagnostics = "System.Diagnostics."; internal static object GetRuntimeObject(string className, Type baseType, string initializeData) { object newObject = null; Type objectType = null; if (className.Length == 0) { throw new ConfigurationErrorsException(SR.EmptyTypeName_NotAllowed); } if (className.StartsWith(SystemDiagnostics)) { // Since the config file likely has just the FullName without the assembly name, // map the FullName to the built in types. objectType = MapToBuiltInTypes(className); } if (objectType == null) { objectType = Type.GetType(className); if (objectType == null) { throw new ConfigurationErrorsException(SR.Format(SR.Could_not_find_type, className)); } } if (!baseType.IsAssignableFrom(objectType)) throw new ConfigurationErrorsException(SR.Format(SR.Incorrect_base_type, className, baseType.FullName)); Exception innerException = null; try { if (string.IsNullOrEmpty(initializeData)) { if (IsOwnedTL(objectType)) throw new ConfigurationErrorsException(SR.TL_InitializeData_NotSpecified); // Create an object with parameterless constructor. ConstructorInfo ctorInfo = objectType.GetConstructor(Array.Empty<Type>()); if (ctorInfo == null) throw new ConfigurationErrorsException(SR.Format(SR.Could_not_get_constructor, className)); newObject = ctorInfo.Invoke(Array.Empty<object>()); } else { // Create an object with a one-string constructor. // First look for a string constructor. ConstructorInfo ctorInfo = objectType.GetConstructor(new Type[] { typeof(string) }); if (ctorInfo != null) { // Special case to enable specifying relative path to trace file from config for // our own TextWriterTraceListener derivatives. We will prepend it with fullpath // prefix from config file location. if (IsOwnedTextWriterTL(objectType)) { if ((initializeData[0] != Path.DirectorySeparatorChar) && (initializeData[0] != Path.AltDirectorySeparatorChar) && !Path.IsPathRooted(initializeData)) { string filePath = DiagnosticsConfiguration.ConfigFilePath; if (!string.IsNullOrEmpty(filePath)) { string dirPath = Path.GetDirectoryName(filePath); if (dirPath != null) initializeData = Path.Combine(dirPath, initializeData); } } } newObject = ctorInfo.Invoke(new object[] { initializeData }); } else { // Now look for another 1 param constructor. ConstructorInfo[] ctorInfos = objectType.GetConstructors(); if (ctorInfos == null) { throw new ConfigurationErrorsException(SR.Format(SR.Could_not_get_constructor, className)); } for (int i = 0; i < ctorInfos.Length; i++) { ParameterInfo[] ctorparams = ctorInfos[i].GetParameters(); if (ctorparams.Length == 1) { Type paramtype = ctorparams[0].ParameterType; try { object convertedInitializeData = ConvertToBaseTypeOrEnum(initializeData, paramtype); newObject = ctorInfos[i].Invoke(new object[] { convertedInitializeData }); break; } catch (TargetInvocationException tiexc) { Debug.Assert(tiexc.InnerException != null, "ill-formed TargetInvocationException!"); innerException = tiexc.InnerException; } catch (Exception e) { innerException = e; // Ignore exceptions for now. If we don't have a newObject at the end, then we'll throw. } } } } } } catch (TargetInvocationException tiexc) { Debug.Assert(tiexc.InnerException != null, "ill-formed TargetInvocationException!"); innerException = tiexc.InnerException; } if (newObject == null) { if (innerException != null) { throw new ConfigurationErrorsException(SR.Format(SR.Could_not_create_type_instance, className), innerException); } throw new ConfigurationErrorsException(SR.Format(SR.Could_not_create_type_instance, className)); } return newObject; } private static Type MapToBuiltInTypes(string className) { string name = className.Substring(SystemDiagnostics.Length); switch (name) { // Types in System.Diagnostics.TraceSource.dll: case nameof(DefaultTraceListener): return typeof(DefaultTraceListener); case nameof(SourceFilter): return typeof(SourceFilter); case nameof(EventTypeFilter): return typeof(EventTypeFilter); case nameof(BooleanSwitch): return typeof(BooleanSwitch); case nameof(TraceSwitch): return typeof(TraceSwitch); case nameof(SourceSwitch): return typeof(SourceSwitch); // Types in System.Diagnostics.TextWriterTraceListener: case nameof(ConsoleTraceListener): return typeof(ConsoleTraceListener); case nameof(DelimitedListTraceListener): return typeof(DelimitedListTraceListener); case nameof(XmlWriterTraceListener): return typeof(XmlWriterTraceListener); case nameof(TextWriterTraceListener): return typeof(TextWriterTraceListener); // Types in System.Diagnostics.EventLog.dll: case nameof(EventLogTraceListener): return typeof(EventLogTraceListener); default: return null; } } // Our own tracelisteners that needs extra config validation. internal static bool IsOwnedTL(Type type) { return typeof(EventLogTraceListener) == type || IsOwnedTextWriterTL(type); } internal static bool IsOwnedTextWriterTL(Type type) { return (typeof(XmlWriterTraceListener) == type) || (typeof(DelimitedListTraceListener) == type) || (typeof(TextWriterTraceListener) == type); } private static object ConvertToBaseTypeOrEnum(string value, Type type) { return type.IsEnum ? Enum.Parse(type, value, false) : Convert.ChangeType(value, type, CultureInfo.InvariantCulture); } // Copy the StringDictionary to another StringDictionary. // This is not as efficient as directly setting the property, but it avoids having to expose a public setter on the property. internal static void CopyStringDictionary(StringDictionary source, StringDictionary dest) { dest.Clear(); foreach (string key in source.Keys) { dest[key] = source[key]; } } } }