Как найти ProjectItem по имени файла

Я разрабатываю собственный инструмент для Visual Studio. Инструмент присваивается файлу, в момент изменения файла я получаю имя этого файла и должен генерировать некоторые изменения в проекте. Мне нужно найти ProjectItem по имени полученного файла. Я нашел только одно решение, которое перечисляет все элементы проекта в каждом проекте решения. Но это кажется огромным решением. Есть ли способ получить объект проекта по имени файла без перечисления?

Это моя реализация метода Generate для IVsSingleFileGenerator

public int Generate(string sourceFilePath, string sourceFileContent, string defaultNamespace, IntPtr[] outputFileContents, out uint output, IVsGeneratorProgress generateProgress)
{
    var dte = (EnvDTE.DTE)Package.GetGlobalService(typeof(EnvDTE.DTE));

    ProjectItem projectItem = null;

    foreach (Project project in dte.Solution.Projects)
    {
        foreach (ProjectItem item in project.ProjectItems)
        {
            var path = item.Properties.Item("FullPath").Value;
            if (sourceFilePath.Equals(path, StringComparison.OrdinalIgnoreCase))
            {
                projectItem = item;
            }
        }               
    }

    output = 0;
    outputFileContents[0] = IntPtr.Zero;

    return Microsoft.VisualStudio.VSConstants.S_OK;
}

Ответ 1

Я также использую этот дружественный мир DTE, чтобы создать Инструкцию. Я не нашел лучшего решения. В основном это методы, которые я использую:

Итерация проектов:

public static ProjectItem FindSolutionItemByName(DTE dte, string name, bool recursive)
{
    ProjectItem projectItem = null;
    foreach (Project project in dte.Solution.Projects)
    {
        projectItem = FindProjectItemInProject(project, name, recursive);

        if (projectItem != null)
        {
            break;
        }
    }
    return projectItem;
}

Найти в одном проекте:

public static ProjectItem FindProjectItemInProject(Project project, string name, bool recursive)
{
    ProjectItem projectItem = null;

    if (project.Kind != Constants.vsProjectKindSolutionItems)
    {
        if (project.ProjectItems != null && project.ProjectItems.Count > 0)
        {
            projectItem = DteHelper.FindItemByName(project.ProjectItems, name, recursive);
        }
    }
    else
    {
        // if solution folder, one of its ProjectItems might be a real project
        foreach (ProjectItem item in project.ProjectItems)
        {
            Project realProject = item.Object as Project;

            if (realProject != null)
            {
                projectItem = FindProjectItemInProject(realProject, name, recursive);

                if (projectItem != null)
                {
                    break;
                }
            }
        }
    }

    return projectItem;
}

Код, который я использую с другими фрагментами, можно найти здесь, в качестве руководства для новых проектов. Найдите исходный код и возьмите его.

Ответ 2

Чтобы получить project.documents - найти элемент - используйте Linq для запроса файлов