refactor(flow) : 重新实现了UIContextOperation的注入逻辑,为后续开发Avalonia版本的编辑器做准备。

This commit is contained in:
fengjiayi
2025-09-19 23:58:52 +08:00
parent 0161c64e2c
commit 630008198d
21 changed files with 415 additions and 200 deletions

View File

@@ -24,21 +24,21 @@ namespace Serein.NodeFlow.Env
private readonly FlowLibraryService flowLibraryService;
private readonly FlowOperationService flowOperationService;
private readonly FlowModelService flowModelService;
private readonly UIContextOperation UIContextOperation;
private readonly UIContextOperation uiContextOperation;
public FlowControl(IFlowEnvironment flowEnvironment,
IFlowEnvironmentEvent flowEnvironmentEvent,
FlowLibraryService flowLibraryService,
FlowOperationService flowOperationService,
FlowModelService flowModelService,
UIContextOperation UIContextOperation)
UIContextOperation uiContextOperation)
{
this.flowEnvironment = flowEnvironment;
this.flowEnvironmentEvent = flowEnvironmentEvent;
this.flowLibraryService = flowLibraryService;
this.flowOperationService = flowOperationService;
this.flowModelService = flowModelService;
this.UIContextOperation = UIContextOperation;
this.uiContextOperation = uiContextOperation;
contexts = new ObjectPool<IFlowContext>(() => new FlowContext(flowEnvironment), context => context.Reset());
flowTaskOptions = new FlowWorkOptions
@@ -340,7 +340,7 @@ namespace Serein.NodeFlow.Env
{
flowWorkManagement.Exit();
}
UIContextOperation?.Invoke(() => flowEnvironmentEvent.OnFlowRunComplete(new FlowEventArgs()));
uiContextOperation?.Invoke(() => flowEnvironmentEvent.OnFlowRunComplete(new FlowEventArgs()));
IOC.Reset();
GC.Collect();
return Task.FromResult(true);

View File

@@ -63,7 +63,44 @@ namespace Serein.NodeFlow.Env
.Build();
// 设置JSON解析器
JsonHelper.UseJsonProvider(new NewtonsoftJsonProvider());
if (JsonHelper.Provider is null)
{
JsonHelper.UseJsonProvider(new NewtonsoftJsonProvider());
}
// 默认使用本地环境
currentFlowEnvironment = ioc.Get<LocalFlowEnvironment>();
currentFlowEnvironmentEvent = ioc.Get<IFlowEnvironmentEvent>();
SereinEnv.SetEnv(currentFlowEnvironment);
}
/// <summary>
/// 提供上下文操作进行调用
/// </summary>
/// <param name="operation"></param>
public FlowEnvironment(UIContextOperation operation)
{
ISereinIOC ioc = new SereinIOC();
ioc.Register<ISereinIOC>(()=> ioc) // IOC容器接口
.Register<UIContextOperation>(() => operation) // 流程环境接口
.Register<IFlowEnvironment>(() => this) // 流程环境接口
.Register<IFlowEnvironmentEvent, FlowEnvironmentEvent>() // 流程环境事件接口
.Register<IFlowEdit, FlowEdit>() // 流程编辑接口
.Register<IFlowControl, FlowControl>() // 流程控制接口
.Register<LocalFlowEnvironment>() // 本地环境
.Register<FlowModelService>() // 节点/画布模型服务
.Register<FlowLibraryService>() // 流程库服务
.Register<FlowCoreGenerateService>() // 代码生成
.Register<FlowOperationService>() // 流程操作
.Register<NodeMVVMService>() // 节点MVVM服务
.Build();
// 设置JSON解析器
if (JsonHelper.Provider is null)
{
JsonHelper.UseJsonProvider(new NewtonsoftJsonProvider());
}
// 默认使用本地环境
currentFlowEnvironment = ioc.Get<LocalFlowEnvironment>();
currentFlowEnvironmentEvent = ioc.Get<IFlowEnvironmentEvent>();

View File

@@ -245,12 +245,14 @@ namespace Serein.NodeFlow.Env
/// <param name="filePath"></param>
public void LoadProject(string filePath)
{
string content = System.IO.File.ReadAllText(filePath); // 读取整个文件内容
_ = Task.Run(async () =>
{
await this.LoadProjetAsync((filePath));
});
/*string content = System.IO.File.ReadAllText(filePath); // 读取整个文件内容
var FlowProjectData = JsonHelper.Deserialize<SereinProjectData>(content);
var FileDataPath = System.IO.Path.GetDirectoryName(filePath)!; // filePath;//
this.ProjectFileLocation = filePath;
var projectData = FlowProjectData;
@@ -285,30 +287,50 @@ namespace Serein.NodeFlow.Env
}
Event.OnProjectLoaded(new ProjectLoadedEventArgs());
});
});*/
}
public async Task LoadProjetAsync(string filePath)
{
string content = await System.IO.File.ReadAllTextAsync(filePath); // 读取整个文件内容
var FlowProjectData = JsonHelper.Deserialize<SereinProjectData>(content);
var FileDataPath = System.IO.Path.GetDirectoryName(filePath)!; // filePath;//
if(FlowProjectData is null)
var content = await System.IO.File.ReadAllTextAsync(filePath); // 读取整个文件内容
var flowProjectData = JsonHelper.Deserialize<SereinProjectData>(content);
var fileDataPath = System.IO.Path.GetDirectoryName(filePath)!; // filePath;//
if(flowProjectData is null)
{
return;
}
var projectData = flowProjectData ?? throw new ArgumentNullException(nameof(flowProjectData));
if (!_flowLibraryService.IsLoadedBaseLibrary)
{
var baseLibrary = _flowLibraryService.LoadBaseLibrary();
if (baseLibrary.MethodInfos.Count > 0 && UIContextOperation is not null)
{
await UIContextOperation.InvokeAsync(() => Event.OnDllLoad(new LoadDllEventArgs(baseLibrary))); // 通知UI创建dll面板显示
}
if (_flowModelService.GetAllCanvasModel().Count == 0)
{
// 创建第一个画布
FlowEdit.CreateCanvas("Default", 1920, 1080);
}
}
this.ProjectFileLocation = filePath;
var projectData = FlowProjectData;
// 加载项目配置文件
var dllPaths = projectData.Librarys.Select(it => it.FilePath).ToList();
List<MethodDetails> methodDetailss = [];
// 遍历依赖项中的特性注解,生成方法详情
foreach (var dllPath in dllPaths)
{
string cleanedRelativePath = dllPath.TrimStart('.', '\\');
var cleanedRelativePath = dllPath.TrimStart('.', '\\');
var tmpPath = Path.Combine(filePath, cleanedRelativePath);
var dllFilePath = Path.GetFullPath(tmpPath);
LoadLibrary(dllFilePath); // 加载项目文件时加载对应的程序集
@@ -526,7 +548,8 @@ namespace Serein.NodeFlow.Env
return;
}
this.UIContextOperation = uiContextOperation;
IOC.Register<UIContextOperation>(() => uiContextOperation).Build();
IOC.Register<UIContextOperation>(() => uiContextOperation);
IOC.Build();
OnUIContextOperationSet();
}
@@ -656,18 +679,11 @@ namespace Serein.NodeFlow.Env
#endregion
/// <summary>
/// 设置了 UIContextOperation 需要立刻执行的方法,用于加载基础库,创建第一个画布。
/// 设置了 UIContextOperation 需要立刻执行的方法
/// </summary>
private void OnUIContextOperationSet()
{
var baseLibrary = _flowLibraryService.LoadBaseLibrary();
if (baseLibrary is not null && baseLibrary.MethodInfos.Count > 0)
{
UIContextOperation?.Invoke(() => Event.OnDllLoad(new LoadDllEventArgs(baseLibrary))); // 通知UI创建dll面板显示
}
// 创建第一个画布
FlowEdit.CreateCanvas("Default", 1920, 1080);
}
}

