Подтвердить что ты не робот

Отсортированный порядок файлов в .csproj

В Visual Studio csproj файлы для компиляции ссылаются следующим образом:

<ItemGroup>
    <Compile Include="C\Something.cs"> 
    <Compile Include="B\SomethingElse.cs"> 
    <Compile Include="A\YetSomethingElse.cs"> 
<\ItemGroup>

Мне кажется, что порядок случайный (по крайней мере, я не вижу принципа упорядочения).

Случилось несколько раз, что при фиксации конфликтов слияния я ошибочно добавил файл дважды (так как есть много файлов, а файл в строке конфликта слияния уже находился в другой позиции в списке). Это было бы легко избежать, если бы был способ отсортировать файлы Compile Include d в алфавитном порядке.

Возможно ли это (или мне самому написать script)? Есть ли какие-либо побочные эффекты, о которых я должен был бы знать?

4b9b3361

Ответ 1

Я только что столкнулся с этой проблемой, поскольку все больше членов нашей команды совершают без их файла решения, мы добавляем файл в решение самостоятельно, они с запозданием передают свой файл решения, а Team Foundation Server/Visual Studio Online полностью не удается получить merge right.

Некоторые файлы добавляются дважды, некоторые не добавляются вообще, все с файлом в другом порядке - сливают ад.

У меня есть какая-то работа, связанная с невозможностью сортировать файлы Content в решении, используя следующий С#, который я выполняю в удивительном 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);

Я уверен, что он может быть слегка сжат и сделан более изящным, но он выполняет эту работу для нас.

Шаги для полноты -

  • Убедитесь, что ваш файл проекта резервную копию, либо в Source Control, либо локально.

  • Щелкните правой кнопкой мыши по проекту в обозревателе решений и выберите "Выгрузить проект" (если файл проекта не отображается, и у вас есть только один проект в решении, выберите "Всегда показывать решение" в параметрах Visual Studio).

  • Значок проекта должен быть изменен, и он будет указан как "(недоступно)". Щелкните правой кнопкой мыши еще раз и выберите "Edit ProjectName.csproj"

  • Найдите ItemGroup node, содержащий ссылки на контент, и либо вырежьте, либо скопируйте и вставьте в новый файл (NotePad ++ идеально подходит для этого, но используйте редактор по вашему выбору) и сохраните его в месте расположения XmlPathName. Убедитесь, что "ItemGroup" node является корнем node вашего нового документа XML.

  • Измените путь в SortedPathName, если хотите, и убедитесь, что ваша учетная запись пользователя Windows имеет разрешение на запись в это место.

  • Запустите вышеуказанный С# в LinqPad (или откройте его и создайте собственное консольное приложение /Powershell script).

  • Осмотрите содержимое выходного файла, чтобы убедиться, что он выглядит корректно (в целом согласованное количество строк и формат), и, если возможно, подтвердите его как допустимый XML (для этого идеально подходят инструменты XML в Notepad ++).

  • Скопируйте содержимое выходного файла обратно в файл решения, замените исходную ItemGroup node.

  • Закройте файл csproj, щелкните правой кнопкой мыши Project в обозревателе решений и выберите "Обновить проект".

  • Если проект был вашим проектом запуска, вам может понадобиться снова щелкнуть правой кнопкой мыши и выбрать "Установить как проект StartUp"

  • Попытка построить