public IDisposable GetOrAdd <TScope, TService>( TScope scope, out TService service, out bool wasAdded, Func <TScope, TService> serviceFactory) { lock (registrations) { if (TryGet(scope, out service)) { wasAdded = false; return(DelegateDisposable.NoOp()); } service = serviceFactory(scope); if (service == null) { throw new ArgumentException( $"{nameof(service)} result is null for {typeof(TService).GetFriendlyFullName()}" + $" --- for scope '{scope}'.", nameof(serviceFactory)); } if (!registrations.TryGetValue(typeof(TScope), out Dictionary <object, object> scopes)) { scopes = new Dictionary <object, object>(8); registrations[typeof(TScope)] = scopes; } else { Debug.Assert(!scopes.ContainsKey(scope), "!scopes.ContainsKey(scope)"); } scopes[scope] = service; wasAdded = true; return(DelegateDisposable.With(scope, s => Remove(typeof(TScope), s))); } }
/// <summary> /// Invokes the <see cref="TraceSources"/> factory method with a delegate /// that adds a verbose console trace listener to all sources. /// </summary> /// <returns>Dispose to reset the default factory.</returns> public static IDisposable TraceAllVerbose() { void Configure(SimpleTraceSource traceSource) { traceSource.TraceSource.TryAdd( new Diagnostics.ConsoleTraceListener { Filter = new EventTypeFilter(SourceLevels.All), }); traceSource.TraceSource.Switch.Level = SourceLevels.All; } void Remove(SimpleTraceSource traceSource) => traceSource.TraceSource.Listeners.Remove(Diagnostics.ConsoleTraceListener.DefaultName); DelegateTraceSourceSelector selector = new DelegateTraceSourceSelector(Configure, Remove); TraceSources.AddSelector(selector); TraceSources.For(typeof(TestHelper)) .Verbose("TraceSources are verbose."); void Dispose() => TraceSources.RemoveSelector(selector); return(DelegateDisposable.With(Dispose)); }
public static IDisposable GetTempDir(string folderName, out string tempDir) { tempDir = Path.Combine(Path.GetTempPath(), $"{typeof(MefComposerTests).GetFriendlyName()}.{folderName}"); string path = tempDir; void DisposeTempDir() { try { Directory.Delete(path, true); } catch { // Ignored } } DisposeTempDir(); try { Directory.CreateDirectory(tempDir); string GetDllPath(bool isDebug) { string result = new Uri(typeof(MefComposerTests).Assembly.CodeBase).LocalPath; result = Path.GetDirectoryName( Path.GetDirectoryName(Path.GetDirectoryName(Path.GetDirectoryName(result)))); // ReSharper disable once AssignNullToNotNullAttribute result = Path.Combine(Path.Combine(result, Helper.PartsProjectName), "bin"); result = Path.Combine( result, isDebug ? "Debug" : "Release"); return(Path.Combine(result, Helper.PartsProjectName + ".dll")); } bool useDebugPath = #if DEBUG true; #else false; #endif // ReSharper disable once ConditionIsAlwaysTrueOrFalse string partsPath = GetDllPath(useDebugPath); if (!File.Exists(partsPath)) { // ReSharper disable once ConditionIsAlwaysTrueOrFalse partsPath = GetDllPath(!useDebugPath); } File.Copy( partsPath, Path.Combine( tempDir, Helper.PartsProjectName + ".dll")); return(DelegateDisposable.With(DisposeTempDir)); } catch (Exception exception) { DisposeTempDir(); throw new AssertFailedException( $"Couldn't create temp assembly directory: {exception.Message}", exception); } }
/// <summary> /// Tries to enter the reader lock, and creates a disposable object that exits the lock /// when disposed. /// </summary> /// <param name="gotLock">Will be false if your attempt to acquire the lock fails: if false /// then you do not have the lock.</param> /// <param name="millisecondsTimeout">Optional timeout to wait for the lock. Notice that the /// defult is not infinite: you may pass <see cref="Timeout.Infinite"/>.</param> /// <param name="cancellationToken">Optional token that will cancel the wait for the lock.</param> /// <returns>Not null.</returns> public IDisposable WithReaderLock( out bool gotLock, int millisecondsTimeout = 1000 * 60 * 3, CancellationToken cancellationToken = default) { DelegateDisposable <bool> result = DelegateDisposable.With( () => enter(millisecondsTimeout, cancellationToken, false), isGotLock => { if (isGotLock) { exit(false); } }); gotLock = result.State; return(result); }
/// <summary> /// Ensures that the directory exists, and returns a disposable /// that will delete the directory and all files. /// </summary> /// <param name="folderPath">Required.</param> /// <returns>Not null.</returns> public static IDisposable UsingTempFolder(string folderPath) { if (!Directory.Exists(folderPath)) { Directory.CreateDirectory(folderPath); } void DeleteTempFolder() { if (!Directory.Exists(folderPath)) { return; } try { Directory.Delete(folderPath, true); } catch { // The folder may be open in Explorer } } return(DelegateDisposable.With(DeleteTempFolder)); }