我是roslyn的初学者,所以我尝试通过制作一个非常简单的控制台应用程序来开始学习它,这是在着名的教程网站中引入的。 (https://riptutorial.com/roslyn/example/16545/introspective-analysis-of-an-analyzer-in-csharp),它运作不佳。
我制作的Cosole应用程序是.NET Framework(目标框架版本是4.7.2),而不是.NET Core或.NET标准。我添加了NuGet包Microsoft.CodeAnalysis和Microsoft.CodeAnalysis.Workspaces.MSBuild,然后编写了一个简单的代码,如下所示。
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.MSBuild;
using System;
using System.Linq;
namespace SimpleRoslynConsole
{
class Program
{
static void Main(string[] args)
{
// Declaring a variable with the current project file path.
// *** You have to change this path to fit your development environment.
const string projectPath =
@"C:\Users\[MyName]\Source\Repos\RoslynTrialConsole01\RoslynTrialConsole01.csproj";
var workspace = MSBuildWorkspace.Create();
var project = workspace.OpenProjectAsync(projectPath).Result;
// [**1]Getting the compilation.
var compilation = project.GetCompilationAsync().Result;
// [**2]As this is a simple single file program, the first syntax tree will be the current file.
var syntaxTree = compilation.SyntaxTrees.FirstOrDefault();
if (syntaxTree != null)
{
var rootSyntaxNode = syntaxTree.GetRootAsync().Result;
var firstLocalVariablesDeclaration = rootSyntaxNode.DescendantNodesAndSelf()
.OfType<LocalDeclarationStatementSyntax>().First();
var firstVariable = firstLocalVariablesDeclaration.Declaration.Variables.First();
var variableInitializer = firstVariable.Initializer.Value.GetFirstToken().ValueText;
Console.WriteLine(variableInitializer);
}
else
{
Console.WriteLine("Could not get SyntaxTrees from this projects.");
}
Console.WriteLine("Hit any key.");
Console.ReadKey();
}
}
}
我的问题是,Compilation对象的SyntaxTrees属性在[** 2]标记中返回null。当然,在FirstOrDefault方法之后返回null。
我已经尝试了其他几个代码。我发现我可以使用CSharpSyntaxTree.ParseText方法从CSharp代码文本中获取SyntaxTree。但我无法从源代码中获取任何内容
var workspace = MSBuildWorkspace.Create();
var project = workspace.OpenProjectAsync(projectPath).Result;
var compilation = project.GetCompilationAsync().Result;
我想知道的是,如果我错过了一些东西,可以通过上面的过程从源代码中获取语法信息。
我很感激有人给我一个很好的建议。
除非您的应用程序的app.config文件中包含msbuild.exe.config中包含的所有相同重定向,否则MsBuildWorkspace将无法正常工作。没有重定向,它可能无法加载msbuild库。您需要找到系统上的msbuild.exe.config文件,并将与Microsoft.Build程序集相关的<assemblyBinding>
元素复制到app.config中。确保将它们放在正确的元素配置/运行时下。
我在网上搜索了各种样本程序,找到了最可靠,最安全的方法。解决方案是创建一个静态方法,在指定的File中返回SyntaxTrees,如下所示。
private static Compilation CreateTestCompilation()
{
var found = false;
var di = new DirectoryInfo(Environment.CurrentDirectory);
var fi = di.GetFiles().Where((crt) => { return crt.Name.Equals("program.cs", StringComparison.CurrentCultureIgnoreCase); }).FirstOrDefault();
while ((fi == null) || (di.Parent == null))
{
di = new DirectoryInfo(di.Parent.FullName);
fi = di.GetFiles().Where((crt) => { return crt.Name.Equals("program.cs", StringComparison.CurrentCultureIgnoreCase); }).FirstOrDefault();
if (fi != null)
{
found = true;
break;
}
}
if (!found)
{
return null;
}
var targetPath = di.FullName + @"\Program.cs";
var targetText = File.ReadAllText(targetPath);
var targetTree =
CSharpSyntaxTree.ParseText(targetText)
.WithFilePath(targetPath);
var target2Path = di.FullName + @"\TypeInferenceRewriter.cs";
var target2Text = File.ReadAllText(target2Path);
var target2Tree =
CSharpSyntaxTree.ParseText(target2Text)
.WithFilePath(target2Path);
SyntaxTree[] sourceTrees = { programTree, target2Tree };
MetadataReference mscorlib =
MetadataReference.CreateFromFile(typeof(object).Assembly.Location);
MetadataReference codeAnalysis =
MetadataReference.CreateFromFile(typeof(SyntaxTree).Assembly.Location);
MetadataReference csharpCodeAnalysis =
MetadataReference.CreateFromFile(typeof(CSharpSyntaxTree).Assembly.Location);
MetadataReference[] references = { mscorlib, codeAnalysis, csharpCodeAnalysis };
return CSharpCompilation.Create("TransformationCS",
sourceTrees,
references,
new CSharpCompilationOptions(
OutputKind.ConsoleApplication));
}
而来电程序将是这样的。
static void Main(string[] args)
{
var test = CreateTestCompilation();
if (test == null)
{
return;
}
foreach (SyntaxTree sourceTree in test.SyntaxTrees)
{
Console.WriteLine(souceTree.ToFullString());
}
}
当然,需要进行许多改进才能将其付诸实践。