diff --git a/src/ReferenceCop.MSBuild/Providers/MSBuildProjectMetadataProvider.cs b/src/ReferenceCop.MSBuild/Providers/MSBuildProjectMetadataProvider.cs index 6710d5c..3f8ddaa 100644 --- a/src/ReferenceCop.MSBuild/Providers/MSBuildProjectMetadataProvider.cs +++ b/src/ReferenceCop.MSBuild/Providers/MSBuildProjectMetadataProvider.cs @@ -1,5 +1,6 @@ namespace ReferenceCop.MSBuild { + using System; using System.Collections.Generic; using System.Linq; using Microsoft.Build.Evaluation; @@ -7,11 +8,22 @@ namespace ReferenceCop.MSBuild /// /// Provides project reference information using MSBuild project evaluation. /// - public class MSBuildProjectMetadataProvider : IProjectMetadataProvider + public class MSBuildProjectMetadataProvider : IProjectMetadataProvider, IDisposable { private const string ProjectReferenceNode = "ProjectReference"; private const string NoWarnMetadata = "NoWarn"; + private readonly ProjectCollection projectCollection; + private bool disposed; + + /// + /// Initializes a new instance of the class. + /// + public MSBuildProjectMetadataProvider() + { + this.projectCollection = new ProjectCollection(); + } + /// /// Gets the project references from a project file. /// @@ -19,8 +31,7 @@ public class MSBuildProjectMetadataProvider : IProjectMetadataProvider /// The collection of project references. public IEnumerable GetProjectReferences(string projectFilePath) { - var projectCollection = new ProjectCollection(); - var project = projectCollection.LoadProject(projectFilePath); + var project = this.LoadOrGetProject(projectFilePath); // Get all ProjectReference items. These are the direct project references. var projectReferences = project.GetItems(ProjectReferenceNode); @@ -47,11 +58,48 @@ public IEnumerable GetProjectReferences(string projectFile /// The resolved property value. public string GetPropertyValue(string projectFilePath, string propertyName) { - var projectCollection = new ProjectCollection(); - var project = projectCollection.LoadProject(projectFilePath); + var project = this.LoadOrGetProject(projectFilePath); project.ReevaluateIfNecessary(); return project.GetPropertyValue(propertyName); } + + /// + public void Dispose() + { + this.Dispose(true); + GC.SuppressFinalize(this); + } + + /// + /// Releases the resources used by the . + /// + /// Whether managed resources should be disposed. + protected virtual void Dispose(bool disposing) + { + if (!this.disposed) + { + if (disposing) + { + this.projectCollection.UnloadAllProjects(); + this.projectCollection.Dispose(); + } + + this.disposed = true; + } + } + + private Project LoadOrGetProject(string projectFilePath) + { + var fullPath = System.IO.Path.GetFullPath(projectFilePath); + var loaded = this.projectCollection.GetLoadedProjects(fullPath); + + if (loaded.Count > 0) + { + return loaded.First(); + } + + return this.projectCollection.LoadProject(fullPath); + } } } diff --git a/src/ReferenceCop.MSBuild/ReferenceCopTask.cs b/src/ReferenceCop.MSBuild/ReferenceCopTask.cs index d370247..d94d9aa 100644 --- a/src/ReferenceCop.MSBuild/ReferenceCopTask.cs +++ b/src/ReferenceCop.MSBuild/ReferenceCopTask.cs @@ -120,6 +120,10 @@ public bool Execute() success = false; this.BuildEngine.LogErrorEvent(ex); } + finally + { + (this.projectReferencesProvider as IDisposable)?.Dispose(); + } return success; }