using System; using System.Collections.Generic; using System.Linq; using System.Threading; using umbraco.interfaces; namespace Umbraco.Core.ObjectResolution { /// /// A resolver to return all IApplicationEvents objects /// /// /// This is disposable because after the app has started it should be disposed to release any memory being occupied by instances. /// internal sealed class ApplicationEventsResolver : ManyObjectsResolverBase, IDisposable { private readonly LegacyStartupHandlerResolver _legacyResolver; /// /// Constructor /// /// internal ApplicationEventsResolver(IEnumerable applicationEventHandlers) : base(applicationEventHandlers) { //create the legacy resolver and only include the legacy types _legacyResolver = new LegacyStartupHandlerResolver( applicationEventHandlers.Where(x => !TypeHelper.IsTypeAssignableFrom(x))); } /// /// Override in order to only return types of IApplicationEventHandler and above, /// do not include the legacy types of IApplicationStartupHandler /// protected override IEnumerable InstanceTypes { get { return base.InstanceTypes.Where(TypeHelper.IsTypeAssignableFrom); } } /// /// Gets the implementations. /// public IEnumerable ApplicationEventHandlers { get { return Values; } } /// /// Create instances of all of the legacy startup handlers /// public void InstantiateLegacyStartupHandlers() { //this will instantiate them all var handlers = _legacyResolver.LegacyStartupHandlers; } protected override bool SupportsClear { get { return false; } } protected override bool SupportsInsert { get { return false; } } private class LegacyStartupHandlerResolver : ManyObjectsResolverBase, IDisposable { internal LegacyStartupHandlerResolver(IEnumerable legacyStartupHandlers) : base(legacyStartupHandlers) { } public IEnumerable LegacyStartupHandlers { get { return Values; } } public void Dispose() { Reset(); } } private bool _disposed; private readonly ReaderWriterLockSlim _disposalLocker = new ReaderWriterLockSlim(); /// /// Gets a value indicating whether this instance is disposed. /// /// /// true if this instance is disposed; otherwise, false. /// public bool IsDisposed { get { return _disposed; } } /// /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. /// /// 2 public void Dispose() { Dispose(true); // Use SupressFinalize in case a subclass of this type implements a finalizer. GC.SuppressFinalize(this); } ~ApplicationEventsResolver() { // Run dispose but let the class know it was due to the finalizer running. Dispose(false); } private void Dispose(bool disposing) { // Only operate if we haven't already disposed if (IsDisposed || disposing == false) return; using (new WriteLock(_disposalLocker)) { // Check again now we're inside the lock if (IsDisposed) return; // Call to actually release resources. This method is only // kept separate so that the entire disposal logic can be used as a VS snippet DisposeResources(); // Indicate that the instance has been disposed. _disposed = true; } } /// /// Clear out all of the instances, we don't want them hanging around and cluttering up memory /// private void DisposeResources() { _legacyResolver.Dispose(); Reset(); } } }