I am creating a Roslyn .NET source generator. With it I am inspecting user code for lambda expressions given as an argument in a method call like this:
// User Code
MyLibrary.MyMethod<Guid>(k => $"alfa/{k.SomeMethod()}");
I want to, within my source generator at compile-time, take the LambdaExpressionSyntax
node k => $"alfa/{k.SomeMethod()}"
and transplant it to some simple code I will generate and run to interrogate it for e.g. its run-time expression tree shape or call its .ToString()
method:
// Generated Code
using System;
using Etc;
Expression<Func<Guid, string>> expression = k => $"alfa/{k.SomeMethod()}";
return expression;
I have so far discovered the CSharpScript.EvaluateAsync()
method, which seems like the easiest way to compile and execute the code.
Unfortunately, this (and probably any) approach requires me to sus out what the dependencies are of the expression I am trying to transplant, so that I can generate the appropriate using
statements and add the required library references to the compilation.
For example, SomeMethod()
above is an extension method that lives in a separate class library from the inspected user code. Its namespace and class library will need to be included in the using
s and compilation references.
Supposing I have a magic method to get the referenced types, what I have so far is something like this:
var referencedTypes = GetReferencedTypes(lambdaExpressionSyntax);
var result = CSharpScript
.EvaluateAsync(
code,
ScriptOptions.Default
.AddReferences(
typeof(Func<,>).Assembly,
typeof(Expression).Assembly)
.AddReferences(referencedTypes
.Select(t => t.ContainingAssembly.GetMetadata().GetReference())
.ToArray()))
.Result;
Unfortunately the way I am trying to add the references does not appear to work. I get an error at runtime that the assembly could not be found.
So my questions are:
- How do I correctly determine all of the dependencies for a given
LambdaExpressionSyntax
? - How do I properly add references to those dependencies when calling
CSharpScript.EvaluateAsync()
? - Is there a better or simpler way of achieving what I am trying to do?