如何使用 Roslyn 的 OpenSolutionAsync 解析所有引用?
How can I resolve all references with Roslyn's OpenSolutionAsync?
我正在尝试使用 OpenSolutionAsync 打开 RoslynLight.sln,然后遍历所有项目。出于我的目的,我需要一个语义模型和已解析的引用。通过这个 issue and this question 的组合,我得到了这个部分解决方案:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.MSBuild;
using System.IO;
namespace OpenRoslyn
{
class Program
{
static void Main(string[] args)
{
var msbw = MSBuildWorkspace.Create();
var sln = msbw.OpenSolutionAsync(@"C:\Users\carr27\Documents\GitHub\roslyn\src\RoslynLight.sln").Result;
//var proj = sln.Projects.First(x => x.Name == "CodeAnalysis.Desktop");
var messages = new List<string>();
foreach (var p in sln.Projects)
{
Console.WriteLine(p.FilePath);
messages.Add(p.FilePath);
var facadesDir = @"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6\Facades\";
var proj = p.AddMetadataReference(MetadataReference.CreateFromAssembly(typeof(object).Assembly));
proj = proj.AddMetadataReference(MetadataReference.CreateFromFile(facadesDir + "System.Runtime.dll"));
proj = proj.AddMetadataReference(MetadataReference.CreateFromFile(facadesDir + "System.Runtime.Extensions.dll"));
proj = proj.AddMetadataReference(MetadataReference.CreateFromFile(facadesDir + "System.IO.dll"));
proj = proj.AddMetadataReference(MetadataReference.CreateFromFile(facadesDir + "System.Threading.Tasks.dll"));
proj = proj.AddMetadataReference(MetadataReference.CreateFromFile(facadesDir + "System.Text.Encoding.dll"));
proj = proj.AddMetadataReference(MetadataReference.CreateFromFile(facadesDir + "System.Reflection.dll"));
try
{
var cu = proj.GetCompilationAsync().Result;
// here I would do useful work, but for know I just get diagnostics
foreach (var e in cu.GetDiagnostics().Where(x => x.Severity == DiagnosticSeverity.Error))
{
Console.WriteLine("{0}: {1}", e.Location, e.GetMessage());
messages.Add(String.Format("{0}: {1}", e.Location, e.GetMessage()));
}
}
catch (AggregateException e)
{
foreach(var ie in e.InnerExceptions)
{
Console.WriteLine(ie.Message);
messages.Add(ie.Message);
}
}
catch (Exception e)
{
Console.WriteLine(e.Message);
messages.Add(e.Message);
}
}
File.WriteAllLines("log.txt", messages);
Console.WriteLine("done.");
Console.ReadKey();
}
}
}
这个程序的日志对我来说太大了post,但是变通方法只适用于某些项目。例如,rosyln\src\compilers\Core\Desktop\CodeAnalysis.Desktop.csproj 没有错误,但 roslyn\src\Compilers\CSharp\Portable\CSharpCodeAnalysis.csproj 有:
None: Multiple assemblies with equivalent identity have been imported: 'C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETPortable\v4.5\Profile\Profile7\System.Threading.Tasks.dll' and 'C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6\Facades\System.Threading.Tasks.dll'. Remove one of the duplicate references.
None: Multiple assemblies with equivalent identity have been imported: 'C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETPortable\v4.5\Profile\Profile7\System.Text.Encoding.dll' and 'C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6\Facades\System.Text.Encoding.dll'. Remove one of the duplicate references.
None: Multiple assemblies with equivalent identity have been imported: 'C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETPortable\v4.5\Profile\Profile7\System.Runtime.Extensions.dll' and 'C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6\Facades\System.Runtime.Extensions.dll'. Remove one of the duplicate references.
None: Multiple assemblies with equivalent identity have been imported: 'C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETPortable\v4.5\Profile\Profile7\System.Runtime.dll' and 'C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6\Facades\System.Runtime.dll'. Remove one of the duplicate references.
None: Multiple assemblies with equivalent identity have been imported: 'C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETPortable\v4.5\Profile\Profile7\System.Reflection.dll' and 'C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6\Facades\System.Reflection.dll'. Remove one of the duplicate references.
None: Multiple assemblies with equivalent identity have been imported: 'C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETPortable\v4.5\Profile\Profile7\System.IO.dll' and 'C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6\Facades\System.IO.dll'. Remove one of the duplicate references.
SourceFile(C:\Users\carr27\Documents\GitHub\roslyn\src\Compilers\CSharp\Portable\BoundTree\UnboundLambda.cs[9068..9109)): The type 'ConcurrentDictionary<TKey, TValue>' exists in both 'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' and 'System.Collections.Concurrent, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'
SourceFile(C:\Users\carr27\Documents\GitHub\roslyn\src\Compilers\CSharp\Portable\BoundTree\UnboundLambda.cs[9203..9250)): The type 'ConcurrentDictionary<TKey, TValue>' exists in both 'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' and 'System.Collections.Concurrent, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'
...以及许多其他人。在我看来,我可以通过任何方式使这项工作适用于任意 project/solution 都非常 hacky。我错过了什么吗?
如果项目以 "full" .NET 框架为目标,您只需要添加 façade 引用。因此,如果您首先查看现有引用,如果有来自 Reference Assemblies\Microsoft.NETPortable\v4.5\Profile\... 的任何引用,则您不需要添加它们。
我正在考虑在 MSBuild 目标中修复此问题,但与此同时,以下解决方法应该可以解决该问题。而不是使用:
MSBuildWorkspace.Create();
使用:
MSBuildWorkspace.Create(new Dictionary<string, string> { { "CheckForSystemRuntimeDependency", "true" } });
我正在尝试使用 OpenSolutionAsync 打开 RoslynLight.sln,然后遍历所有项目。出于我的目的,我需要一个语义模型和已解析的引用。通过这个 issue and this question 的组合,我得到了这个部分解决方案:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.MSBuild;
using System.IO;
namespace OpenRoslyn
{
class Program
{
static void Main(string[] args)
{
var msbw = MSBuildWorkspace.Create();
var sln = msbw.OpenSolutionAsync(@"C:\Users\carr27\Documents\GitHub\roslyn\src\RoslynLight.sln").Result;
//var proj = sln.Projects.First(x => x.Name == "CodeAnalysis.Desktop");
var messages = new List<string>();
foreach (var p in sln.Projects)
{
Console.WriteLine(p.FilePath);
messages.Add(p.FilePath);
var facadesDir = @"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6\Facades\";
var proj = p.AddMetadataReference(MetadataReference.CreateFromAssembly(typeof(object).Assembly));
proj = proj.AddMetadataReference(MetadataReference.CreateFromFile(facadesDir + "System.Runtime.dll"));
proj = proj.AddMetadataReference(MetadataReference.CreateFromFile(facadesDir + "System.Runtime.Extensions.dll"));
proj = proj.AddMetadataReference(MetadataReference.CreateFromFile(facadesDir + "System.IO.dll"));
proj = proj.AddMetadataReference(MetadataReference.CreateFromFile(facadesDir + "System.Threading.Tasks.dll"));
proj = proj.AddMetadataReference(MetadataReference.CreateFromFile(facadesDir + "System.Text.Encoding.dll"));
proj = proj.AddMetadataReference(MetadataReference.CreateFromFile(facadesDir + "System.Reflection.dll"));
try
{
var cu = proj.GetCompilationAsync().Result;
// here I would do useful work, but for know I just get diagnostics
foreach (var e in cu.GetDiagnostics().Where(x => x.Severity == DiagnosticSeverity.Error))
{
Console.WriteLine("{0}: {1}", e.Location, e.GetMessage());
messages.Add(String.Format("{0}: {1}", e.Location, e.GetMessage()));
}
}
catch (AggregateException e)
{
foreach(var ie in e.InnerExceptions)
{
Console.WriteLine(ie.Message);
messages.Add(ie.Message);
}
}
catch (Exception e)
{
Console.WriteLine(e.Message);
messages.Add(e.Message);
}
}
File.WriteAllLines("log.txt", messages);
Console.WriteLine("done.");
Console.ReadKey();
}
}
}
这个程序的日志对我来说太大了post,但是变通方法只适用于某些项目。例如,rosyln\src\compilers\Core\Desktop\CodeAnalysis.Desktop.csproj 没有错误,但 roslyn\src\Compilers\CSharp\Portable\CSharpCodeAnalysis.csproj 有:
None: Multiple assemblies with equivalent identity have been imported: 'C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETPortable\v4.5\Profile\Profile7\System.Threading.Tasks.dll' and 'C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6\Facades\System.Threading.Tasks.dll'. Remove one of the duplicate references.
None: Multiple assemblies with equivalent identity have been imported: 'C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETPortable\v4.5\Profile\Profile7\System.Text.Encoding.dll' and 'C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6\Facades\System.Text.Encoding.dll'. Remove one of the duplicate references.
None: Multiple assemblies with equivalent identity have been imported: 'C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETPortable\v4.5\Profile\Profile7\System.Runtime.Extensions.dll' and 'C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6\Facades\System.Runtime.Extensions.dll'. Remove one of the duplicate references.
None: Multiple assemblies with equivalent identity have been imported: 'C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETPortable\v4.5\Profile\Profile7\System.Runtime.dll' and 'C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6\Facades\System.Runtime.dll'. Remove one of the duplicate references.
None: Multiple assemblies with equivalent identity have been imported: 'C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETPortable\v4.5\Profile\Profile7\System.Reflection.dll' and 'C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6\Facades\System.Reflection.dll'. Remove one of the duplicate references.
None: Multiple assemblies with equivalent identity have been imported: 'C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETPortable\v4.5\Profile\Profile7\System.IO.dll' and 'C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6\Facades\System.IO.dll'. Remove one of the duplicate references.
SourceFile(C:\Users\carr27\Documents\GitHub\roslyn\src\Compilers\CSharp\Portable\BoundTree\UnboundLambda.cs[9068..9109)): The type 'ConcurrentDictionary<TKey, TValue>' exists in both 'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' and 'System.Collections.Concurrent, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'
SourceFile(C:\Users\carr27\Documents\GitHub\roslyn\src\Compilers\CSharp\Portable\BoundTree\UnboundLambda.cs[9203..9250)): The type 'ConcurrentDictionary<TKey, TValue>' exists in both 'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' and 'System.Collections.Concurrent, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'
...以及许多其他人。在我看来,我可以通过任何方式使这项工作适用于任意 project/solution 都非常 hacky。我错过了什么吗?
如果项目以 "full" .NET 框架为目标,您只需要添加 façade 引用。因此,如果您首先查看现有引用,如果有来自 Reference Assemblies\Microsoft.NETPortable\v4.5\Profile\... 的任何引用,则您不需要添加它们。
我正在考虑在 MSBuild 目标中修复此问题,但与此同时,以下解决方法应该可以解决该问题。而不是使用:
MSBuildWorkspace.Create();
使用:
MSBuildWorkspace.Create(new Dictionary<string, string> { { "CheckForSystemRuntimeDependency", "true" } });