View File

@@ -1,5 +1,6 @@
using Serein.Library;
using Serein.NodeFlow.Tool;
using System.Globalization;
using System.Reflection;
namespace Serein.NodeFlow.Model.Library
@@ -229,14 +230,17 @@ namespace Serein.NodeFlow.Model.Library
public FlowLibraryInfo ToInfo()
{
var assemblyName = Assembly.GetName().Name;
var mdInfos = MethodDetailss.Values.Select(x => x.ToInfo()).ToList();
mdInfos.Sort((a, b) => string.Compare(a.MethodName, b.MethodName, StringComparison.OrdinalIgnoreCase));
var mdInfos = MethodDetailss.Values.Select(x => x.ToInfo())
.OrderBy(d => d.AssemblyName)
.ThenBy(s => s.MethodAnotherName, StringComparer.Create(CultureInfo.GetCultureInfo("zh-cn"), true))
.ToList();
return new FlowLibraryInfo
{
AssemblyName = assemblyName,
FileName = FullName,
FilePath = FilePath,
MethodInfos = mdInfos.ToList(),
MethodInfos = mdInfos,
};
}

View File

@@ -14,6 +14,11 @@ namespace Serein.NodeFlow.Services
/// </summary>
public class FlowLibraryService
{
/// <summary>
/// 是否加载过基础依赖
/// </summary>
public bool IsLoadedBaseLibrary { get; private set; } = false;
/// <summary>
/// 构造函数,初始化流程依赖
/// </summary>
@@ -60,7 +65,7 @@ namespace Serein.NodeFlow.Services
/// </summary>
public FlowLibraryInfo LoadBaseLibrary()
{
Assembly baseAssmbly = typeof(FlowBaseLibrary).Assembly;
var baseAssmbly = typeof(FlowBaseLibrary).Assembly;
var flowLibrary = new FlowLibraryCache(baseAssmbly);
flowLibrary.LoadFlowMethod();
var assemblyName = baseAssmbly.GetName().Name;
@@ -69,7 +74,9 @@ namespace Serein.NodeFlow.Services
throw new Exception($"程序集\"{baseAssmbly}\"返回 Name 为 null");
}
_flowLibraryCaches.TryAdd(assemblyName, flowLibrary);
return flowLibrary.ToInfo();
var infos = flowLibrary.ToInfo();
IsLoadedBaseLibrary = true;
return infos;
}
/// <summary>

View File

@@ -332,7 +332,7 @@ public static class NodeMethodDetailsHelper
{
isExplicitData = nodeParmsAttribute.IsExplicit; // 设置是否是显式参数
}
if (string.IsNullOrEmpty(nodeParmsAttribute.Name))
if (!string.IsNullOrEmpty(nodeParmsAttribute.Name))
{
description = nodeParmsAttribute.Name; // 设置显示的名称
}