LINQ to Visual Studio Solution
使用 LINQ 搜索解决方案内项目的属性。
引言
在尝试使用 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 的强大功能。 希望这对其他人有所帮助。