0
votes

I have installed Microsoft.CodeAnalysis.CSharp & Microsoft.CodeAnalysis.CSharp.Scripting (Version 3.3.1) packages in the .Net Core 2.2 Console Application and also I have developed the codes below :

SyntaxTree syntaxTree = CSharpSyntaxTree.ParseText(@"
    public class MyGlobals
    {
        public int Age {get; set;} = 21;
    }
");

var references = new List<MetadataReference>
{
    MetadataReference.CreateFromFile(typeof(object).Assembly.Location)
};

var compilation = CSharpCompilation.Create("DynamicAssembly")
    .WithOptions(new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary))
    .AddSyntaxTrees(syntaxTree)
    .AddReferences(references);

Type globalsType = null;
Assembly assembly = null;
using (var memoryStream = new MemoryStream())
{
    var compileResult = compilation.Emit(memoryStream);
    assembly = Assembly.Load(memoryStream.GetBuffer());

    if (compileResult.Success)
    {
        globalsType = assembly.GetType("MyGlobals");
    }
}
var globals = Activator.CreateInstance(globalsType);
var validationResult = CSharpScript.EvaluateAsync<bool>("Age == 21", globals: globals);

The globals object is created but the expression is not evaluated and the following exception is throwed by CSharpScript :

The name 'Age' does not exist in the current context (are you missing a reference to assembly 'DynamicAssembly, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'?)'

Is there a setting I missed?

1
I think the problem might be globals variable is of type object. You probably need to cast it to MyGlobals type.dropoutcoder
I think there's still an issue...Peter Schneider
@dropoutcoder How can I change the globals variable type to a dynamic class which generated by SyntaxTree ?!Mohsen Alikhani
you may try dynamic globals = Activator.CreateInstance(globalsType);dropoutcoder
Why would that make a difference, @dropoutcoder?Paulo Morgado

1 Answers

0
votes

The reason why you get an error is the absence of reference to DynamicAssembly you just created. To fix this you may pass ScriptOptions to CSharpScript.EvaluateAsync<bool>() call. The following code runs well for me.

SyntaxTree syntaxTree = CSharpSyntaxTree.ParseText(@"
public class MyGlobals
{
    public int Age {get; set;} = 21;
}
");

var references = new List<MetadataReference>
{
    MetadataReference.CreateFromFile(typeof(object).Assembly.Location)
};

var compilation = CSharpCompilation.Create("DynamicAssembly")
    .WithOptions(new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary))
    .AddSyntaxTrees(syntaxTree)
    .AddReferences(references);

Type globalsType = null;
Assembly assembly = null;
using (var memoryStream = new MemoryStream())
{
    var compileResult = compilation.Emit(memoryStream);
    var buffer = memoryStream.GetBuffer();
    File.WriteAllBytes("DynamicAssembly.dll", buffer);
    assembly = Assembly.LoadFile(Path.GetFullPath("DynamicAssembly.dll"));

    if (compileResult.Success)
    {
        globalsType = assembly.GetType("MyGlobals");
    }
}

var globals = Activator.CreateInstance(globalsType);
var options = ScriptOptions.Default.WithReferences("DynamicAssembly.dll");

var validationResult = CSharpScript.EvaluateAsync<bool>(
    "Age == 21",
    globals: globals,
    options: options
);
Console.WriteLine(await validationResult);