ConfigurationSetProcessorFactoryBase.cs (7096B)
1 // ----------------------------------------------------------------------------- 2 // <copyright file="ConfigurationSetProcessorFactoryBase.cs" company="Microsoft Corporation"> 3 // Copyright (c) Microsoft Corporation. Licensed under the MIT License. 4 // </copyright> 5 // ----------------------------------------------------------------------------- 6 7 namespace Microsoft.Management.Configuration.Processor.Factory 8 { 9 using System; 10 using System.Runtime.CompilerServices; 11 using Microsoft.Management.Configuration; 12 using Microsoft.Management.Configuration.Processor.DSCv3.Helpers; 13 using Microsoft.Management.Configuration.Processor.Set; 14 15 /// <summary> 16 /// IConfigurationSetProcessorFactory base implementation. 17 /// </summary> 18 internal abstract partial class ConfigurationSetProcessorFactoryBase : IDiagnosticsSink 19 { 20 private bool isCreateProcessorInvoked = false; 21 22 // Backing variables for properties that are restricted in limit mode. 23 private ConfigurationSet? limitationSet; 24 25 /// <summary> 26 /// Initializes a new instance of the <see cref="ConfigurationSetProcessorFactoryBase"/> class. 27 /// </summary> 28 public ConfigurationSetProcessorFactoryBase() 29 { 30 } 31 32 /// <summary> 33 /// Diagnostics event; useful for logging and/or verbose output. 34 /// </summary> 35 public event EventHandler<IDiagnosticInformation>? Diagnostics; 36 37 /// <summary> 38 /// Gets or sets the minimum diagnostic level to send. 39 /// </summary> 40 public DiagnosticLevel MinimumLevel { get; set; } = DiagnosticLevel.Informational; 41 42 /// <summary> 43 /// Gets or sets the limitation set. Limitation set can only be set once. 44 /// </summary> 45 public ConfigurationSet? LimitationSet 46 { 47 get 48 { 49 return this.limitationSet; 50 } 51 52 set 53 { 54 if (this.IsLimitMode()) 55 { 56 throw new InvalidOperationException("Setting LimitationSet in limit mode is invalid."); 57 } 58 59 this.limitationSet = value; 60 } 61 } 62 63 /// <summary> 64 /// Gets the configuration unit processor details for the given unit. 65 /// </summary> 66 /// <param name="incomingSet">Configuration Set.</param> 67 /// <returns>Configuration set processor.</returns> 68 public IConfigurationSetProcessor CreateSetProcessor(ConfigurationSet? incomingSet) 69 { 70 try 71 { 72 bool isLimitMode = this.IsLimitMode(); 73 this.OnDiagnostics(DiagnosticLevel.Informational, $"The set processor factory is running in limit mode: {isLimitMode}."); 74 75 this.CheckLimitMode(); 76 77 ConfigurationSet? set = isLimitMode ? this.limitationSet : incomingSet; 78 79 this.OnDiagnostics(DiagnosticLevel.Verbose, $"Creating set processor for `{set?.Name ?? "<null>"}`..."); 80 81 if (set != null && (set.Parameters.Count > 0 || set.Variables.Count > 0)) 82 { 83 this.OnDiagnostics(DiagnosticLevel.Error, $" Parameters/variables are not yet supported."); 84 throw new NotImplementedException(); 85 } 86 87 IConfigurationSetProcessor result = this.CreateSetProcessorInternal(set, isLimitMode); 88 89 this.OnDiagnostics(DiagnosticLevel.Verbose, "... done creating set processor."); 90 91 return result; 92 } 93 catch (Exception ex) 94 { 95 this.OnDiagnostics(DiagnosticLevel.Error, ex.ToString()); 96 throw; 97 } 98 } 99 100 /// <inheritdoc /> 101 void IDiagnosticsSink.OnDiagnostics(DiagnosticLevel level, string message) 102 { 103 this.OnDiagnostics(level, message); 104 } 105 106 /// <summary> 107 /// Sends diagnostics if appropriate. 108 /// </summary> 109 /// <param name="level">The level of this diagnostic message.</param> 110 /// <param name="message">The diagnostic message.</param> 111 internal void OnDiagnostics(DiagnosticLevel level, string message) 112 { 113 EventHandler<IDiagnosticInformation>? diagnostics = this.Diagnostics; 114 if (diagnostics != null && level >= this.MinimumLevel) 115 { 116 this.InvokeDiagnostics(diagnostics, level, message); 117 } 118 } 119 120 /// <summary> 121 /// Determines if diagnostics are enabled. 122 /// This allows optimizing out string construction for some cases. 123 /// </summary> 124 /// <returns>True if diagnostics are enabled; false if not.</returns> 125 protected bool AreDiagnosticsEnabled() 126 { 127 return this.Diagnostics != null; 128 } 129 130 /// <summary> 131 /// Gets the configuration unit processor details for the given unit. 132 /// </summary> 133 /// <param name="set">Configuration Set.</param> 134 /// <param name="isLimitMode">Whether the processor should be in limit mode.</param> 135 /// <returns>Configuration set processor.</returns> 136 protected abstract IConfigurationSetProcessor CreateSetProcessorInternal(ConfigurationSet? set, bool isLimitMode); 137 138 /// <summary> 139 /// Gets a value indicating whether the factory is operation in limit mode. 140 /// </summary> 141 /// <returns>True if the factory is in limit mode, false otherwise.</returns> 142 protected bool IsLimitMode() 143 { 144 return this.limitationSet != null; 145 } 146 147 /// <summary> 148 /// Sends diagnostics to the given handler. 149 /// </summary> 150 /// <param name="diagnostics">The handler to invoke.</param> 151 /// <param name="level">The level of this diagnostic message.</param> 152 /// <param name="message">The diagnostic message.</param> 153 private void InvokeDiagnostics(EventHandler<IDiagnosticInformation> diagnostics, DiagnosticLevel level, string message) 154 { 155 Helpers.DiagnosticInformation information = new () 156 { 157 Level = level, 158 Message = message, 159 }; 160 diagnostics.Invoke(this, information); 161 } 162 163 [MethodImpl(MethodImplOptions.Synchronized)] 164 private void CheckLimitMode() 165 { 166 if (!this.IsLimitMode()) 167 { 168 return; 169 } 170 171 if (this.isCreateProcessorInvoked) 172 { 173 this.OnDiagnostics(DiagnosticLevel.Error, "CreateSetProcessor is already invoked in limit mode."); 174 throw new InvalidOperationException("CreateSetProcessor is already invoked in limit mode."); 175 } 176 else 177 { 178 this.isCreateProcessorInvoked = true; 179 } 180 } 181 } 182 }