在Visual Studio脚手架中获得项目中的所有类

本文关键字:项目 Visual Studio 脚手架 | 更新日期: 2023-09-27 18:19:23

我正在为visual studio构建一个脚手架工具,并且需要呈现从某个抽象类派生的类列表,但仅在活动项目中的类。我让它工作,但它需要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;
                }
            }
        }
    }
}

所以我必须做一个名称空间的检查,当它找到一个匹配的类,以确保它是在我的项目。这感觉就像我做了一大堆不必要的工作。下面是visual studio项目中脚手架模板的例子:

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

代码类型服务是正确的方法吗?

编辑基本上,当它搜索类时,它不仅在当前活动的项目中搜索,而且还搜索所有引用的项目。这就是为什么我必须检查名称空间,以便只从活动项目获得结果。我想这就是为什么它会慢下来的原因,因为参考的项目非常大,所以它做了很多完全不必要的工作…

在Visual Studio脚手架中获得项目中的所有类

我注意到有人给这个问题点赞,提醒我发布一下我是如何让它工作得更快一点的。正如Maslow所指出的,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);
                    }
                }
            }
        }
    }
}