Получить все классы в проекте в Visual Studio Scaffolder

Я создаю инструмент для создания лесов для Visual Studio, и мне нужно представить список классов, которые являются производными от определенного абстрактного класса, но только классов в активном проекте. У меня он работает, но визуальной студии требуется немного времени, чтобы запустить код.

ICodeTypeService codeTypeService = (ICodeTypeService)Context
                    .ServiceProvider.GetService(typeof(ICodeTypeService));

var types = codeTypeService.GetAllCodeTypes(Context.ActiveProject);

foreach (var type in types)
{
    type.
    if (type.Kind == vsCMElement.vsCMElementClass)
    {
        foreach (var d in type.Bases)
        {
            var dClass = d as CodeClass;
            var name = type.Name;
            if (dClass.Name == "MyAbstractClass")
            {
                if (type.Namespace.Name.Contains(Context.ActiveProject.Name))
                {
                    yield return type.Name;
                }
            }

        }
    }
}

Поэтому мне нужно проверить пространство имен, когда он найдет соответствующий класс, чтобы убедиться, что он находится в моем проекте. Такое ощущение, что я делаю кучу ненужной работы. Это пример, который они приводят с проектом визуальной студии шаблона каркаса:

ICodeTypeService codeTypeService = (ICodeTypeService)Context
                    .ServiceProvider.GetService(typeof(ICodeTypeService));

return codeTypeService
    .GetAllCodeTypes(Context.ActiveProject)
    .Where(codeType => codeType.IsValidWebProjectEntityType())
    .Select(codeType => new ModelType(codeType));

правильный ли способ сделать это с помощью codetypeservice?

РЕДАКТИРОВАТЬ Обычно, когда он ищет классы, он не просто выполняет это в текущем активном проекте, но также ищет все проекты, на которые есть ссылки. Вот почему мне нужно проверить пространство имен, чтобы получить результаты только из активного проекта. Я считаю, что именно поэтому он замедляется, потому что проекты, на которые есть ссылки, довольно большие, поэтому он выполняет чертовски много совершенно ненужной работы ...


person Hazza    schedule 26.08.2014    source источник
comment
Можете ли вы дать определение «ненадолго», при этом ли вы подумали о Roslyn? Кажется, что если скорость - это то, что вы ищете, это будет лучший вариант.   -  person Maslow    schedule 01.10.2014
comment
На моем компьютере это занимает около 10-15 секунд, и Visual Studio во время этого переходит в режим ожидания. Так что не страшно, но ... да. И да, Roslyn действительно выглядит как путь вперед, но это для VS2014, верно?   -  person Hazza    schedule 01.10.2014
comment
Я понимаю, что не очень хорошо объяснил проблему ... Я добавлю правку в сообщение   -  person Hazza    schedule 01.10.2014
comment
вы уже можете использовать Roslyn для анализа и написания C #. плюс части Roslyn уже есть в VS2013   -  person Maslow    schedule 01.10.2014
comment
Понятно, я этого не осознавал. Я должен это изучить. Спасибо, вы очень помогли. И последнее, есть ли у вас какие-нибудь хорошие ссылки на ресурсы на Roslyn? Лучшее, что я нашел, похоже, это кодекс Roslyn, там есть несколько примеров, которые должны меня подтолкнуть. Снова ура   -  person Hazza    schedule 01.10.2014
comment
Вот пример roslyn, который я написал code.msdn.microsoft.com/Implementing- a-Code-Action-28579fb1   -  person Maslow    schedule 01.10.2014
comment
Отлично, я посмотрю на это сегодня вечером. Спасибо!   -  person Hazza    schedule 02.10.2014


Ответы (1)


Я заметил, что кто-то проголосовал за этот вопрос, напомнив мне опубликовать, как я заставил его работать немного быстрее. Roslyn, как указал Маслоу, - это круто, но Roslyn не был доступен, когда я создавал это расширение, за исключением предварительной версии, так что в основном это было просто бессмысленно.

Мое расширение размещено на GitHub, вот соответствующий фрагмент кода: https://github.com/Hazzamanic/orchardizer/blob/master/Orchardization/UI/CustomViewModel.cs

Но в случае, если GitHub умрет / кто-то заплатит мне миллион долларов за мой код, вот соответствующий код ...

/// <summary>
/// Recursively gets all the ProjectItem objects in a list of projectitems from a Project
/// </summary>
/// <param name="projectItems">The project items.</param>
/// <returns></returns>
public IEnumerable<ProjectItem> GetProjectItems(EnvDTE.ProjectItems projectItems)
{
    foreach (EnvDTE.ProjectItem item in projectItems)
    {
        yield return item;

        if (item.SubProject != null)
        {
            foreach (EnvDTE.ProjectItem childItem in GetProjectItems(item.SubProject.ProjectItems))
                yield return childItem;
        }
        else
        {
            foreach (EnvDTE.ProjectItem childItem in GetProjectItems(item.ProjectItems))
                yield return childItem;
        }
    }

}

Когда у вас есть все элементы проекта, вы можете фильтровать по ним. Кажется, это нормально работает в довольно больших проектах, хотя, честно говоря, у меня нет особо крупных проектов. В моем случае я хотел найти все классы с базовым классом DatMigrationImpl. Итак, у меня был такой код:

var allClasses = GetProjectItems(Context.ActiveProject.ProjectItems).Where(v => v.Name.Contains(".cs"));
// check for .cs extension on each

foreach (var c in allClasses)
{
    var eles = c.FileCodeModel;
    if (eles == null)
        continue;
    foreach (var ele in eles.CodeElements)
    {
        if (ele is EnvDTE.CodeNamespace)
        {
            var ns = ele as EnvDTE.CodeNamespace;
            // run through classes
            foreach (var property in ns.Members)
            {
                var member = property as CodeType;
                if (member == null)
                    continue;

                foreach (var d in member.Bases)
                {
                    var dClass = d as CodeClass;
                    if (dClass == null)
                        continue;

                    var name = member.Name;
                    if (dClass.Name == "DataMigrationImpl")
                    {
                        yield return new Migration(member);
                    }
                }
            }
        }
    }
}
person Hazza    schedule 29.09.2015