84 lines
2.8 KiB
C#
84 lines
2.8 KiB
C#
using System.Reflection;
|
|
using InterfaceForward.Application.Contracts.ForwardCore;
|
|
using Microsoft.CodeAnalysis;
|
|
|
|
namespace InterfaceForward.Application.ForwardCore;
|
|
|
|
internal static class NatashaScriptCompiler
|
|
{
|
|
public static Action<ForwardCoreContext> CompileAction(string script)
|
|
{
|
|
var method = Compile(script, "void");
|
|
return method.CreateDelegate<Action<ForwardCoreContext>>();
|
|
}
|
|
|
|
public static Func<ForwardCoreContext, Task> CompileAsyncFunc(string script)
|
|
{
|
|
var method = Compile(script, "async System.Threading.Tasks.Task");
|
|
return method.CreateDelegate<Func<ForwardCoreContext, Task>>();
|
|
}
|
|
|
|
static MethodInfo Compile(string script, string returnType)
|
|
{
|
|
var typeName = "Script_" + Guid.NewGuid().ToString("N");
|
|
var code = $$"""
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Threading.Tasks;
|
|
using InterfaceForward.Application.Contracts.ForwardCore;
|
|
using InterfaceForward.Domain.Shared;
|
|
using InterfaceForward.Domain.Shared.Dtos;
|
|
using InterfaceForward.Domain.Shared.Enum;
|
|
using Newtonsoft.Json.Linq;
|
|
|
|
public static class {{typeName}}
|
|
{
|
|
public static {{returnType}} Run(ForwardCoreContext obj)
|
|
{
|
|
var context = obj;
|
|
{{script}}
|
|
}
|
|
}
|
|
""";
|
|
|
|
var assembly = new AssemblyCSharpBuilder()
|
|
.UseRandomDomain()
|
|
.WithSpecifiedReferences(GetMetadataReferences())
|
|
.Add(code)
|
|
.GetAssembly();
|
|
|
|
return assembly
|
|
.GetType(typeName, throwOnError: true)!
|
|
.GetMethod("Run", BindingFlags.Public | BindingFlags.Static)!;
|
|
}
|
|
|
|
static IEnumerable<MetadataReference> GetMetadataReferences()
|
|
{
|
|
var paths = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
|
|
|
|
if (AppContext.GetData("TRUSTED_PLATFORM_ASSEMBLIES") is string trustedPlatformAssemblies)
|
|
{
|
|
foreach (var path in trustedPlatformAssemblies.Split(Path.PathSeparator))
|
|
{
|
|
AddPath(path);
|
|
}
|
|
}
|
|
|
|
foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
|
|
{
|
|
AddPath(assembly.Location);
|
|
}
|
|
|
|
return paths.Select(path => MetadataReference.CreateFromFile(path));
|
|
|
|
void AddPath(string? path)
|
|
{
|
|
if (!string.IsNullOrWhiteSpace(path) && File.Exists(path))
|
|
{
|
|
paths.Add(path);
|
|
}
|
|
}
|
|
}
|
|
}
|