ProjectFileRewriter.cs 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. using RxGauntlet.Xml;
  2. using System.Xml;
  3. namespace RxGauntlet.Build;
  4. public class ProjectFileRewriter
  5. {
  6. private readonly XmlDocument _document = new();
  7. private ProjectFileRewriter(string template)
  8. {
  9. _document.Load(template);
  10. }
  11. public void SetTargetFramework(string targetFrameworkMoniker)
  12. {
  13. XmlNode targetFrameworkNode = _document.GetRequiredNode("/Project/PropertyGroup/TargetFramework");
  14. targetFrameworkNode.InnerText = targetFrameworkMoniker;
  15. }
  16. public void SetTargetFrameworks(string targetFrameworkMonikerList)
  17. {
  18. ReplaceProperty("TargetFrameworks", targetFrameworkMonikerList);
  19. }
  20. public void AddAssemblyNameProperty(string assemblyName)
  21. {
  22. AddPropertyGroup([new("AssemblyName", assemblyName)]);
  23. }
  24. public void ReplaceProperty(string propertyName, string newValue)
  25. {
  26. XmlNode propertyNode = _document.GetRequiredNode($"/Project/PropertyGroup/{propertyName}");
  27. propertyNode.InnerText = newValue;
  28. }
  29. public void ReplacePackageReference(string packageId, PackageIdAndVersion[] replacementPackages)
  30. {
  31. XmlNode packageRefNode = _document.GetRequiredNode($"/Project/ItemGroup/PackageReference[@Include='{packageId}']");
  32. if (replacementPackages is [PackageIdAndVersion singleReplacement])
  33. {
  34. packageRefNode.SetAttribute("Include", singleReplacement.PackageId);
  35. packageRefNode.SetAttribute("Version", singleReplacement.Version);
  36. }
  37. else
  38. {
  39. // We are to replace a single package reference with multiple package references
  40. // so we remove the original PackageReference and add new ones.
  41. ReplaceNodeWithPackageReferences(packageRefNode, replacementPackages);
  42. }
  43. }
  44. public void ReplaceProjectReferenceWithPackageReference(
  45. string targetCsProjNameWithoutDirectory,
  46. PackageIdAndVersion[] replacementPackages)
  47. {
  48. XmlNode projectRefNode = _document.GetRequiredNode($"/Project/ItemGroup/ProjectReference[contains(@Include, '{targetCsProjNameWithoutDirectory}')]");
  49. ReplaceNodeWithPackageReferences(projectRefNode, replacementPackages);
  50. }
  51. public void AddPropertyGroup(IEnumerable<KeyValuePair<string, string>> properties)
  52. {
  53. XmlNode propertyGroupNode = _document.CreateElement("PropertyGroup");
  54. foreach ((string name, string value) in properties)
  55. {
  56. XmlNode propertyNode = _document.CreateElement(name);
  57. propertyNode.InnerText = value;
  58. propertyGroupNode.AppendChild(propertyNode);
  59. }
  60. _document.SelectSingleNode("/Project")!.AppendChild(propertyGroupNode);
  61. }
  62. public void AddUseUiFrameworksIfRequired(bool? useWpf, bool? useWindowsForms)
  63. {
  64. if (useWpf.HasValue || useWindowsForms.HasValue)
  65. {
  66. List<KeyValuePair<string, string>> useUiFrameworksProperties = [];
  67. if (useWpf.HasValue)
  68. {
  69. useUiFrameworksProperties.Add(new("UseWPF", useWpf.Value.ToString()));
  70. }
  71. if (useWindowsForms.HasValue)
  72. {
  73. useUiFrameworksProperties.Add(new("UseWindowsForms", useWindowsForms.Value.ToString()));
  74. }
  75. AddPropertyGroup(useUiFrameworksProperties);
  76. }
  77. }
  78. internal void WriteModified(string destinationPath)
  79. {
  80. _document.Save(destinationPath);
  81. }
  82. private static void ReplaceNodeWithPackageReferences(
  83. XmlNode nodeToReplace,
  84. PackageIdAndVersion[] replacementPackages)
  85. {
  86. XmlNode packageRefItemGroup = nodeToReplace.ParentNode!;
  87. packageRefItemGroup.RemoveChild(nodeToReplace);
  88. foreach (PackageIdAndVersion packageIdAndVersion in replacementPackages)
  89. {
  90. XmlNode rxNewPackageRefNode = packageRefItemGroup.OwnerDocument!.CreateElement("PackageReference");
  91. rxNewPackageRefNode.SetAttribute("Include", packageIdAndVersion.PackageId);
  92. rxNewPackageRefNode.SetAttribute("Version", packageIdAndVersion.Version);
  93. packageRefItemGroup.AppendChild(rxNewPackageRefNode);
  94. }
  95. }
  96. public static ProjectFileRewriter CreateForCsProj(string template)
  97. {
  98. return new ProjectFileRewriter(template);
  99. }
  100. public void FixUpProjectReferences(string templateProjectFolder)
  101. {
  102. if (_document.SelectNodes("/Project/ItemGroup/ProjectReference") is XmlNodeList projectReferences)
  103. {
  104. foreach (XmlElement projectReference in projectReferences.OfType<XmlElement>())
  105. {
  106. string relativePath = projectReference.GetAttribute("Include");
  107. string absolutePath = Path.GetFullPath(Path.Combine(templateProjectFolder, relativePath));
  108. projectReference.SetAttribute("Include", absolutePath);
  109. }
  110. }
  111. }
  112. }