在Visual Studio csproj中,要编译的文件如下所示:
<ItemGroup>
<Compile Include="C\Something.cs">
<Compile Include="B\SomethingElse.cs">
<Compile Include="A\YetSomethingElse.cs">
<\ItemGroup>
在我看来,订单是随机的(至少我看不到订购原则)。
有几次,在修复合并冲突期间,我错误地添加了两次文件(因为有很多文件,并且合并冲突行的文件已经在列表中的另一个位置)。如果有一种方法可以按字母顺序对Compile Include
d文件进行排序,这将很容易避免。
这是否可能(或者我必须自己编写脚本)?是否有任何副作用我必须注意?
答案 0 :(得分:7)
我刚遇到这个问题,因为我们团队的更多成员在没有他们的解决方案文件的情况下提交,我们将文件独立地添加到解决方案中,他们迟迟未提交他们的解决方案文件,Team Foundation Server / Visual Studio Online完全无法获得合并权。
有些文件已添加两次,有些文件根本没有添加,每个人都有不同顺序的文件 - 合并地狱。
我有类解决了无法使用以下C#对解决方案中的内容文件进行排序的问题,我在令人敬畏的LinqPad中执行了这个。
var documentsLocation = System.Environment.GetFolderPath(System.Environment.SpecialFolder.MyDocuments);
var unsortedFilePath = Path.Combine(documentsLocation.ToString(), "UnsortedConfigItems.xml");
var unsortedFile = new FileInfo(unsortedFilePath);
if (!unsortedFile.Exists) {
throw new FileNotFoundException(string.Format("The unsorted file could not be found at path {0}", unsortedFilePath));
}
var sortedFilePath = Path.Combine(documentsLocation, "SortedConfigItems.xml");
const string RootNodeName = "ItemGroup";
const string IncludeAttributeName = "Include";
var contentElementNames = new [] { "Compile", "Content", "None" };
var xmlFile = XDocument.Load(unsortedFile.FullName);
if (xmlFile == null || xmlFile.Root == null || xmlFile.Root.Name != RootNodeName)
{
Console.WriteLine("Invalid file or unexpected file schema");
return;
}
var allElements = xmlFile.Root.Elements();
var contentElements = new List<XElement>();
foreach(var elementName in contentElementNames) {
contentElements.AddRange(xmlFile.Root.Elements(elementName));
}
var elementsWithInclude = contentElements.Where(ce => ce.Attribute(IncludeAttributeName) != null && !string.IsNullOrWhiteSpace(ce.Attribute(IncludeAttributeName).Value));
if (!elementsWithInclude.Any())
{
Console.WriteLine("No content elements to sort");
return;
}
contentElements = null; // Make candidate for garbage collection
var uniqueElements = new List<XElement>(elementsWithInclude.Count());
foreach (var element in elementsWithInclude)
{
if (!uniqueElements.Any(e => e.Attribute(IncludeAttributeName).Value == element.Attribute(IncludeAttributeName).Value))
{
uniqueElements.Add(element);
}
}
var sortedUniqueElements = uniqueElements.OrderBy(ue => ue.Name.LocalName).ThenBy(ue => ue.Attribute(IncludeAttributeName).Value).ToList();
var remainingElements = new List<XElement>();
foreach (var element in allElements.Where(ae => !elementsWithInclude.Contains(ae))) { // This uses elements with include and not sorted unique to avoid re-adding filtered files
remainingElements.Add(element);
}
var sortedFile = new XDocument();
sortedFile.AddFirst(new XElement(RootNodeName));
sortedUniqueElements.ForEach(sue => sortedFile.Root.Add(sue));
remainingElements.ForEach(re => sortedFile.Root.Add(re));
sortedFile.Save(sortedFilePath);
我确信它可以稍微压缩并且更加优雅,但是它可以帮助我们。
完整性的步骤 -
确保您的项目文件已备份,无论是在源代码管理中还是本地。
右键单击解决方案资源管理器中的项目,然后选择&#34;卸载项目&#34; (如果未显示项目文件,并且解决方案中只有一个项目,则选择&#34;始终显示解决方案&#34;在Visual Studio选项中)。
项目图标应该已更改,并将列为&#34;(不可用)&#34;。再次右键单击并选择&#34;编辑 ProjectName .csproj&#34;
找到包含内容引用的ItemGroup节点,并剪切或复制并粘贴到新文件中(NotePad ++非常适用于此,但使用您选择的编辑器)并保存在XmlPathName的位置。确保&#34; ItemGroup&#34; node是新XML文档的根节点。
如果需要,请更改SortedPathName中的路径,并确保您的Windows用户帐户具有该位置的写入权限。
在LinqPad中运行上述C#(或将其分支并创建自己的控制台应用程序/ Powershell脚本)。
检查输出文件的内容以确保它看起来正确(大致一致的行数和格式),如果可能,验证为有效的XML(Notepad ++中的XML工具是理想的)。
将输出文件的内容复制回解决方案文件替换原始ItemGroup节点。
关闭csproj文件,右键单击解决方案资源管理器中的项目,然后选择&#34;重新加载项目&#34;。
如果项目是您的启动项目,您可能需要再次右键单击并选择&#34;设置为启动项目&#34;
尝试构建
答案 1 :(得分:1)
SortProjectItems是我刚刚发现的命令行实用程序,可以帮助缓解此问题。这不是永久性的解决方案:随着时间的推移,Visual Studio将不断提高.csproj
文件中项目的排序顺序。但这与我到目前为止发现的解决方案非常接近,而且总比没有好。