65.9K
CodeProject 正在变化。 阅读更多。
Home

LINQ to Visual Studio Solution

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.20/5 (7投票s)

2009年12月1日

CPOL

3分钟阅读

viewsIcon

29568

downloadIcon

253

使用 LINQ 搜索解决方案内项目的属性。

来自 LINQPad 的截图,显示了此代码的一个示例用法。

引言

在尝试使用 Visual Studio C# Express 或 SharpDevelop 为 Windows Mobile 编写软件时,我发现设计器生成的一些通用代码在 Windows Mobile 上无法运行。 我不想每次在表单上更改内容时都手动修复它,我想编写一个通用重构工具,可以从命令行(或“工具”菜单)运行并修复问题代码。

我用 SharpDevelop 的 NRefactory 库(或滥用)编写了一些非常难看的东西。 但是,我发现有时我需要使用 Reflection,因此我需要知道项目中引用了哪些库。 此时,我从未用过 LINQ,但我开始看到 LINQ to XML 如何节省大量代码。

然后,在我的工作过程中,获取项目属性的代码演变成了我在这里展示的通用 LINQ to Visual Studio 解决方案。 这段代码中没有任何内容涉及重构。 它只对 Visual Studio 项目执行只读属性查询。 希望在某个时候,我的重构代码能够达到一个不错的阶段,我可以发布一篇关于此的文章。

背景

正如我之前所说,直到几天前我才使用过 LINQ。 并非所有这些代码都非常漂亮,并且可能有一种更简单/更好的方法来实现此代码中的某些功能。 如果有,我将不胜感激。 话虽如此,当我针对我计算机上的许多解决方案文件/项目运行一系列查询时,它的表现非常好。

Using the Code

要使用演示应用程序,只需从命令行启动它,传递您希望递归扫描解决方案文件和项目的目录。 它将每个解决方案/项目的摘要输出到应用程序目录中的 output.txt 文件中。 在演示应用程序的代码中,还有几个您可以尝试的其他查询已被注释掉。 我建议您查看这些内容以了解此库的一些可能性。

添加对演示下载中找到的 LinqToVisualStudioSolution.dll 的引用。 为 LinqToVisualStudioSolution 命名空间添加一个 using 指令。 现在,您可以开始使用代码了。

using System;
using LinqToVisualStudioSolution;

class Program
{
   static void Main(string[] args)
   {
       // Change the path to a real solution file.
       Solution solution = new Solution(@"D:\temp\Test.sln");

       var projects = (from project in solution
                       where project.OutputType == OutputType.Library
                       select project);

       foreach (var project in projects)
       {
         
            Console.Write("Project: ");
            Console.WriteLine(project.ProjectName);

            // OutputPathToAssemblyFull is a calculated property from 
            // OutputPathFull (another calculation), AssemblyName, and OutputType.

            Console.WriteLine(project.OutputPathToAssemblyFull);
            Console.WriteLine();
            if (project.Errors.Count > 0)
            {
                Console.ForegroundColor = ConsoleColor.Red;
                foreach (string err in project.Errors)
                {
                    Console.WriteLine(err);
                }
                Console.ResetColor();
            }
       }
   }
}

关注点

我的代码中最难的部分是使 Element(s)Attribute(s) 功能正常工作,以便用户可以访问项目中的任何属性,而不仅仅是常见属性。 我必须创建一个名为 PElement 的类,该类继承自 XElement。 这样做的原因是让用户不必在他的查询中包含命名空间。 因此,您无需编写以下内容

XNamespace ns = "http://schemas.microsoft.com/developer/msbuild/2003";

var projects = (from project in solution
                where project.Element(ns + "PropertyGroup") != null &&
                project.Element(ns + "PropertyGroup")
                .Element(ns + "AssemblyName") != null &&
                project.Element(ns + "PropertyGroup")
                .Element(ns + "AssemblyName").Value == "Test"
                select project); 

您可以完全忘记 XNamespace

为了实现这一点,我必须为 IEnumerable<PElement> 类编写几个扩展方法。 可以在 PElement.cs 文件的开头找到它们。

我还为 IEnumerable<Reference> 类编写了一个扩展方法,以便我可以拥有一个自定义的 Contains 方法。 现在,您可以搜索包含特定引用的项目。

var projects = (from project in solution
                 where project.References.Contains("mscorlib")
                 select project);

结论

我编写这段代码很有趣,并从中了解到很多东西,包括 LINQ 的强大功能。 希望这对其他人有所帮助。

© . All rights reserved.