using System; using System.IO; using System.Threading; namespace Microsoft.AspNetCore.NodeServices { /// /// Makes it easier to pass script files to Node in a way that's sure to clean up after the process exits. /// public sealed class StringAsTempFile : IDisposable { private bool _disposedValue; private bool _hasDeletedTempFile; private object _fileDeletionLock = new object(); private IDisposable _applicationLifetimeRegistration; /// /// Create a new instance of . /// /// The contents of the temporary file to be created. /// A token that indicates when the host application is stopping. public StringAsTempFile(string content, CancellationToken applicationStoppingToken) { FileName = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); File.WriteAllText(FileName, content); // Because .NET finalizers don't reliably run when the process is terminating, also // add event handlers for other shutdown scenarios. _applicationLifetimeRegistration = applicationStoppingToken.Register(EnsureTempFileDeleted); } /// /// Specifies the filename of the temporary file. /// public string FileName { get; } /// /// Disposes the instance and deletes the associated temporary file. /// public void Dispose() { DisposeImpl(true); GC.SuppressFinalize(this); } private void DisposeImpl(bool disposing) { if (!_disposedValue) { if (disposing) { // Dispose managed state _applicationLifetimeRegistration.Dispose(); } EnsureTempFileDeleted(); _disposedValue = true; } } private void EnsureTempFileDeleted() { lock (_fileDeletionLock) { if (!_hasDeletedTempFile) { File.Delete(FileName); _hasDeletedTempFile = true; } } } /// /// Implements the finalization part of the IDisposable pattern by calling Dispose(false). /// ~StringAsTempFile() { DisposeImpl(false); } } }