mirror of
https://gitee.com/langsisi_admin/serein-flow
synced 2026-05-03 22:01:27 +08:00
准备修改运行环境中类库的依赖结构
This commit is contained in:
@@ -138,15 +138,15 @@ namespace Serein.Library.Api
|
|||||||
|
|
||||||
public class LoadDllEventArgs : FlowEventArgs
|
public class LoadDllEventArgs : FlowEventArgs
|
||||||
{
|
{
|
||||||
public LoadDllEventArgs(NodeLibrary nodeLibrary, List<MethodDetailsInfo> MethodDetailss)
|
public LoadDllEventArgs(NodeLibraryInfo nodeLibraryInfo, List<MethodDetailsInfo> MethodDetailss)
|
||||||
{
|
{
|
||||||
this.NodeLibrary = nodeLibrary;
|
this.NodeLibraryInfo = nodeLibraryInfo;
|
||||||
this.MethodDetailss = MethodDetailss;
|
this.MethodDetailss = MethodDetailss;
|
||||||
}
|
}
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 已加载了的程序集
|
/// 已加载了的程序集
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public NodeLibrary NodeLibrary { get; protected set; }
|
public NodeLibraryInfo NodeLibraryInfo { get; protected set; }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// dll文件中有效的流程方法描述
|
/// dll文件中有效的流程方法描述
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -676,8 +676,8 @@ namespace Serein.Library.Api
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 移除DLL
|
/// 移除DLL
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="assemblyFullName">程序集的名称</param>
|
/// <param name="assemblyName">程序集的名称</param>
|
||||||
bool RemoteDll(string assemblyFullName);
|
bool RemoteDll(string assemblyName);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 清理加载的DLL(待更改)
|
/// 清理加载的DLL(待更改)
|
||||||
|
|||||||
@@ -1,34 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Reflection;
|
|
||||||
using System.Text;
|
|
||||||
|
|
||||||
namespace Serein.Library
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 节点DLL依赖类,如果一个项目中引入了多个DLL,需要放置在同一个文件夹中
|
|
||||||
/// </summary>
|
|
||||||
public class NodeLibrary
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 文件名
|
|
||||||
/// </summary>
|
|
||||||
public string FileName { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 路径
|
|
||||||
/// </summary>
|
|
||||||
public string FilePath { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 依赖类的名称
|
|
||||||
/// </summary>
|
|
||||||
public string FullName{ get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 对应的程序集
|
|
||||||
/// </summary>
|
|
||||||
public Assembly Assembly { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
108
Library/Entity/NodeLibraryInfo.cs
Normal file
108
Library/Entity/NodeLibraryInfo.cs
Normal file
@@ -0,0 +1,108 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Concurrent;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace Serein.Library
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 节点DLL依赖类,如果一个项目中引入了多个DLL,需要放置在同一个文件夹中
|
||||||
|
/// </summary>
|
||||||
|
public class NodeLibraryInfo
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 文件名
|
||||||
|
/// </summary>
|
||||||
|
public string FileName { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 路径
|
||||||
|
/// </summary>
|
||||||
|
public string FilePath { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 所属的程序集名称
|
||||||
|
/// </summary>
|
||||||
|
public string AssemblyName{ get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
public class FlowLibrary
|
||||||
|
{
|
||||||
|
public FlowLibrary(string assemblyName,
|
||||||
|
Action actionOfUnloadAssmbly)
|
||||||
|
{
|
||||||
|
this.AssemblyName = assemblyName;
|
||||||
|
this.actionOfUnloadAssmbly = actionOfUnloadAssmbly;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string AssemblyName { get; }
|
||||||
|
|
||||||
|
//public string AssemblyVersion { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 加载程序集时创建的方法描述
|
||||||
|
/// </summary>
|
||||||
|
public ConcurrentDictionary<string, MethodDetails> MethodDetailss { get; } = new ConcurrentDictionary<string, MethodDetails>();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 管理通过Emit动态构建的委托
|
||||||
|
/// </summary>
|
||||||
|
public ConcurrentDictionary<string, DelegateDetails> DelegateDetailss { get; } = new ConcurrentDictionary<string, DelegateDetails>();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 记录不同的注册时机需要自动创建全局唯一实例的类型信息
|
||||||
|
/// </summary>
|
||||||
|
public ConcurrentDictionary<RegisterSequence, Type[]> RegisterTypes { get; } = new ConcurrentDictionary<RegisterSequence, Type[]>();
|
||||||
|
|
||||||
|
|
||||||
|
private readonly Action actionOfUnloadAssmbly;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 卸载当前程序集以及附带的所有信息
|
||||||
|
/// </summary>
|
||||||
|
public void Upload()
|
||||||
|
{
|
||||||
|
actionOfUnloadAssmbly?.Invoke();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 通过方法名称获取对应的Emit委托(元数据),用于动态调用节点对应的方法
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="methodName">方法名称</param>
|
||||||
|
/// <param name="dd">Emit委托</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public bool GetDelegateDetails(string methodName, out DelegateDetails dd)
|
||||||
|
{
|
||||||
|
return DelegateDetailss.TryGetValue(methodName, out dd);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 通过方法名称获取对应的方法描述(元数据),用于创建节点时,节点实例需要的方法描述
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="methodName">方法名称</param>
|
||||||
|
/// <param name="md">方法描述</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public bool GetMethodDetails(string methodName, out MethodDetails md)
|
||||||
|
{
|
||||||
|
return MethodDetailss.TryGetValue(methodName, out md);
|
||||||
|
}
|
||||||
|
|
||||||
|
public NodeLibraryInfo ToInfo()
|
||||||
|
{
|
||||||
|
return new NodeLibraryInfo
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -129,7 +129,7 @@ namespace Serein.Library
|
|||||||
&& index < ParameterDetailss.Length) // 防止下标越界
|
&& index < ParameterDetailss.Length) // 防止下标越界
|
||||||
{
|
{
|
||||||
ParameterDetailss[index] = null; // 释放对象引用
|
ParameterDetailss[index] = null; // 释放对象引用
|
||||||
var tmp = ArrayHelper.RemoteToArray(ParameterDetailss, index); // 新增;
|
var tmp = ArrayHelper.RemoteToArray<ParameterDetails>(ParameterDetailss, index); // 新增;
|
||||||
UpdateParamIndex(ref tmp);
|
UpdateParamIndex(ref tmp);
|
||||||
ParameterDetailss = tmp; // 新增
|
ParameterDetailss = tmp; // 新增
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -12,9 +12,9 @@ namespace Serein.Library
|
|||||||
public class MethodDetailsInfo
|
public class MethodDetailsInfo
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 属于哪个DLL文件
|
/// 属于哪个程序集
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string LibraryName { get; set; }
|
public string AssemblyName { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 方法名称
|
/// 方法名称
|
||||||
|
|||||||
@@ -33,9 +33,9 @@ namespace Serein.Library
|
|||||||
public class LibraryMds
|
public class LibraryMds
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 程序集FullName
|
/// 程序集名称
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string LibraryName { get; set; }
|
public string AssemblyName { get; set; }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 相关的方法详情
|
/// 相关的方法详情
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -2,8 +2,8 @@
|
|||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<Version>1.0.19</Version>
|
<Version>1.0.19</Version>
|
||||||
<TargetFrameworks>net8.0;net462</TargetFrameworks>
|
|
||||||
<!--<TargetFrameworks>net8.0</TargetFrameworks>-->
|
<!--<TargetFrameworks>net8.0</TargetFrameworks>-->
|
||||||
|
<TargetFrameworks>net8.0;net462</TargetFrameworks>
|
||||||
<BaseOutputPath>D:\Project\C#\DynamicControl\SereinFlow\.Output</BaseOutputPath>
|
<BaseOutputPath>D:\Project\C#\DynamicControl\SereinFlow\.Output</BaseOutputPath>
|
||||||
<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
|
<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
|
||||||
<Title>SereinFow</Title>
|
<Title>SereinFow</Title>
|
||||||
@@ -37,8 +37,6 @@
|
|||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|
||||||
<ProjectReference Include="..\Serein.Library.MyGenerator\Serein.Library.NodeGenerator.csproj" OutputItemType="Analyzer" />
|
|
||||||
|
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||||
<PackageReference Include="System.Reactive" Version="6.0.1" />
|
<PackageReference Include="System.Reactive" Version="6.0.1" />
|
||||||
<PackageReference Include="System.Threading.Channels" Version="8.0.0" />
|
<PackageReference Include="System.Threading.Channels" Version="8.0.0" />
|
||||||
@@ -60,4 +58,8 @@
|
|||||||
</None>
|
</None>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\Serein.Library.MyGenerator\Serein.Library.NodeGenerator.csproj " OutputItemType="Analyzer" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@@ -223,24 +223,45 @@ namespace Serein.NodeFlow.Env
|
|||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region 私有变量
|
#region 私有变量
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 通过程序集名称管理动态加载的程序集,用于节点创建提供方法描述,流程运行时提供Emit委托
|
||||||
|
/// </summary>
|
||||||
|
public ConcurrentDictionary<string, FlowLibrary> FlowLibrarys { get; } = [];
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Library 与 MethodDetailss的依赖关系
|
/// Library 与 MethodDetailss的依赖关系
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public ConcurrentDictionary<NodeLibrary, List<MethodDetails>> MethodDetailsOfLibrarys { get; } = [];
|
public ConcurrentDictionary<NodeLibraryInfo, List<MethodDetails>> MethodDetailsOfLibraryInfos { get; } = [];
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 存储已加载的程序集
|
/// <para>存储已加载的程序集</para>
|
||||||
|
/// <para>Key:程序集的FullName </para>
|
||||||
|
/// <para>Value:构造的方法信息</para>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public ConcurrentDictionary<string, NodeLibrary> Librarys { get; } = [];
|
public ConcurrentDictionary<string, NodeLibraryInfo> LibraryInfos { get; } = [];
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 存储已加载的方法信息。描述所有DLL中NodeAction特性的方法的原始副本
|
/// <para>存储已加载的方法信息。描述所有DLL中NodeAction特性的方法的原始副本</para>
|
||||||
|
/// <para>Key:反射时获取的MethodInfo.MehtodName</para>
|
||||||
|
/// <para>Value:构造的方法信息</para>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public ConcurrentDictionary<string, MethodDetails> MethodDetailss { get; } = [];
|
public ConcurrentDictionary<string, MethodDetails> MethodDetailss { get; } = [];
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 从dll中加载的类的注册类型
|
||||||
|
/// </summary>
|
||||||
|
private Dictionary<RegisterSequence, List<Type>> AutoRegisterTypes { get; } = [];
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 容器管理
|
/// 存放所有通过Emit加载的委托
|
||||||
|
/// md.Methodname - delegate
|
||||||
|
/// </summary>
|
||||||
|
private ConcurrentDictionary<string, DelegateDetails> MethodDelegates { get; } = [];
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// IOC对象容器管理
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private readonly SereinIOC sereinIOC;
|
private readonly SereinIOC sereinIOC;
|
||||||
|
|
||||||
@@ -255,18 +276,7 @@ namespace Serein.NodeFlow.Env
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private List<SingleFlipflopNode> FlipflopNodes { get; } = [];
|
private List<SingleFlipflopNode> FlipflopNodes { get; } = [];
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 从dll中加载的类的注册类型
|
|
||||||
/// </summary>
|
|
||||||
private Dictionary<RegisterSequence, List<Type>> AutoRegisterTypes { get; } = [];
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 存放委托
|
|
||||||
///
|
|
||||||
/// md.Methodname - delegate
|
|
||||||
/// </summary>
|
|
||||||
|
|
||||||
private ConcurrentDictionary<string, DelegateDetails> MethodDelegates { get; } = [];
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 起始节点私有属性
|
/// 起始节点私有属性
|
||||||
@@ -470,28 +480,28 @@ namespace Serein.NodeFlow.Env
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public async Task<FlowEnvInfo> GetEnvInfoAsync()
|
public async Task<FlowEnvInfo> GetEnvInfoAsync()
|
||||||
{
|
{
|
||||||
Dictionary<NodeLibrary, List<MethodDetailsInfo>> LibraryMds = [];
|
Dictionary<NodeLibraryInfo, List<MethodDetailsInfo>> MdsOfLibraryInfos = [];
|
||||||
|
|
||||||
foreach (var mdskv in MethodDetailsOfLibrarys)
|
foreach (var mdskv in MethodDetailsOfLibraryInfos)
|
||||||
{
|
{
|
||||||
var library = mdskv.Key;
|
var library = mdskv.Key;
|
||||||
var mds = mdskv.Value;
|
var mds = mdskv.Value;
|
||||||
foreach (var md in mds)
|
foreach (var md in mds)
|
||||||
{
|
{
|
||||||
if (!LibraryMds.TryGetValue(library, out var t_mds))
|
if (!MdsOfLibraryInfos.TryGetValue(library, out var t_mds))
|
||||||
{
|
{
|
||||||
t_mds = new List<MethodDetailsInfo>();
|
t_mds = new List<MethodDetailsInfo>();
|
||||||
LibraryMds[library] = t_mds;
|
MdsOfLibraryInfos[library] = t_mds;
|
||||||
}
|
}
|
||||||
var mdInfo = md.ToInfo();
|
var mdInfo = md.ToInfo();
|
||||||
mdInfo.LibraryName = library.FullName;
|
mdInfo.AssemblyName = library.AssemblyName;
|
||||||
t_mds.Add(mdInfo);
|
t_mds.Add(mdInfo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LibraryMds[] libraryMdss = LibraryMds.Select(kv => new LibraryMds
|
LibraryMds[] libraryMdss = MdsOfLibraryInfos.Select(kv => new LibraryMds
|
||||||
{
|
{
|
||||||
LibraryName = kv.Key.FullName,
|
AssemblyName = kv.Key.AssemblyName,
|
||||||
Mds = kv.Value.ToArray()
|
Mds = kv.Value.ToArray()
|
||||||
}).ToArray();
|
}).ToArray();
|
||||||
var project = await GetProjectInfoAsync();
|
var project = await GetProjectInfoAsync();
|
||||||
@@ -716,7 +726,7 @@ namespace Serein.NodeFlow.Env
|
|||||||
{
|
{
|
||||||
var projectData = new SereinProjectData()
|
var projectData = new SereinProjectData()
|
||||||
{
|
{
|
||||||
Librarys = Librarys.Values.Select(lib => lib.ToLibrary()).ToArray(),
|
Librarys = LibraryInfos.Values.Select(lib => lib.ToLibrary()).ToArray(),
|
||||||
Nodes = NodeModels.Values.Select(node => node.ToInfo()).Where(info => info is not null).ToArray(),
|
Nodes = NodeModels.Values.Select(node => node.ToInfo()).Where(info => info is not null).ToArray(),
|
||||||
StartNode = NodeModels.Values.FirstOrDefault(it => it.IsStart)?.Guid,
|
StartNode = NodeModels.Values.FirstOrDefault(it => it.IsStart)?.Guid,
|
||||||
};
|
};
|
||||||
@@ -738,11 +748,11 @@ namespace Serein.NodeFlow.Env
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 移除DLL
|
/// 移除DLL
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="assemblyFullName"></param>
|
/// <param name="assemblyName"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public bool RemoteDll(string assemblyFullName)
|
public bool RemoteDll(string assemblyName)
|
||||||
{
|
{
|
||||||
var library = Librarys.Values.FirstOrDefault(nl => assemblyFullName.Equals(nl.FullName));
|
var library = LibraryInfos.Values.FirstOrDefault(nl => assemblyName.Equals(nl.AssemblyName));
|
||||||
if (library is null)
|
if (library is null)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
@@ -761,7 +771,7 @@ namespace Serein.NodeFlow.Env
|
|||||||
return true; // 当前无节点,可以直接删除
|
return true; // 当前无节点,可以直接删除
|
||||||
}
|
}
|
||||||
|
|
||||||
if (MethodDetailsOfLibrarys.TryGetValue(library, out var mds)) // 存在方法
|
if (MethodDetailsOfLibraryInfos.TryGetValue(library, out var mds)) // 存在方法
|
||||||
{
|
{
|
||||||
foreach (var md in mds)
|
foreach (var md in mds)
|
||||||
{
|
{
|
||||||
@@ -778,7 +788,7 @@ namespace Serein.NodeFlow.Env
|
|||||||
{
|
{
|
||||||
MethodDetailss.TryRemove(md.MethodName, out _);
|
MethodDetailss.TryRemove(md.MethodName, out _);
|
||||||
}
|
}
|
||||||
MethodDetailsOfLibrarys.TryRemove(library, out _);
|
MethodDetailsOfLibraryInfos.TryRemove(library, out _);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -1395,35 +1405,56 @@ namespace Serein.NodeFlow.Env
|
|||||||
/// <param name="dllPath"></param>
|
/// <param name="dllPath"></param>
|
||||||
private void LoadDllNodeInfo(string dllPath)
|
private void LoadDllNodeInfo(string dllPath)
|
||||||
{
|
{
|
||||||
(var nodeLibrary, var registerTypes, var mdlist) = LoadAssembly(dllPath);
|
|
||||||
if (nodeLibrary is not null && mdlist.Count > 0)
|
var fileName = Path.GetFileName(dllPath);
|
||||||
|
AssemblyLoadContext flowAlc = new AssemblyLoadContext(fileName, true);
|
||||||
|
flowAlc.LoadFromAssemblyPath(dllPath); // 加载指定路径的程序集
|
||||||
|
|
||||||
|
foreach(var assemblt in flowAlc.Assemblies)
|
||||||
{
|
{
|
||||||
Librarys.TryAdd(nodeLibrary.FullName, nodeLibrary);
|
(var registerTypes, var mdlist) = LoadAssembly(assemblt);
|
||||||
MethodDetailsOfLibrarys.TryAdd(nodeLibrary, mdlist);
|
if (mdlist.Count > 0)
|
||||||
|
|
||||||
foreach (var md in mdlist)
|
|
||||||
{
|
{
|
||||||
MethodDetailss.TryAdd(md.MethodName, md);
|
var nodeLibraryInfo = new NodeLibraryInfo
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var kv in registerTypes)
|
|
||||||
{
|
|
||||||
if (!AutoRegisterTypes.TryGetValue(kv.Key, out var types))
|
|
||||||
{
|
{
|
||||||
types = new List<Type>();
|
//Assembly = assembly,
|
||||||
AutoRegisterTypes.Add(kv.Key, types);
|
AssemblyName = assemblt.FullName,
|
||||||
|
FileName = Path.GetFileName(dllPath),
|
||||||
|
FilePath = dllPath,
|
||||||
|
};
|
||||||
|
|
||||||
|
LibraryInfos.TryAdd(nodeLibraryInfo.AssemblyName, nodeLibraryInfo);
|
||||||
|
MethodDetailsOfLibraryInfos.TryAdd(nodeLibraryInfo, mdlist);
|
||||||
|
|
||||||
|
foreach (var md in mdlist)
|
||||||
|
{
|
||||||
|
MethodDetailss.TryAdd(md.MethodName, md);
|
||||||
}
|
}
|
||||||
types.AddRange(kv.Value);
|
|
||||||
}
|
|
||||||
var mdInfos = mdlist.Select(md => md.ToInfo()).ToList(); // 转换成方法信息
|
|
||||||
|
|
||||||
if (OperatingSystem.IsWindows())
|
foreach (var kv in registerTypes)
|
||||||
{
|
{
|
||||||
UIContextOperation?.Invoke(() => OnDllLoad?.Invoke(new LoadDllEventArgs(nodeLibrary, mdInfos))); // 通知UI创建dll面板显示
|
if (!AutoRegisterTypes.TryGetValue(kv.Key, out var types))
|
||||||
|
{
|
||||||
|
types = new List<Type>();
|
||||||
|
AutoRegisterTypes.Add(kv.Key, types);
|
||||||
|
}
|
||||||
|
types.AddRange(kv.Value);
|
||||||
|
}
|
||||||
|
var mdInfos = mdlist.Select(md => md.ToInfo()).ToList(); // 转换成方法信息
|
||||||
|
|
||||||
|
if (OperatingSystem.IsWindows())
|
||||||
|
{
|
||||||
|
UIContextOperation?.Invoke(() => OnDllLoad?.Invoke(new LoadDllEventArgs(nodeLibraryInfo, mdInfos))); // 通知UI创建dll面板显示
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -1477,18 +1508,17 @@ namespace Serein.NodeFlow.Env
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
///
|
/// 动态加载程序集
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="dllPath"></param>
|
/// <param name="assembly">程序集本身</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
private (NodeLibrary?, Dictionary<RegisterSequence, List<Type>>, List<MethodDetails>) LoadAssembly(string dllPath)
|
private (Dictionary<RegisterSequence, List<Type>>, List<MethodDetails>) LoadAssembly(Assembly assembly)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
//FlowLibraryLoader flowLibraryLoader = new FlowLibraryLoader(dllPath);
|
|
||||||
//Assembly assembly = flowLibraryLoader.LoadFromAssemblyPath(dllPath);
|
|
||||||
Assembly assembly = Assembly.LoadFrom(dllPath); // 加载DLL文件
|
|
||||||
List<Type> types = assembly.GetTypes().ToList(); // 获取程序集中的所有类型
|
List<Type> types = assembly.GetTypes().ToList(); // 获取程序集中的所有类型
|
||||||
|
|
||||||
|
#region 获取所有需要注册的类型
|
||||||
Dictionary<RegisterSequence, List<Type>> autoRegisterTypes = new Dictionary<RegisterSequence, List<Type>>();
|
Dictionary<RegisterSequence, List<Type>> autoRegisterTypes = new Dictionary<RegisterSequence, List<Type>>();
|
||||||
foreach (Type type in types)
|
foreach (Type type in types)
|
||||||
{
|
{
|
||||||
@@ -1504,25 +1534,29 @@ namespace Serein.NodeFlow.Env
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
#region 获取 DynamicFlow 特性的流程控制器,如果没有返回空
|
||||||
List<(Type, string)> scanTypes = types.Select(t =>
|
List<(Type, string)> scanTypes = types.Select(t =>
|
||||||
{
|
{
|
||||||
if (t.GetCustomAttribute<DynamicFlowAttribute>() is DynamicFlowAttribute dynamicFlowAttribute
|
if (t.GetCustomAttribute<DynamicFlowAttribute>() is DynamicFlowAttribute dynamicFlowAttribute
|
||||||
&& dynamicFlowAttribute.Scan == true)
|
&& dynamicFlowAttribute.Scan == true)
|
||||||
{
|
{
|
||||||
return (t, dynamicFlowAttribute.Name);
|
return (t, dynamicFlowAttribute.Name);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return (null, null);
|
return (null, null);
|
||||||
}
|
}
|
||||||
}).Where(it => it.t is not null).ToList();
|
}).Where(it => it.t is not null).ToList();
|
||||||
if (scanTypes.Count == 0)
|
if (scanTypes.Count == 0)
|
||||||
{
|
{
|
||||||
return (null, [], []);
|
return ([], []);
|
||||||
}
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region 创建对应的方法元数据
|
||||||
List<MethodDetails> methodDetails = new List<MethodDetails>();
|
List<MethodDetails> methodDetails = new List<MethodDetails>();
|
||||||
// 遍历扫描的类型
|
// 遍历扫描的类型
|
||||||
foreach ((var type, var flowName) in scanTypes)
|
foreach ((var type, var flowName) in scanTypes)
|
||||||
@@ -1553,22 +1587,15 @@ namespace Serein.NodeFlow.Env
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
var nodeLibrary = new NodeLibrary
|
|
||||||
{
|
return (autoRegisterTypes, methodDetails);
|
||||||
FullName = assembly.GetName().FullName,
|
|
||||||
Assembly = assembly,
|
|
||||||
FileName = Path.GetFileName(dllPath),
|
|
||||||
FilePath = dllPath,
|
|
||||||
};
|
|
||||||
//LoadedAssemblies.Add(assembly); // 将加载的程序集添加到列表中
|
|
||||||
//LoadedAssemblyPaths.Add(dllPath); // 记录加载的DLL路径
|
|
||||||
return (nodeLibrary, autoRegisterTypes, methodDetails);
|
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Console.WriteLine(ex.ToString());
|
Console.WriteLine(ex.ToString());
|
||||||
return (null, [], []);
|
return ([], []);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -307,9 +307,9 @@ namespace Serein.NodeFlow.Env
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public bool RemoteDll(string assemblyFullName)
|
public bool RemoteDll(string assemblyName)
|
||||||
{
|
{
|
||||||
return currentFlowEnvironment.RemoteDll(assemblyFullName);
|
return currentFlowEnvironment.RemoteDll(assemblyName);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<bool> RemoveConnectInvokeAsync(string fromNodeGuid, string toNodeGuid, ConnectionInvokeType connectionType)
|
public async Task<bool> RemoveConnectInvokeAsync(string fromNodeGuid, string toNodeGuid, ConnectionInvokeType connectionType)
|
||||||
|
|||||||
@@ -87,16 +87,17 @@ namespace Serein.NodeFlow.Env
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 程序集封装依赖
|
/// 程序集封装依赖
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="library"></param>
|
/// <param name="libraryInfo"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public static Library.Library ToLibrary(this Library.NodeLibrary library)
|
public static Library.Library ToLibrary(this Library.NodeLibraryInfo libraryInfo)
|
||||||
{
|
{
|
||||||
var tmp = library.Assembly.ManifestModule.Name;
|
//var tmp = library.Assembly.ManifestModule.Name;
|
||||||
return new Library.Library
|
return new Library.Library
|
||||||
{
|
{
|
||||||
AssemblyName = library.Assembly.GetName().Name,
|
AssemblyName = libraryInfo.AssemblyName,
|
||||||
FileName = library.FileName,
|
//AssemblyName = library.Assembly.GetName().Name,
|
||||||
FilePath = library.FilePath,
|
FileName = libraryInfo.FileName,
|
||||||
|
FilePath = libraryInfo.FilePath,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -112,6 +112,11 @@ namespace Serein.NodeFlow.Env
|
|||||||
return prjectInfo;
|
return prjectInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 远程环境下加载项目
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="flowEnvInfo"></param>
|
||||||
|
/// <param name="filePath"></param>
|
||||||
public void LoadProject(FlowEnvInfo flowEnvInfo, string filePath)
|
public void LoadProject(FlowEnvInfo flowEnvInfo, string filePath)
|
||||||
{
|
{
|
||||||
Console.WriteLine("加载远程环境");
|
Console.WriteLine("加载远程环境");
|
||||||
@@ -120,13 +125,13 @@ namespace Serein.NodeFlow.Env
|
|||||||
var libmds = flowEnvInfo.LibraryMds;
|
var libmds = flowEnvInfo.LibraryMds;
|
||||||
foreach (var lib in libmds)
|
foreach (var lib in libmds)
|
||||||
{
|
{
|
||||||
NodeLibrary nodeLibrary = new NodeLibrary
|
NodeLibraryInfo nodeLibraryInfo = new NodeLibraryInfo
|
||||||
{
|
{
|
||||||
FullName = lib.LibraryName,
|
AssemblyName = lib.AssemblyName,
|
||||||
FilePath = "Remote",
|
FilePath = "Remote",
|
||||||
};
|
};
|
||||||
var mdInfos = lib.Mds.ToList();
|
var mdInfos = lib.Mds.ToList();
|
||||||
UIContextOperation?.Invoke(() => OnDllLoad?.Invoke(new LoadDllEventArgs(nodeLibrary, mdInfos))); // 通知UI创建dll面板显示
|
UIContextOperation?.Invoke(() => OnDllLoad?.Invoke(new LoadDllEventArgs(nodeLibraryInfo, mdInfos))); // 通知UI创建dll面板显示
|
||||||
foreach (var mdInfo in mdInfos)
|
foreach (var mdInfo in mdInfos)
|
||||||
{
|
{
|
||||||
MethodDetailss.TryAdd(mdInfo.MethodName, new MethodDetails(mdInfo)); // 从DLL读取时生成元数据
|
MethodDetailss.TryAdd(mdInfo.MethodName, new MethodDetails(mdInfo)); // 从DLL读取时生成元数据
|
||||||
@@ -397,7 +402,7 @@ namespace Serein.NodeFlow.Env
|
|||||||
Console.WriteLine("远程环境尚未实现的接口:LoadDll");
|
Console.WriteLine("远程环境尚未实现的接口:LoadDll");
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool RemoteDll(string assemblyFullName)
|
public bool RemoteDll(string assemblyName)
|
||||||
{
|
{
|
||||||
// 尝试移除远程环境中的加载了的依赖
|
// 尝试移除远程环境中的加载了的依赖
|
||||||
Console.WriteLine("远程环境尚未实现的接口:RemoteDll");
|
Console.WriteLine("远程环境尚未实现的接口:RemoteDll");
|
||||||
|
|||||||
@@ -15,6 +15,8 @@ namespace Serein.NodeFlow.Tool
|
|||||||
{
|
{
|
||||||
private Assembly _pluginAssembly;
|
private Assembly _pluginAssembly;
|
||||||
|
|
||||||
|
public string FullName => _pluginAssembly.FullName;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 加载程序集
|
/// 加载程序集
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -35,6 +37,12 @@ namespace Serein.NodeFlow.Tool
|
|||||||
return null; // 保持默认加载行为
|
return null; // 保持默认加载行为
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public List<Type> LoadFlowTypes()
|
||||||
|
{
|
||||||
|
return _pluginAssembly.GetTypes().ToList();
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 是否对程序集的引用
|
/// 是否对程序集的引用
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ public static class NodeMethodDetailsHelper
|
|||||||
return type.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
|
return type.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
|
||||||
.Where(m => m.GetCustomAttribute<NodeActionAttribute>()?.Scan == true);
|
.Where(m => m.GetCustomAttribute<NodeActionAttribute>()?.Scan == true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 创建方法信息
|
/// 创建方法信息
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -250,22 +251,6 @@ public static class NodeMethodDetailsHelper
|
|||||||
IsParams = hasParams, // 判断是否为可变参数
|
IsParams = hasParams, // 判断是否为可变参数
|
||||||
};
|
};
|
||||||
|
|
||||||
//string explicitTypeName = GetExplicitTypeName(explicitParemType);
|
|
||||||
//var items = GetExplicitItems(explicitParemType, explicitTypeName);
|
|
||||||
//if ("Bool".Equals(explicitTypeName)) explicitTypeName = "Select"; // 布尔值 转为 可选类型
|
|
||||||
//return new ParameterDetails
|
|
||||||
//{
|
|
||||||
// IsExplicitData = isExplicitData, //attribute is null ? parameterInfo.HasDefaultValue : true,
|
|
||||||
// Index = index, // 索引
|
|
||||||
// ExplicitTypeName = explicitTypeName, // Select/Bool/Value
|
|
||||||
// ExplicitType = explicitParemType,// 显示的入参类型
|
|
||||||
// Convertor = func, // 转换器
|
|
||||||
// DataType = dataType, // 实际的入参类型
|
|
||||||
// Name = parameterInfo.Name,
|
|
||||||
// DataValue = parameterInfo.HasDefaultValue ? parameterInfo?.DefaultValue?.ToString() : "", // 如果存在默认值,则使用默认值
|
|
||||||
// Items = items.ToArray(), // 如果是枚举值入参,则获取枚举类型的字面量
|
|
||||||
// IsParams = hasParams, // 判断是否为可变参数
|
|
||||||
//};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -316,10 +316,10 @@ namespace Serein.Workbench
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private void FlowEnvironment_DllLoadEvent(LoadDllEventArgs eventArgs)
|
private void FlowEnvironment_DllLoadEvent(LoadDllEventArgs eventArgs)
|
||||||
{
|
{
|
||||||
NodeLibrary nodeLibrary = eventArgs.NodeLibrary;
|
NodeLibraryInfo nodeLibraryInfo = eventArgs.NodeLibraryInfo;
|
||||||
List<MethodDetailsInfo> methodDetailss = eventArgs.MethodDetailss;
|
List<MethodDetailsInfo> methodDetailss = eventArgs.MethodDetailss;
|
||||||
|
|
||||||
var dllControl = new DllControl(nodeLibrary);
|
var dllControl = new DllControl(nodeLibraryInfo);
|
||||||
|
|
||||||
foreach (var methodDetailsInfo in methodDetailss)
|
foreach (var methodDetailsInfo in methodDetailss)
|
||||||
{
|
{
|
||||||
@@ -341,7 +341,7 @@ namespace Serein.Workbench
|
|||||||
var menu = new ContextMenu();
|
var menu = new ContextMenu();
|
||||||
menu.Items.Add(CreateMenuItem("卸载", (s, e) =>
|
menu.Items.Add(CreateMenuItem("卸载", (s, e) =>
|
||||||
{
|
{
|
||||||
if (this.EnvDecorator.RemoteDll(nodeLibrary.FullName))
|
if (this.EnvDecorator.RemoteDll(nodeLibraryInfo.AssemblyName))
|
||||||
{
|
{
|
||||||
DllStackPanel.Children.Remove(dllControl);
|
DllStackPanel.Children.Remove(dllControl);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,17 +16,17 @@ namespace Serein.Workbench.Node.View
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public partial class DllControl : UserControl
|
public partial class DllControl : UserControl
|
||||||
{
|
{
|
||||||
private readonly NodeLibrary nodeLibrary;
|
private readonly NodeLibraryInfo nodeLibraryInfo;
|
||||||
|
|
||||||
public DllControl()
|
public DllControl()
|
||||||
{
|
{
|
||||||
Header = "DLL文件"; // 设置初始值
|
Header = "DLL文件"; // 设置初始值
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
}
|
}
|
||||||
public DllControl(NodeLibrary nodeLibrary)
|
public DllControl(NodeLibraryInfo nodeLibraryInfo)
|
||||||
{
|
{
|
||||||
this.nodeLibrary = nodeLibrary;
|
this.nodeLibraryInfo = nodeLibraryInfo;
|
||||||
Header = "DLL name : " + nodeLibrary.FullName;
|
Header = "DLL name : " + nodeLibraryInfo.AssemblyName;
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user