Я создаю инструмент для лесов для визуальной студии и должен представить список классов, которые происходят из определенного абстрактного класса, но только классы в активном проекте. У меня есть работа, но для запуска кода требуется визуальная студия.
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));
является ли режим codetypes правильным способом для этого?
EDIT В основном, когда он ищет классы, он не просто делает это в текущем активном проекте, но также выполняет поиск по всем указанным проектам. Вот почему я должен проверять пространство имен, поэтому получаю результаты только от активного проекта. Я считаю, что это замедлилось, потому что проекты, на которые ссылаются, достаточно велики, поэтому он делает чертовски много ненужной работы...
Я заметил, что кто-то поддержал этот вопрос, напомнив мне, как мне заставить его работать немного быстрее. Рослин, как отметил Маслоу, классный, но Рослин не был доступен, когда я строил это расширение, за исключением предварительного просмотра, так что в основном это было просто бессмысленно.
Мое расширение находится на 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);
}
}
}
}
}
}