Created
September 24, 2013 13:17
-
-
Save mavnn/6684569 to your computer and use it in GitHub Desktop.
C# and F# comparisons of NuGet ProjectSystem implementations. F# code is from https://github.com/mavnn/NuGetPlus/blob/master/NuGetPlus.Core/ProjectSystem.fs
C# code is from http://nuget.codeplex.com/SourceControl/latest#src/CommandLine/Common/MSBuildProjectSystem.cs They aren't identical in functionality, but they're pretty similar and implement…
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.IO; | |
using System.Linq; | |
using System.Reflection; | |
using System.Runtime.Versioning; | |
using Microsoft.Build.Evaluation; | |
namespace NuGet.Common | |
{ | |
public class MSBuildProjectSystem : PhysicalFileSystem, IMSBuildProjectSystem | |
{ | |
public MSBuildProjectSystem(string projectFile) | |
: base(Path.GetDirectoryName(projectFile)) | |
{ | |
Project = GetProject(projectFile); | |
} | |
public bool IsBindingRedirectSupported | |
{ | |
get | |
{ | |
return true; | |
} | |
} | |
private Project Project | |
{ | |
get; | |
set; | |
} | |
public void AddFrameworkReference(string name) | |
{ | |
// No-op | |
} | |
public void AddReference(string referencePath, Stream stream) | |
{ | |
string fullPath = PathUtility.GetAbsolutePath(Root, referencePath); | |
string relativePath = PathUtility.GetRelativePath(Project.FullPath, fullPath); | |
// REVIEW: Do we need to use the fully qualified the assembly name for strong named assemblies? | |
string include = Path.GetFileNameWithoutExtension(fullPath); | |
Project.AddItem("Reference", | |
include, | |
new[] { | |
new KeyValuePair<string, string>("HintPath", relativePath) | |
}); | |
} | |
public dynamic GetPropertyValue(string propertyName) | |
{ | |
return Project.GetPropertyValue(propertyName); | |
} | |
public bool IsSupportedFile(string path) | |
{ | |
return true; | |
} | |
public string ProjectName | |
{ | |
get | |
{ | |
return Path.GetFileNameWithoutExtension(Project.FullPath); | |
} | |
} | |
public bool ReferenceExists(string name) | |
{ | |
return GetReference(name) != null; | |
} | |
public void RemoveReference(string name) | |
{ | |
ProjectItem assemblyReference = GetReference(name); | |
if (assemblyReference != null) | |
{ | |
Project.RemoveItem(assemblyReference); | |
} | |
} | |
private IEnumerable<ProjectItem> GetItems(string itemType, string name) | |
{ | |
return Project.GetItems(itemType).Where(i => i.EvaluatedInclude.StartsWith(name, StringComparison.OrdinalIgnoreCase)); | |
} | |
public ProjectItem GetReference(string name) | |
{ | |
name = Path.GetFileNameWithoutExtension(name); | |
return GetItems("Reference", name) | |
.FirstOrDefault( | |
item => | |
new AssemblyName(item.EvaluatedInclude).Name.Equals(name, StringComparison.OrdinalIgnoreCase)); | |
} | |
public FrameworkName TargetFramework | |
{ | |
get | |
{ | |
string moniker = GetPropertyValue("TargetFrameworkMoniker"); | |
if (String.IsNullOrEmpty(moniker)) | |
{ | |
return null; | |
} | |
return new FrameworkName(moniker); | |
} | |
} | |
public string ResolvePath(string path) | |
{ | |
return path; | |
} | |
public void Save() | |
{ | |
Project.Save(); | |
} | |
public bool FileExistsInProject(string path) | |
{ | |
// some ItemTypes which starts with _ are added by various MSBuild tasks for their own purposes | |
// and they do not represent content files of the projects. Therefore, we exclude them when checking for file existence. | |
return Project.Items.Any( | |
i => i.EvaluatedInclude.Equals(path, StringComparison.OrdinalIgnoreCase) && | |
(String.IsNullOrEmpty(i.ItemType) || i.ItemType[0] != '_')); | |
} | |
private static Project GetProject(string projectFile) | |
{ | |
return ProjectCollection.GlobalProjectCollection.GetLoadedProjects(projectFile).FirstOrDefault() ?? new Project(projectFile); | |
} | |
public void AddImport(string targetPath, ProjectImportLocation location) | |
{ | |
if (targetPath == null) | |
{ | |
throw new ArgumentNullException("targetPath"); | |
} | |
// adds an <Import> element to this project file. | |
if (Project.Xml.Imports == null || | |
Project.Xml.Imports.All(import => !targetPath.Equals(import.Project, StringComparison.OrdinalIgnoreCase))) | |
{ | |
Project.Xml.AddImport(targetPath); | |
NuGet.MSBuildProjectUtility.AddEnsureImportedTarget(Project, targetPath); | |
Project.ReevaluateIfNecessary(); | |
Project.Save(); | |
} | |
} | |
public void RemoveImport(string targetPath) | |
{ | |
if (targetPath == null) | |
{ | |
throw new ArgumentNullException("targetPath"); | |
} | |
if (Project.Xml.Imports != null) | |
{ | |
// search for this import statement and remove it | |
var importElement = Project.Xml.Imports.FirstOrDefault( | |
import => targetPath.Equals(import.Project, StringComparison.OrdinalIgnoreCase)); | |
if (importElement != null) | |
{ | |
Project.Xml.RemoveChild(importElement); | |
NuGet.MSBuildProjectUtility.RemoveEnsureImportedTarget(Project, targetPath); | |
Project.ReevaluateIfNecessary(); | |
Project.Save(); | |
} | |
} | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[<AutoOpen>] | |
module NuGetPlus.ProjectSystem | |
open System | |
open System.IO | |
open System.Collections.Generic | |
open System.Reflection | |
open Microsoft.Build.Evaluation | |
open NuGet | |
let TryGetProject projectFile = | |
ProjectCollection.GlobalProjectCollection.GetLoadedProjects(projectFile) | |
|> Seq.tryFind(fun p -> p.FullPath = projectFile) | |
type ProjectSystem(projectFile : string) = | |
inherit PhysicalFileSystem(Path.GetDirectoryName(projectFile)) | |
let project = | |
match TryGetProject projectFile with | |
| Some project -> project | |
| None -> Project(projectFile) | |
let projectName = Path.GetFileNameWithoutExtension <| project.FullPath | |
let framework = | |
new Runtime.Versioning.FrameworkName(project.GetPropertyValue | |
("TargetFrameworkMoniker")) | |
let GetReferenceByName name = | |
project.GetItems("Reference") | |
|> Seq.filter | |
(fun i -> | |
i.EvaluatedInclude.StartsWith | |
(name, StringComparison.OrdinalIgnoreCase)) | |
|> Seq.tryFind | |
(fun i -> | |
AssemblyName(i.EvaluatedInclude) | |
.Name.Equals(name, StringComparison.OrdinalIgnoreCase)) | |
let GetReferenceByPath path = | |
let name = Path.GetFileNameWithoutExtension path | |
GetReferenceByName name | |
interface IProjectSystem with | |
member x.TargetFramework with get () = framework | |
member x.ProjectName with get () = projectName | |
member x.AddReference(path, stream) = | |
let fullPath = PathUtility.GetAbsolutePath(x.Root, path) | |
let relPath = | |
PathUtility.GetRelativePath(project.FullPath, fullPath) | |
let includeName = Path.GetFileNameWithoutExtension fullPath | |
project.AddItem | |
("Reference", includeName, [|KeyValuePair("HintPath", relPath)|]) | |
|> ignore | |
project.Save() | |
member x.AddFrameworkReference name = | |
project.AddItem("Reference", name) |> ignore | |
project.Save() | |
member x.ReferenceExists path = | |
match GetReferenceByName path with | |
| Some _ -> true | |
| None -> false | |
member x.RemoveReference path = | |
match GetReferenceByPath path with | |
| Some i -> | |
project.RemoveItem(i) |> ignore | |
project.Save() | |
| None -> () | |
member x.IsSupportedFile path = true | |
member x.ResolvePath path = path | |
member x.IsBindingRedirectSupported with get () = true | |
member x.AddImport((targetPath : string), location) = | |
if project.Xml.Imports = null | |
|| project.Xml.Imports | |
|> Seq.forall | |
(fun import -> | |
not | |
<| targetPath.Equals | |
(import.Project, | |
StringComparison.OrdinalIgnoreCase)) then | |
project.Xml.AddImport(targetPath) |> ignore | |
project.ReevaluateIfNecessary() | |
project.Save() | |
member x.RemoveImport(targetPath : string) = | |
match project.Xml.Imports | |
|> Seq.tryFind | |
(fun import -> | |
targetPath.Equals | |
(import.Project, | |
StringComparison.OrdinalIgnoreCase)) with | |
| None -> () | |
| Some i -> | |
project.Xml.RemoveChild(i) | |
project.ReevaluateIfNecessary() | |
project.Save() | |
member x.FileExistsInProject(path : string) = | |
project.Items | |
|> Seq.exists | |
(fun i -> | |
i.EvaluatedInclude.Equals | |
(path, StringComparison.OrdinalIgnoreCase) | |
&& (String.IsNullOrEmpty(i.ItemType) | |
|| i.ItemType.[0] <> '_')) | |
interface IPropertyProvider with | |
member x.GetPropertyValue name = project.GetPropertyValue(name) :> obj |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment