using Serein.Library; using Serein.NodeFlow.Tool; using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Text; namespace Serein.NodeFlow { /// /// /// public class FlowLibrary { private readonly Assembly assembly; private readonly Action actionOfUnloadAssmbly; private string _assemblyFilePath; public FlowLibrary(string assemblyFilePath, Assembly assembly, Action actionOfUnloadAssmbly) { this._assemblyFilePath = assemblyFilePath; this.assembly = assembly; this.actionOfUnloadAssmbly = actionOfUnloadAssmbly; LoadAssembly(assembly); } public string FullName => assembly.GetName().FullName; public string Version => assembly.GetName().Version.ToString(); /// /// 加载程序集时创建的方法描述 /// public ConcurrentDictionary MethodDetailss { get; } = new ConcurrentDictionary(); /// /// 管理通过Emit动态构建的委托 /// public ConcurrentDictionary DelegateDetailss { get; } = new ConcurrentDictionary(); /// /// 记录不同的注册时机需要自动创建全局唯一实例的类型信息 /// public ConcurrentDictionary> RegisterTypes { get; } = new ConcurrentDictionary>(); /// /// 卸载当前程序集以及附带的所有信息 /// public void Upload() { actionOfUnloadAssmbly?.Invoke(); } public NodeLibraryInfo ToInfo() { return new NodeLibraryInfo { AssemblyName = FullName, FileName = Path.GetFileName(_assemblyFilePath), FilePath = _assemblyFilePath, }; } //public void LoadAssmely(Assembly assembly) //{ // (var registerTypes, var mdlist) = LoadAssembly2(assembly); // if (mdlist.Count > 0) // { // var nodeLibraryInfo = new NodeLibraryInfo // { // //Assembly = assembly, // AssemblyName = assembly.FullName, // FileName = Path.GetFileName(_assemblyFilePath), // FilePath = _assemblyFilePath, // }; // //LibraryInfos.TryAdd(nodeLibraryInfo.AssemblyName, nodeLibraryInfo); // MethodDetailss.TryAdd(nodeLibraryInfo.AssemblyName, mdlist); // foreach (var md in mdlist) // { // MethodDetailss.TryAdd(md.MethodName, md); // } // foreach (var kv in registerTypes) // { // if (!RegisterTypes.TryGetValue(kv.Key, out var types)) // { // types = new List(); // RegisterTypes.TryAdd(kv.Key, types); // } // types.AddRange(kv.Value); // } // var mdInfos = mdlist.Select(md => md.ToInfo()).ToList(); // 转换成方法信息 // } //} /// /// 动态加载程序集 /// /// 程序集本身 /// private bool LoadAssembly(Assembly assembly) { #region 检查入参 // 加载DLL,创建 MethodDetails、实例作用对象、委托方法 var assemblyName = assembly.GetName().Name; if (string.IsNullOrEmpty(assemblyName)) // 防止动态程序集没有定义程序集名称 { return false; } List types = assembly.GetTypes().ToList(); // 获取程序集中的所有类型 if (types.Count < 0) // 防止动态程序集中没有类型信息? { return false; } #endregion try { #region 获取 DynamicFlow 特性的流程控制器,如果没有退出 // Type : 具有 DynamicFlowAttribute 标记的类型 // string : 类型元数据 DynamicFlowAttribute 特性中的 Name 属性 (用于生成方法描述时,添加在方法别名中提高可读性) List<(Type Type, string Name)> scanTypes = new List<(Type Type, string Name)>(); // (Type, string) // Type : 具有 DynamicFlowAttribute 标记的类型 // string : 类型元数据 DynamicFlowAttribute 特性中的 Name 属性 foreach (var type in types) { if (type.GetCustomAttribute() is DynamicFlowAttribute dynamicFlowAttribute && dynamicFlowAttribute.Scan == true) { scanTypes.Add((type, dynamicFlowAttribute.Name)); } } if (scanTypes.Count == 0) { // 类型没有流程控制器 return false; } #endregion #region 创建对应的方法元数据 // 从 scanTypes.Type 创建的方法信息 // Md : 方法描述 // Dd :方法对应的Emit委托 List<(MethodDetails Md, DelegateDetails Dd)> detailss = new List<(MethodDetails Md, DelegateDetails Dd)>(); // 遍历扫描的类型 foreach ((var type, var flowName) in scanTypes) { var methodInfos = NodeMethodDetailsHelper.GetMethodsToProcess(type); foreach (var methodInfo in methodInfos) // 遍历流程控制器类型中的方法信息 { // 尝试创建 if (!NodeMethodDetailsHelper.TryCreateDetails(type, methodInfo, assemblyName, out var md, out var dd)) // 返回的描述 { Console.WriteLine($"无法加载方法信息:{assemblyName}-{type}-{methodInfo}"); continue; } md.MethodAnotherName = flowName + md.MethodAnotherName; // 方法别名 detailss.Add((md, dd)); } } #endregion #region 检查是否成功加载,如果成功,则真正写入到缓存的集合中 if(detailss.Count == 0) { return false; } #region 加载成功,缓存所有方法、委托的信息 foreach((var md,var dd) in detailss) { MethodDetailss.TryAdd(md.MethodName, md); DelegateDetailss.TryAdd(md.MethodName, dd); } #endregion #region 加载成功,开始获取并记录所有需要自动实例化的类型(在流程启动时) foreach (Type type in types) { if (type.GetCustomAttribute() is AutoRegisterAttribute attribute) { if (!RegisterTypes.TryGetValue(attribute.Class, out var valus)) { valus = new List(); RegisterTypes.TryAdd(attribute.Class, valus); } valus.Add(type); } } #endregion #endregion return true; } catch (Exception ex) { Console.WriteLine(ex.ToString()); return false; } } } }