.csproj中文件的排序顺序

Wil*_*ert 24 xml csproj visual-studio visual-studio-2013

在Visual Studio csproj中,要编译的文件如下所示:

<ItemGroup>
    <Compile Include="C\Something.cs"> 
    <Compile Include="B\SomethingElse.cs"> 
    <Compile Include="A\YetSomethingElse.cs"> 
<\ItemGroup>
Run Code Online (Sandbox Code Playgroud)

在我看来,订单是随机的(至少我看不到订购原则).

它发生了几次,在修复合并冲突期间,我错误地添加了两次文件(因为有很多文件,并且合并冲突行的文件已经在列表中的另一个位置).如果有一种方法可以Compile Include按字母顺序对d文件进行排序,这将很容易避免.

这是否可能(或者我自己必须编写脚本)?是否有任何副作用我必须注意?

pwd*_*dst 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);
Run Code Online (Sandbox Code Playgroud)

我确信它可以稍微压缩并且更加优雅,但它可以帮助我们.

完整性的步骤 -

  1. 确保在Source Control或本地备份项目文件.

  2. 右键单击解决方案资源管理器中的项目,然后选择"卸载项目"(如果未显示项目文件,并且解决方案中只有一个项目,则在Visual Studio选项中选择"始终显示解决方案").

  3. 项目图标应该已更改,并将列为"(不可用)".再次右键单击并选择"编辑ProjectName .csproj"

  4. 找到包含内容引用的ItemGroup节点,并将其剪切或复制并粘贴到新文件中(NotePad ++非常适用于此,但使用您选择的编辑器)并保存在XmlPathName的位置.确保"ItemGroup"节点是新XML文档的根节点.

  5. 如果需要,请更改SortedPathName中的路径,并确保您的Windows用户帐户具有该位置的写入权限.

  6. 在LinqPad中运行上面的C#(或者将其分支并创建自己的控制台应用程序/ Powershell脚本).

  7. 检查输出文件的内容以确保它看起来正确(广泛一致的行数和格式),如果可能,验证为有效的XML(Notepad ++中的XML工具是理想的).

  8. 将输出文件的内容复制回解决方案文件,替换原始ItemGroup节点.

  9. 关闭csproj文件,右键单击Solution Explorer中的Project并选择"Reload project".

  10. 如果项目是您的启动项目,您可能需要再次右键单击并选择"设置为启动项目"

  11. 尝试建立


Mas*_*Net 5

SortProjectItems是我刚刚发现的一个命令行实用程序,可能有助于缓解此问题。这不是永久修复:随着时间的推移,Visual Studio 会不断打乱文件中项目的排序顺序.csproj。但这是我迄今为止找到的最接近解决方案的解决方案,而且总比没有好得多。

  • 如果您想对 csproj 文件进行排序,但它对我来说不适用于新的 SDK 样式 csproj 文件,则此工具可以减少手动工作量。 (2认同)