简体   繁体   中英

Automatically resolving dependencies when compiling using Roslyn

I'm currently writing an application that currently loads a project via Roslyn's workspace API, turns a specified C# file into a syntax tree then creates an in memory assembly form it, then eventually extracts the IL.

This is all working fine, however as soon as I reference any external libraries within the said C# file, the compilation fails as Roslyn doesn't know where to resolve those references.

Here's a simplified version of what I'm currently doing:

MetadataReference[] metaDatareferences = {
    MetadataReference.CreateFromFile(typeof(object).GetTypeInfo().Assembly.Location),
    MetadataReference.CreateFromFile(typeof(Uri).GetTypeInfo().Assembly.Location),
    MetadataReference.CreateFromFile(typeof(DynamicAttribute).GetTypeInfo().Assembly.Location),
    MetadataReference.CreateFromFile(typeof(AssemblyMetadata).GetTypeInfo().Assembly.Location),
};

var sourceLanguage = new CSharpLanguage();

var syntaxTree = sourceLanguage.ParseText(sourceCode, SourceCodeKind.Regular);
var options = new CSharpCompilationOptions(
    OutputKind.DynamicallyLinkedLibrary,
    optimizationLevel: OptimizationLevel.Debug,
    allowUnsafe: true
);

CSharpCompilation compilation = CSharpCompilation.Create("ExampleAssembly", options: options);

var stream = new MemoryStream();
var result = compilation.
    AddReferences(metaDatareferences)
    .AddSyntaxTrees(syntaxTree)
    .Emit(stream);

// Success is false
if (!emitResult.Success)
{
    foreach (var diagnostic in emitResult.Diagnostics)
    {
        Debug.WriteLine(diagnostic.ToString());
    }
}

The output of the Debug.WriteLine is:

(1,7): error CS0246: The type or namespace name 'MediatR' could not be found (are you missing a using directive or an assembly reference?)
(9,32): error CS0246: The type or namespace name 'Mediator' could not be found (are you missing a using directive or an assembly reference?)

And the file my Roslyn project is reading is simply this:

using MediatR;

namespace ConsoleApplication
{
    public class Program
    {
        public static void Main(string[] args)
        {
            var mediator = new Mediator(null, null);
        }
    }
}

My question is, does Roslyn provide an API for automatically load any dependencies a file may have? I was hopeful that the Roslyn workspace would allow this to be done, but I've not been able to find anything.

If the MediatR console project is a project.json project, then you can use ProjectJsonWorkspace from "Microsoft.DotNet.ProjectModel.Workspaces": "1.0.0-preview2-1-003177" . You can point it at your project.json and get a Compilation object, this will have done all the hard work for you of getting the project references, file references, etc... Then you can just emit your IL from here.

Here is an example:

var compilation = new ProjectJsonWorkspace(@"PathToYour\project.json").CurrentSolution.Projects.First().GetCompilationAsync().Result;

var stream = new MemoryStream();
var emitResult = compilation.Emit(stream);

Or if you need total control, you could continue to use CSharpCompilation.Create , copying in what you need from the compilation object here, and passing in a SyntaxTree .

Hope that helps.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM