fix:natasha 8.0

This commit is contained in:
xiaolipro 2026-06-01 17:09:54 +08:00
parent b78cce31fd
commit 18ff452ca7
6 changed files with 129 additions and 20 deletions

View File

@ -1,5 +1,6 @@
{
"sdk": {
"version": "8.0.303"
"version": "8.0.421",
"rollForward": "latestFeature"
}
}
}

View File

@ -647,14 +647,14 @@ public class DefaultForwardFlow : IForwardFlow, ITransientDependency
if (script.StartsWith("//async") || script.Contains("await"))
{
var @delegate = DelegateDic.GetOrAdd(scriptHash,
static (_, arg) => NDelegate.RandomDomain().AsyncFunc<ForwardCoreContext, Task>(arg), script);
static (_, arg) => NatashaScriptCompiler.CompileAsyncFunc(arg), script);
await (Task)@delegate.DynamicInvoke(context)!;
}
else
{
var @delegate = DelegateDic.GetOrAdd(scriptHash,
static (_, arg) => NDelegate.RandomDomain().Action<ForwardCoreContext>(arg), script);
static (_, arg) => NatashaScriptCompiler.CompileAction(arg), script);
@delegate.DynamicInvoke(context);
}
}
}
}

View File

@ -0,0 +1,83 @@
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);
}
}
}
}

View File

@ -3,7 +3,7 @@
<Import Project="../../common.props"/>
<PropertyGroup>
<TargetFramework>net8</TargetFramework>
<TargetFramework>net8.0</TargetFramework>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
</PropertyGroup>
@ -16,7 +16,9 @@
<ItemGroup>
<PackageReference Include="DiffPlex" Version="1.9.0" />
<PackageReference Include="Aliyun.OSS.SDK.NetCore" Version="2.14.1" />
<PackageReference Include="DotNetCore.Natasha.CSharp" Version="5.2.2.1"/>
<PackageReference Include="DotNetCore.Compile.Environment" Version="3.2.0" />
<PackageReference Include="DotNetCore.Natasha.CSharp.Compiler" Version="8.0.0" />
<PackageReference Include="DotNetCore.Natasha.CSharp.Compiler.Domain" Version="8.0.0" />
<PackageReference Include="Fake.AspNetCore" Version="$(FakePackageVersion)" />
<PackageReference Include="Fake.EventBus.RabbitMQ" Version="$(FakePackageVersion)" />
<PackageReference Include="Fake.ObjectMapping.AutoMapper" Version="$(FakePackageVersion)" />

View File

@ -6,6 +6,8 @@ using Fake.ObjectMapping.AutoMapper;
using Fake.RabbitMQ;
using FreeRedis;
using InterfaceForward.Application.Contracts;
using InterfaceForward.Application.Contracts.ForwardCore;
using InterfaceForward.Application.ForwardCore;
using InterfaceForward.Application.Helpers;
using InterfaceForward.Application.HostServices;
using InterfaceForward.Domain.Shared;
@ -26,7 +28,7 @@ public class InterfaceForwardApplicationModule:FakeModule
public override void ConfigureServices(ServiceConfigurationContext context)
{
var configuration = context.Services.GetConfiguration();
context.Services.Configure<FakeAutoMapperOptions>(options =>
{
options.ScanProfiles<InterfaceForwardApplicationModule>();
@ -35,28 +37,49 @@ public class InterfaceForwardApplicationModule:FakeModule
context.Services.Configure<InterfaceRelayOptions>(configuration.GetSection("InterfaceRelay"));
context.Services.AddHostedService<AppSubscribeHostService>();
var options = configuration.GetSection("Redis").Get<ConnectionStringBuilder>();
if (options == null)
throw new FakeException("未找到Redis相关配置请检查配置文件中是否包含名为Redis的节点");
RedisHelper.Init(options, showLogInfo: System.Diagnostics.Debugger.IsAttached);
// 预热
NatashaInitializer.Preheating();
context.Services.AddHttpClient("forward", client =>
{
client.Timeout = TimeSpan.FromSeconds(20);
})
// 预热并验证动态脚本编译环境。
PreheatNatasha();
context.Services.AddHttpClient("forward", client => { client.Timeout = TimeSpan.FromSeconds(20); })
.ConfigurePrimaryHttpMessageHandler(_ =>
{
var httpClientHandler = new HttpClientHandler();
// 确保支持较新的 SSL/TLS 版本
httpClientHandler.SslProtocols = SslProtocols.Tls12 | SslProtocols.Tls13;
// 忽略 SSL/TLS 证书错误
httpClientHandler.ServerCertificateCustomValidationCallback =
httpClientHandler.ServerCertificateCustomValidationCallback =
HttpClientHandler.DangerousAcceptAnyServerCertificateValidator;
return httpClientHandler;
});
}
}
static void PreheatNatasha()
{
NatashaManagement.Preheating<NatashaDomainCreator>(false, false);
var context = new ForwardCoreContext();
NatashaScriptCompiler.CompileAction("""
obj.FormFieldList.Add(new InterfaceForward.Domain.Shared.Dtos.InterfaceFormFieldDto
{
Name = "_natasha_health",
Value = obj.GetAccountFieldValueOrNull("_missing") ?? "ok"
});
""")(context);
NatashaScriptCompiler.CompileAsyncFunc("""
//async
await System.Threading.Tasks.Task.CompletedTask;
obj.FormFieldList.Add(new InterfaceForward.Domain.Shared.Dtos.InterfaceFormFieldDto
{
Name = "_natasha_async_health",
Value = "ok"
});
""")(context).GetAwaiter().GetResult();
}
}

View File

@ -3,7 +3,7 @@
<Import Project="../../common.props" />
<PropertyGroup>
<TargetFramework>net8</TargetFramework>
<TargetFramework>net8.0</TargetFramework>
</PropertyGroup>
<ItemGroup>