/// <summary> /// Initializes a new <see cref="StObjEngineConfiguration"/> from a <see cref="XElement"/>. /// </summary> /// <param name="e">The xml element.</param> public StObjEngineConfiguration(XElement e) { Throw.CheckNotNullArgument(e); // Global options. BasePath = (string?)e.Element(xBasePath); GeneratedAssemblyName = (string?)e.Element(xGeneratedAssemblyName); TraceDependencySorterInput = (bool?)e.Element(xTraceDependencySorterInput) ?? false; TraceDependencySorterOutput = (bool?)e.Element(xTraceDependencySorterOutput) ?? false; RevertOrderingNames = (bool?)e.Element(xRevertOrderingNames) ?? false; InformationalVersion = (string?)e.Element(xInformationalVersion); var sha1 = (string?)e.Element(xBaseSHA1); BaseSHA1 = sha1 != null?SHA1Value.Parse(sha1) : SHA1Value.Zero; ForceRun = (bool?)e.Element(xForceRun) ?? false; GlobalExcludedTypes = new HashSet <string>(FromXml(e, xGlobalExcludedTypes, xType)); // BinPaths. BinPaths = e.Elements(xBinPaths).Elements(xBinPath).Select(e => new BinPathConfiguration(e)).ToList(); // Aspects. Aspects = new List <IStObjEngineAspectConfiguration>(); foreach (var a in e.Elements(xAspect)) { string type = (string)a.AttributeRequired(xType); Type? tAspect = SimpleTypeFinder.WeakResolver(type, true); Debug.Assert(tAspect != null); IStObjEngineAspectConfiguration aspect = (IStObjEngineAspectConfiguration)Activator.CreateInstance(tAspect, a) !; Aspects.Add(aspect); } }
public StObjEngine(IActivityMonitor monitor, StObjEngineConfiguration config) { Throw.CheckNotNullArgument(monitor); Throw.CheckNotNullArgument(config); _monitor = monitor; _config = new RunningStObjEngineConfiguration(config); }
public CKTypeCollector(IActivityMonitor monitor, IServiceProvider serviceProvider, IDynamicAssembly tempAssembly, Func <IActivityMonitor, Type, bool>?typeFilter = null, IEnumerable <string>?names = null) { Throw.CheckNotNullArgument(monitor); Throw.CheckNotNullArgument(serviceProvider); Throw.CheckNotNullArgument(tempAssembly); _monitor = monitor; _typeFilter = typeFilter ?? ((m, type) => type.FullName != null); _tempAssembly = tempAssembly; _serviceProvider = serviceProvider; _assemblies = new HashSet <Assembly>(); _objectCollector = new Dictionary <Type, RealObjectClassInfo?>(); _regularTypeCollector = new Dictionary <Type, TypeAttributesCache?>(); _roots = new List <RealObjectClassInfo>(); _serviceCollector = new Dictionary <Type, AutoServiceClassInfo>(); _serviceRoots = new List <AutoServiceClassInfo>(); _serviceInterfaces = new Dictionary <Type, AutoServiceInterfaceInfo?>(); _multipleMappings = new Dictionary <Type, MultipleImpl>(); KindDetector = new CKTypeKindDetector(typeFilter); _pocoRegistrar = new PocoRegistrar((m, t) => (KindDetector.GetValidKind(m, t) & CKTypeKind.IsPoco) != 0, typeFilter: _typeFilter); _names = names == null || !names.Any() ? new[] { String.Empty } : names.ToArray(); }
/// <summary> /// Initializes a new <see cref="StObjCollector"/>. /// </summary> /// <param name="monitor">Logger to use. Can not be null.</param> /// <param name="serviceProvider">Service provider used for attribute constructor injection. Must not be null.</param> /// <param name="traceDepencySorterInput">True to trace in <paramref name="monitor"/> the input of dependency graph.</param> /// <param name="traceDepencySorterOutput">True to trace in <paramref name="monitor"/> the sorted dependency graph.</param> /// <param name="typeFilter">Optional type filter.</param> /// <param name="configurator">Used to configure items. See <see cref="IStObjStructuralConfigurator"/>.</param> /// <param name="valueResolver"> /// Used to explicitly resolve or alter StObjConstruct parameters and object ambient properties. /// See <see cref="IStObjValueResolver"/>. /// </param> /// <param name="names">Optional list of names for the final StObjMap. When null or empty, a single empty string is the default name.</param> public StObjCollector(IActivityMonitor monitor, IServiceProvider serviceProvider, bool traceDepencySorterInput = false, bool traceDepencySorterOutput = false, IStObjTypeFilter?typeFilter = null, IStObjStructuralConfigurator?configurator = null, IStObjValueResolver?valueResolver = null, IEnumerable <string>?names = null) { Throw.CheckNotNullArgument(monitor); _monitor = monitor; _tempAssembly = new DynamicAssembly(); Func <IActivityMonitor, Type, bool>?tFilter = null; if (typeFilter != null) { tFilter = typeFilter.TypeFilter; } _cc = new CKTypeCollector(_monitor, serviceProvider, _tempAssembly, tFilter, names); _configurator = configurator; _valueResolver = valueResolver; if (traceDepencySorterInput) { DependencySorterHookInput = i => i.Trace(monitor); } if (traceDepencySorterOutput) { DependencySorterHookOutput = i => i.Trace(monitor); } AddWellKnownServices(); }
/// <summary> /// Initializes a new <see cref="StObjMapAccessedEventArgs"/>. /// </summary> /// <param name="current">The current StObjMap. Must not be null.</param> /// <param name="deltaLastAccess">Time span from last access.</param> /// <param name="loadedTime">The current loaded time.</param> public StObjMapAccessedEventArgs(IStObjMap current, TimeSpan deltaLastAccess, TimeSpan loadedTime) { Throw.CheckNotNullArgument(current); Current = current; DeltaLastAccessTime = deltaLastAccess; CurrentLoadedTime = loadedTime; }
/// <summary> /// Opens a <see cref="LogReader"/> to read the content of a compressed or uncompressed stream. /// The stream will be closed when <see cref="LogReader.Dispose"/> will be called. /// </summary> /// <param name="seekableStream">Stream that must support Seek operations (<see cref="Stream.CanSeek"/> must be true).</param> /// <param name="dataOffset"> /// An optional offset where the stream position must be initially set: this is the position of an entry in the actual (potentially uncompressed stream), /// not the offset in the original stream. /// </param> /// <param name="filter">An optional <see cref="MulticastFilter"/>.</param> /// <returns>A <see cref="LogReader"/> that will close the file when disposed.</returns> /// <remarks> /// .ckmon files exist in different file versions, depending on headers. /// The file can be compressed using GZipStream, in which case the header will be the magic GZIP header: 1F 8B. /// New header (applies to version 5), the file will start with 43 4B 4D 4F 4E (CKMON in ASCII), followed by the version number, instead of only the version number. /// </remarks> public static LogReader Open(Stream seekableStream, long dataOffset = 0, MulticastFilter?filter = null) { Throw.CheckNotNullArgument(seekableStream); Throw.CheckArgument(seekableStream.CanSeek); LogReaderStreamInfo i = LogReaderStreamInfo.OpenStream(seekableStream); var s = i.LogStream; if (dataOffset > 0) { if (s.CanSeek) { s.Seek(dataOffset, SeekOrigin.Current); } else { var buffer = new byte[8192]; int toRead; while ((toRead = (int)Math.Min(8192, dataOffset)) > 0 && s.Read(buffer, 0, toRead) == toRead) { dataOffset -= toRead; } } } var r = new LogReader(s, i.Version, i.HeaderLength) { CurrentFilter = filter }; return(r); }
/// <summary> /// Initialization of the handler: computes the path. /// </summary> /// <param name="monitor"></param> public ValueTask <bool> ActivateAsync(IActivityMonitor monitor) { Throw.CheckNotNullArgument(monitor); using (monitor.OpenTrace($"Initializing BinaryFile handler (MaxCountPerFile = {_file.MaxCountPerFile}).")) { return(ValueTask.FromResult(_file.Initialize(monitor))); } }
/// <summary> /// Registers the map, the Real objects, singleton services and scoped services. /// Caution: this never throws, instead any exception is logged and false is returned. /// </summary> /// <param name="map">The map to register. Must not be null.</param> /// <returns> /// True on success, false if any <see cref="LogLevel.Fatal"/> or <see cref="LogLevel.Error"/> has been logged or if an exception has been thrown. /// </returns> public bool AddStObjMap(IStObjMap map) { bool result = true; using (Monitor.OnError(() => result = false)) using (Monitor.OpenInfo("Configuring Service collection from StObjMap.")) { try { Throw.CheckNotNullArgument(map); DoRegisterSingletonInstance(typeof(IStObjMap), map, isRealObject: true, isMultiple: false); map.StObjs.ConfigureServices(this); foreach (var o in map.StObjs.FinalImplementations) { DoRegisterSingletonInstance(o.ClassType, o.Implementation, isRealObject: true, isMultiple: false); foreach (var u in o.UniqueMappings) { DoRegisterSingletonInstance(u, o.Implementation, isRealObject: true, isMultiple: false); } foreach (var mult in o.MultipleMappings) { DoRegisterSingletonInstance(mult, o.Implementation, isRealObject: true, true); } } foreach (var s in map.Services.SimpleMappingList) { Register(s.ClassType, s.FinalType, s.IsScoped, allowMultipleRegistration: false); foreach (var u in s.UniqueMappings) { Register(u, s.FinalType, s.IsScoped, allowMultipleRegistration: false); } foreach (var mult in s.MultipleMappings) { Register(mult, s.FinalType, s.IsScoped, allowMultipleRegistration: true); } } foreach (var s in map.Services.ManualMappingList) { Register(s.ClassType, s.CreateInstance, s.IsScoped, allowMultipleRegistration: false); foreach (var u in s.UniqueMappings) { Register(u, s.CreateInstance, s.IsScoped, allowMultipleRegistration: false); } foreach (var mult in s.MultipleMappings) { Register(mult, s.CreateInstance, s.IsScoped, allowMultipleRegistration: true); } } } catch (Exception ex) { Monitor.Error("While registering StObjMap.", ex); } } return(result); }
public static StObjEngineResult Run(IActivityMonitor monitor, StObjCollectorResult result, StObjEngineConfiguration config) { Throw.CheckNotNullArgument(monitor); Throw.CheckNotNullArgument(result); Throw.CheckNotNullArgument(config); Throw.CheckArgument(config.BinPaths.Select(b => b.Path).Distinct().Count() == 1); var e = new StObjEngine(monitor, config); return(e.Run(new MonoResolver(result))); }
public KeyExchangeFailedEventArgs(IActivityMonitor monitor, ITrustedParty targetParty, KeyExchangeResultCode resultCode) : base(monitor) { Throw.CheckNotNullArgument(targetParty); Throw.CheckArgument(resultCode != KeyExchangeResultCode.Success); TargetParty = targetParty; ResultCode = resultCode; }
public PocoRegistrar(Func <IActivityMonitor, Type, bool> actualPocoPredicate, string @namespace = "CK.GPoco", Func <IActivityMonitor, Type, bool>?typeFilter = null) { Throw.CheckNotNullArgument(actualPocoPredicate); Throw.CheckNotNullArgument(@namespace); _actualPocoPredicate = actualPocoPredicate; _namespace = @namespace; _all = new Dictionary <Type, PocoType?>(); _result = new List <List <Type> >(); _typeFilter = typeFilter ?? ((m, type) => true); }
/// <summary> /// Applies a configuration. /// This is thread safe and can be called at any moment. /// </summary> /// <param name="configuration">The configuration to apply.</param> /// <param name="waitForApplication"> /// True to block until this configuration has been applied. /// Note that another (new) configuration may have already replaced the given configuration /// once this call ends. /// </param> public void ApplyConfiguration(GrandOutputConfiguration configuration, bool waitForApplication = false) { Throw.CheckNotNullArgument(configuration); if (!configuration.InternalClone) { configuration = configuration.Clone(); configuration.InternalClone = true; } _sink.ApplyConfiguration(configuration, waitForApplication); }
public KeyExchangeRequiredEventArgs(IActivityMonitor monitor, ITrustedParty targetParty, ReadOnlyMemory <byte> exchangeData, OneTimePassword?oneTimePassword) : base(monitor) { Throw.CheckNotNullArgument(targetParty); TargetParty = targetParty; ExchangeRequestData = exchangeData; OneTimePassword = oneTimePassword; }
/// <summary> /// Gets the <see cref="IStObjMap"/> if no error prevents its instantiation from /// the <see cref="StObjMapInfo"/>. /// This never throws: errors are logged (a new monitor is automatically managed when <paramref name="monitor"/> is null), /// and null is returned. /// This method like all the methods that manipulates StObjMapInfo are thread/concurrency safe. /// </summary> /// <param name="info">The info.</param> /// <param name="monitor">Optional monitor.</param> /// <returns>The loaded map or null on error.</returns> public static IStObjMap?GetStObjMap(StObjMapInfo info, IActivityMonitor?monitor = null) { Throw.CheckNotNullArgument(info); if (info.StObjMap != null || info.LoadError != null) { return(info.StObjMap); } lock ( _alreadyHandled ) { return(LockedGetStObjMapFromInfo(info, ref monitor)); } }
public void LogErrorAndWarnings(IActivityMonitor monitor) { Throw.CheckNotNullArgument(monitor); using (monitor.OpenTrace($"Collector summary:")) { if (PocoSupport == null) { monitor.Fatal($"Poco support failed!"); } RealObjects.LogErrorAndWarnings(monitor); AutoServices.LogErrorAndWarnings(monitor); } }
/// <summary> /// Initializes a new <see cref="ServiceRegister"/>. /// </summary> /// <param name="monitor">The monitor to use. Must not be null.</param> /// <param name="services">The service collection to configure.</param> /// <param name="startupServices"> /// Optional simple container that may provide startup services. This is not used to build IRealObject /// (they must be independent of any "dynamic" services), however registered services become available to /// any <see cref="StObjContextRoot.ConfigureServicesMethodName"/> methods by parameter injection. /// </param> public ServiceRegister(IActivityMonitor monitor, IServiceCollection services, SimpleServiceContainer?startupServices = null) { Throw.CheckNotNullArgument(monitor); Throw.CheckNotNullArgument(services); Monitor = monitor; Services = services; StartupServices = startupServices ?? new SimpleServiceContainer(); _registered = new Dictionary <Type, RegType>(); foreach (var r in services) { _registered[r.ServiceType] = RegType.PreviouslyRegistered; } AllowOverride = false; }
/// <summary> /// Binary writes a multicast closing entry. /// </summary> /// <param name="w">Binary writer to use.</param> /// <param name="grandOutputId">Identifier of the GrandOutput.</param> /// <param name="monitorId">Identifier of the monitor.</param> /// <param name="previousEntryType">Log type of the previous entry in the monitor..</param> /// <param name="previousLogTime">Time stamp of the previous entry in the monitor.</param> /// <param name="depth">Depth of the group (number of opened groups above).</param> /// <param name="level">Log level of the log entry.</param> /// <param name="closeTime">Time stamp of the group closing.</param> /// <param name="conclusions">Group conclusions.</param> static public void WriteCloseGroup(CKBinaryWriter w, string grandOutputId, string monitorId, LogEntryType previousEntryType, DateTimeStamp previousLogTime, int depth, LogLevel level, DateTimeStamp closeTime, IReadOnlyList <ActivityLogGroupConclusion>?conclusions) { Throw.CheckNotNullArgument(w); StreamLogType type = StreamLogType.TypeGroupClosed | StreamLogType.IsMultiCast; type = UpdateTypeWithPrevious(type, previousEntryType, ref previousLogTime); DoWriteCloseGroup(w, type, level, closeTime, conclusions); WriteMulticastFooter(w, grandOutputId, monitorId, previousEntryType, previousLogTime, depth); }
public async ValueTask <ISender> CreateSenderAsync(IActivityMonitor monitor, TrustedParty audience, ISignAlgorithm algorithm, TimeSpan validity, bool encrypt = false, uint maxUseCount = 0) { Throw.CheckNotNullArgument(monitor); Throw.CheckNotNullArgument(audience); Throw.CheckNotNullArgument(algorithm); Throw.CheckArgument(validity >= Configuration.MinSignatureLifetime && validity <= Configuration.MaxSignatureLifetime); var bestBefore = _appClock.Clock.UtcNow + validity; var key = algorithm.KeyRequirement != null ? await ResolveOutgoingKeyAsync(monitor, audience, algorithm.KeyRequirement, bestBefore, maxUseCount) : null; return(new Sender(this, audience, algorithm, key, bestBefore)); }
CKSetupRunResult DoRunStObjSetup(StObjEngineConfiguration stObjConf, ForceSetupLevel forceSetup) { Throw.CheckNotNullArgument(stObjConf); using (_ckSetup.Monitor.OpenInfo($"Invoking StObjSetupRunning event.")) { try { var ev = new StObjSetupRunningEventArgs(stObjConf, forceSetup); _stObjSetupRunning?.Invoke(this, ev); var ckSetupConf = new SetupConfiguration(new XDocument(ev.StObjEngineConfiguration.ToXml()), "CK.Setup.StObjEngine, CK.StObj.Engine"); ckSetupConf.CKSetupName = _ckSetup.TestProjectName; return(_ckSetup.CKSetup.Run(ckSetupConf, forceSetup: ev.ForceSetup)); } catch (Exception ex) { _ckSetup.Monitor.Error(ex); throw; } } }
/// <summary> /// Helper that copy a directory content to another one with retries. /// This first deletes the target directory before copying the content. /// </summary> /// <param name="monitor">The monitor to use.</param> /// <param name="source">The source directory.</param> /// <param name="target">The target directory.</param> /// <returns>True on success, false on error.</returns> public static bool SafeCopy(IActivityMonitor monitor, NormalizedPath source, NormalizedPath target) { Throw.CheckNotNullArgument(monitor); Throw.CheckArgument(!target.StartsWith(source) && !source.StartsWith(target)); int tryCount = 0; retry: try { var dS = new DirectoryInfo(source); var dT = new DirectoryInfo(target); if (!dS.Exists) { monitor.Error($"Source directory '{dS.FullName}' not found."); return(false); } if (!dT.Exists) { Directory.CreateDirectory(dT.FullName); } else { dT.Delete(recursive: true); } FileUtil.CopyDirectory(dS, dT); } catch (Exception ex) { if (++tryCount > 5) { monitor.Error($"Failed to copy directory content from {source} to '{target}' after 5 tries.", ex); return(false); } monitor.Warn($"Error while copying directory content. Retrying in {tryCount * 50} ms.", ex); System.Threading.Thread.Sleep(tryCount * 50); goto retry; } monitor.Info($"Directory content copied from '{source}' to '{target}'."); return(true); }
/// <summary> /// Binary writes a multicast log entry. /// </summary> /// <param name="w">Binary writer to use.</param> /// <param name="grandOutputId">Identifier of the GrandOutput.</param> /// <param name="monitorId">Identifier of the monitor.</param> /// <param name="previousEntryType">Log type of the previous entry in the monitor..</param> /// <param name="previousLogTime">Time stamp of the previous entry in the monitor.</param> /// <param name="depth">Depth of the line (number of opened groups above).</param> /// <param name="isOpenGroup">True if this the opening of a group. False for a line.</param> /// <param name="text">Text of the log entry.</param> /// <param name="level">Log level of the log entry.</param> /// <param name="logTime">Time stamp of the log entry.</param> /// <param name="tags">Tags of the log entry</param> /// <param name="ex">Exception of the log entry.</param> /// <param name="fileName">Source file name of the log entry</param> /// <param name="lineNumber">Source line number of the log entry</param> static public void WriteLog(CKBinaryWriter w, string grandOutputId, string monitorId, LogEntryType previousEntryType, DateTimeStamp previousLogTime, int depth, bool isOpenGroup, LogLevel level, DateTimeStamp logTime, string text, CKTrait tags, CKExceptionData?ex, string?fileName, int lineNumber) { Throw.CheckNotNullArgument(w); StreamLogType type = StreamLogType.IsMultiCast | (isOpenGroup ? StreamLogType.TypeOpenGroup : StreamLogType.TypeLine); type = UpdateTypeWithPrevious(type, previousEntryType, ref previousLogTime); DoWriteLog(w, type, level, logTime, text, tags, ex, fileName, lineNumber); WriteMulticastFooter(w, grandOutputId, monitorId, previousEntryType, previousLogTime, depth); }
/// <summary> /// Attempts to load a StObjMap from an assembly. /// </summary> /// <param name="a">Already generated assembly.</param> /// <param name="monitor">Optional monitor for loading operation.</param> /// <returns>A <see cref="IStObjMap"/> that provides access to the objects graph.</returns> public static IStObjMap?Load(Assembly a, IActivityMonitor?monitor = null) { Throw.CheckNotNullArgument(a); lock ( _alreadyHandled ) { var info = LockedGetMapInfo(a, ref monitor); if (info == null) { return(null); } var alc = AssemblyLoadContext.GetLoadContext(a); if (alc == null) { monitor.Warn($"Assembly '{a.FullName}' is not in any AssemblyLoadContext."); } else if (alc != AssemblyLoadContext.Default) { monitor.Warn($"Assembly '{a.FullName}' is loaded in non-default AssemblyLoadContext '{alc.Name}'."); } return(LockedGetStObjMapFromInfo(info, ref monitor)); } }
public void RegisterType(Type type) { Throw.CheckNotNullArgument(type); if (type != typeof(object)) { if (type.IsClass) { DoRegisterClass(type, out _, out _); } else if (type.IsInterface) { if (_pocoRegistrar.RegisterInterface(_monitor, type)) { RegisterAssembly(type); } RegisterRegularType(type); } else { RegisterRegularType(type); } } }
/// <summary> /// Creates an instance of the specified type, using any available services. /// The strategy is to use the longest public constructor. /// </summary> /// <param name="monitor">Monitor to use.</param> /// <param name="t">Type of the object to create.</param> /// <param name="services">Available services to inject.</param> /// <param name="requiredParameters">Optional required parameters.</param> /// <returns>The object instance or null on error.</returns> public static object?Create(IActivityMonitor monitor, Type t, IServiceProvider services, IEnumerable <object>?requiredParameters = null) { Throw.CheckNotNullArgument(monitor); Throw.CheckNotNullArgument(t); using (monitor.OpenDebug($"Creating instance of type: {t.AssemblyQualifiedName}.")) try { Required required = requiredParameters == null ? Array.Empty <KeyValuePair <object?, Type> >() : (Required)requiredParameters.Select(r => new KeyValuePair <object?, Type>(r, r.GetType())).ToList(); var longestCtor = t.GetConstructors() .Select(x => ValueTuple.Create(x, x.GetParameters())) .Where(x => x.Item2.Length >= required.Count) .OrderByDescending(x => x.Item2.Length) .Select(x => new { Ctor = x.Item1, Parameters = x.Item2, Mapped = x.Item2 .Select(p => required.FirstOrDefault(r => p.ParameterType.IsAssignableFrom(r.Value)).Key) .ToArray() }) .Where(x => x.Mapped.Count(m => m != null) == required.Count) .FirstOrDefault(); if (longestCtor == null) { var msg = $"Unable to find a public constructor for '{t.FullName}'."; if (required.Count > 0) { msg += " With required parameters compatible with type: " + required.Select(r => r.Value.Name).Concatenate(); } monitor.Error(msg); return(null); } int failCount = 0; for (int i = 0; i < longestCtor.Mapped.Length; ++i) { if (longestCtor.Mapped[i] == null) { var p = longestCtor.Parameters[i]; var resolved = services.GetService(p.ParameterType); if (resolved == null && !p.HasDefaultValue) { monitor.Error($"Resolution failed for parameter '{p.Name}', type: '{p.ParameterType}'."); ++failCount; } longestCtor.Mapped[i] = resolved; } } if (failCount > 0) { monitor.Error($"Unable to resolve parameters for '{t.FullName}'. Considered longest constructor: {longestCtor.Ctor}."); return(null); } return(longestCtor.Ctor.Invoke(longestCtor.Mapped)); } catch (Exception ex) { monitor.Error($"While instantiating {t.FullName}.", ex); return(null); } }
/// <summary> /// Initializes a new <see cref="AutomaticServicesConfigurationEventArgs"/>. /// </summary> /// <param name="map">The current StObjMap. Must not be null.</param> /// <param name="serviceRegister">The service register.</param> public AutomaticServicesConfigurationEventArgs(IStObjMap map, StObjContextRoot.ServiceRegister serviceRegister) { Throw.CheckNotNullArgument(map); StObjMap = map; ServiceRegister = serviceRegister; }
public StObjEngineResult Run(IStObjCollectorResultResolver resolver) { Throw.CheckNotNullArgument(resolver); return(DoRun(resolver)); }
/// <summary> /// Creates a MonitorTraceListener instance. /// </summary> /// <param name="grandOutput">The <see cref="Monitoring.GrandOutput"/> to send traces to.</param> /// <param name="failFast"> /// When true <see cref="Environment.FailFast(string)"/> will terminate the application on <see cref="Debug.Assert(bool)"/>, <see cref="Trace.Assert(bool)"/>, /// <see cref="Debug.Fail(string)"/> and <see cref="Trace.Fail(string)"/>. /// See this <see cref="MonitorTraceListener"/>'s remarks section to understand why this should be false. /// </param> public MonitorTraceListener(GrandOutput grandOutput, bool failFast) { Throw.CheckNotNullArgument(grandOutput); GrandOutput = grandOutput; FailFast = failFast; }
/// <summary> /// Produces a string description of this <see cref="NullableTypeTree"/>. /// </summary> /// <param name="b">The string builder to use.</param> /// <param name="withNamespace">True to include the types' namespace and enclosing types (non generic) if any.</param> /// <returns>The string builder.</returns> public StringBuilder ToString(StringBuilder b, bool withNamespace = false) { Throw.CheckNotNullArgument(b); if (Type.IsArray) { RawSubTypes[0].ToString(b, withNamespace); b.Append('[').Append(',', Type.GetArrayRank() - 1).Append(']'); } else { if ((Kind & NullabilityTypeKind.IsGenericType) != 0) { bool isTuple = Type.IsValueTuple(); if (isTuple) { b.Append('('); } else { var n = CodeWriterExtensions.GetTypeAlias(Type); if (n == null) { n = Type.Name; int idx = n.IndexOf('`', StringComparison.Ordinal); if (idx > 0) { n = n.Substring(0, idx); } if (withNamespace) { DumpNamespace(b, Type); } } b.Append(n).Append('<'); } bool atLeastOne = false; foreach (var t in SubTypes) { if (atLeastOne) { b.Append(','); } else { atLeastOne = true; } t.ToString(b, withNamespace); } b.Append(isTuple ? ')' : '>'); } else { var n = CodeWriterExtensions.GetTypeAlias(Type); if (n == null) { if (withNamespace) { DumpNamespace(b, Type); } n = Type.Name; } b.Append(n); } } if (Kind.IsNullable()) { b.Append('?'); } return(b);
/// <summary> /// Fluent function application: this enables a procedural fragment to be inlined in a fluent code. /// </summary> /// <typeparam name="T">Actual type of the code writer.</typeparam> /// <param name="this">This code writer.</param> /// <param name="f">Fluent function to apply.</param> /// <returns>This code writer to enable fluent syntax.</returns> public static T Append <T>(this T @this, Func <T, T> f) where T : ICodeWriter { Throw.CheckNotNullArgument(f); return(f(@this)); }
/// <summary> /// Fluent action application: this enables a procedural fragment to be inlined in a fluent code. /// </summary> /// <typeparam name="T">Actual type of the code writer.</typeparam> /// <param name="this">This code writer.</param> /// <param name="f">Action to apply to this code writer.</param> /// <returns>This code writer to enable fluent syntax.</returns> public static T Append <T>(this T @this, Action <T> f) where T : ICodeWriter { Throw.CheckNotNullArgument(f); f(@this); return(@this); }