diff --git a/Library.Core/NodeFlow/DynamicContext.cs b/Library.Core/NodeFlow/DynamicContext.cs index 7c73a31..26c33b9 100644 --- a/Library.Core/NodeFlow/DynamicContext.cs +++ b/Library.Core/NodeFlow/DynamicContext.cs @@ -24,7 +24,7 @@ namespace Serein.Library.Core.NodeFlow { if (NodeRunCts == null) { - NodeRunCts = Env.IOC.GetOrRegisterInstantiate(); + NodeRunCts = Env.IOC.Get(); } // 使用局部变量,避免捕获外部的 `action` Action localAction = action; diff --git a/Library.Framework/NodeFlow/DynamicContext.cs b/Library.Framework/NodeFlow/DynamicContext.cs index a012f9d..eb057d0 100644 --- a/Library.Framework/NodeFlow/DynamicContext.cs +++ b/Library.Framework/NodeFlow/DynamicContext.cs @@ -27,7 +27,7 @@ namespace Serein.Library.Framework.NodeFlow { if(NodeRunCts == null) { - NodeRunCts = Env.IOC.GetOrRegisterInstantiate(); + NodeRunCts = Env.IOC.Get(); } // 使用局部变量,避免捕获外部的 `action` Action localAction = action; diff --git a/Library/Api/IFlowEnvironment.cs b/Library/Api/IFlowEnvironment.cs index f02f3be..3c4a647 100644 --- a/Library/Api/IFlowEnvironment.cs +++ b/Library/Api/IFlowEnvironment.cs @@ -24,7 +24,13 @@ namespace Serein.Library.Api /// /// 加载项目文件时成功加载了DLL文件 /// - public delegate void LoadDLLHandler(LoadDLLEventArgs eventArgs); + public delegate void LoadDllHandler(LoadDllEventArgs eventArgs); + + /// + /// 移除了加载的dll + /// + /// + public delegate void RemoteDllHandler(RemoteDllEventArgs eventArgs); /// /// 运行环境节点连接发生了改变 @@ -110,23 +116,30 @@ namespace Serein.Library.Api } } - public class LoadDLLEventArgs : FlowEventArgs + public class LoadDllEventArgs : FlowEventArgs { - public LoadDLLEventArgs(Assembly Assembly, List MethodDetailss) + public LoadDllEventArgs(NodeLibrary nodeLibrary, List MethodDetailss) { - this.Assembly = Assembly; + this.NodeLibrary = nodeLibrary; this.MethodDetailss = MethodDetailss; } /// /// 已加载了的程序集 /// - public Assembly Assembly { get; protected set; } + public NodeLibrary NodeLibrary { get; protected set; } /// /// dll文件中有效的流程方法描述 /// public List MethodDetailss { get; protected set; } } + public class RemoteDllEventArgs : FlowEventArgs + { + public RemoteDllEventArgs() + { + } + } + public class NodeConnectChangeEventArgs : FlowEventArgs { @@ -385,7 +398,7 @@ namespace Serein.Library.Api /// /// 加载Dll /// - event LoadDLLHandler OnDllLoad; + event LoadDllHandler OnDllLoad; /// /// 项目加载完成 @@ -455,6 +468,8 @@ namespace Serein.Library.Api bool TryGetMethodDetails(string methodName, out MethodDetails md); + bool TryGetDelegate(string methodName, out Delegate del); + //bool TryGetNodeData(string methodName, out NodeData node); #region 环境基础接口 @@ -475,6 +490,12 @@ namespace Serein.Library.Api /// /// void LoadDll(string dllPath); + /// + /// 移除DLL + /// + /// + bool RemoteDll(string assemblyFullName); + /// /// 清理加载的DLL(待更改) /// diff --git a/Library/Api/ISereinIoc.cs b/Library/Api/ISereinIoc.cs index 0953496..c1aaf32 100644 --- a/Library/Api/ISereinIoc.cs +++ b/Library/Api/ISereinIoc.cs @@ -30,20 +30,21 @@ namespace Serein.Library.Api /// /// ISereinIOC Register(params object[] parameters) where TImplementation : TService; - /// - /// 获取或创建并注入目标类型,会记录到IOC容器中。 - /// - T GetOrRegisterInstantiate(); - /// - /// 获取或创建并注入目标类型,会记录到IOC容器中。 - /// - object GetOrRegisterInstantiate(Type type); + ///// + ///// 获取或创建并注入目标类型,会记录到IOC容器中。 + ///// + //T GetOrRegisterInstantiate(); + ///// + ///// 获取或创建并注入目标类型,会记录到IOC容器中。 + ///// + //object GetOrRegisterInstantiate(Type type); /// /// 获取类型的实例 /// /// /// object Get(Type type); + T Get(); /// /// 获取指定名称的实例 @@ -64,8 +65,11 @@ namespace Serein.Library.Api /// /// 用于临时实例的创建,不注册到IOC容器中,依赖项注入失败时也不记录。 /// - object Instantiate(Type type, params object[] parameters); - + object Instantiate(Type type); + /// + /// 用于临时实例的创建,不注册到IOC容器中,依赖项注入失败时也不记录。 + /// + T Instantiate(); /// /// 实例化注册的类型,并注入依赖项 /// diff --git a/Library/Entity/MethodDetails.cs b/Library/Entity/MethodDetails.cs index 1cd15c0..a666065 100644 --- a/Library/Entity/MethodDetails.cs +++ b/Library/Entity/MethodDetails.cs @@ -22,7 +22,6 @@ namespace Serein.Library.Entity { ActingInstance = ActingInstance, ActingInstanceType = ActingInstanceType, - MethodDelegate = MethodDelegate, MethodDynamicType = MethodDynamicType, MethodGuid = Guid.NewGuid().ToString(), MethodTips = MethodTips, @@ -68,8 +67,7 @@ namespace Serein.Library.Entity /// /// 方法委托 /// - - public Delegate MethodDelegate { get; set; } + // public Delegate MethodDelegate { get; set; } /// /// 节点类型 diff --git a/Library/Entity/NodeLibrary.cs b/Library/Entity/NodeLibrary.cs new file mode 100644 index 0000000..439f6e9 --- /dev/null +++ b/Library/Entity/NodeLibrary.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Reflection; +using System.Text; + +namespace Serein.Library.Entity +{ + public class NodeLibrary + { + public string Path { get; set; } + public Assembly Assembly { get; set; } + } + +} diff --git a/Library/NodeAttribute.cs b/Library/NodeAttribute.cs index bd733cc..b8e9f9c 100644 --- a/Library/NodeAttribute.cs +++ b/Library/NodeAttribute.cs @@ -9,10 +9,10 @@ namespace Serein.Library.Attributes [AttributeUsage(AttributeTargets.Property)] public sealed class AutoInjectionAttribute : Attribute { - } + } /// - /// 表示该类自动注册 + /// 表示该类自动注册(单例模式) /// [AttributeUsage(AttributeTargets.Class)] public sealed class AutoRegisterAttribute : Attribute @@ -20,7 +20,7 @@ namespace Serein.Library.Attributes } /// - /// 用来判断一个类是否需要注册并构建实例(单例模式场景使用) + /// 用来判断一个类是否需要注册并构建节点 /// [AttributeUsage(AttributeTargets.Class)] public class DynamicFlowAttribute : Attribute diff --git a/Library/Utils/SereinIoc.cs b/Library/Utils/SereinIoc.cs index 15bf99f..02c64a8 100644 --- a/Library/Utils/SereinIoc.cs +++ b/Library/Utils/SereinIoc.cs @@ -8,6 +8,7 @@ using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Xml; +using System.Xml.Schema; namespace Serein.Library.Utils { @@ -43,10 +44,14 @@ namespace Serein.Library.Utils _unfinishedDependencies = new ConcurrentDictionary>(); } + /// + /// 绑定之前进行的默认绑定 + /// public void InitRegister() { - //_dependencies[typeof(ISereinIOC).FullName] = this; + _dependencies[typeof(ISereinIOC).FullName] = this; Register(); + //foreach (var type in _typeMappings.Values) //{ // Register(type); @@ -91,47 +96,47 @@ namespace Serein.Library.Utils /// /// 尝试从容器中获取对象,如果不存在目标类型的对象,则将类型信息登记到容器,并实例化注入依赖项。如果依然无法注册,则返回null。 /// - public T GetOrRegisterInstantiate() - { - return (T)GetOrRegisterInstantiate(typeof(T)); - } + //public T GetOrRegisterInstantiate() + //{ + // return (T)GetOrRegisterInstantiate(typeof(T)); + //} - /// - /// 尝试从容器中获取对象,如果不存在目标类型的对象,则将类型信息登记到容器,并实例化注入依赖项。如果依然无法注册,则返回null。 - /// - public object GetOrRegisterInstantiate(Type type) - { - // 尝试从容器中获取对象 - if (!_dependencies.TryGetValue(type.FullName, out object value)) - { - // 容器中不存在目标类型的对象 - if (type.IsInterface) - { - if (_typeMappings.TryGetValue(type.FullName, out Type implementationType)) - { - // 是接口类型,存在注册信息 - Register(type);// 注册类型信息 - value = Instantiate(implementationType); // 创建实例对象,并注入依赖 - CustomRegisterInstance(type.FullName, value);// 登记到IOC容器中 - _typeMappings.TryRemove(type.FullName, out _); // 取消类型的注册信息 - } - else - { - //需要获取接口类型的实例,但不存在类型注册信息 - Console.WriteLine("当前需要获取接口,但没有注册实现类的类型,无法创建接口实例"); - return null; - } - } - else - { - // 不是接口,直接注册 - Register(type);// 注册类型信息 - value = Instantiate(type); // 创建实例对象,并注入依赖 - CustomRegisterInstance(type.FullName, value);// 登记到IOC容器中 - } - } - return value; - } + ///// + ///// 尝试从容器中获取对象,如果不存在目标类型的对象,则将类型信息登记到容器,并实例化注入依赖项。如果依然无法注册,则返回null。 + ///// + //public object GetOrRegisterInstantiate(Type type) + //{ + // // 尝试从容器中获取对象 + // if (!_dependencies.TryGetValue(type.FullName, out object value)) + // { + // // 容器中不存在目标类型的对象 + // if (type.IsInterface) + // { + // if (_typeMappings.TryGetValue(type.FullName, out Type implementationType)) + // { + // // 是接口类型,存在注册信息 + // Register(type);// 注册类型信息 + // value = Instantiate(implementationType); // 创建实例对象,并注入依赖 + // CustomRegisterInstance(type.FullName, value);// 登记到IOC容器中 + // _typeMappings.TryRemove(type.FullName, out _); // 取消类型的注册信息 + // } + // else + // { + // //需要获取接口类型的实例,但不存在类型注册信息 + // Console.WriteLine("当前需要获取接口,但没有注册实现类的类型,无法创建接口实例"); + // return null; + // } + // } + // else + // { + // // 不是接口,直接注册 + // Register(type);// 注册类型信息 + // value = Instantiate(type); // 创建实例对象,并注入依赖 + // CustomRegisterInstance(type.FullName, value);// 登记到IOC容器中 + // } + // } + // return value; + //} /// /// 用于临时实例的创建,不登记到IOC容器中,依赖项注入失败时也不记录。 @@ -139,16 +144,25 @@ namespace Serein.Library.Utils /// /// /// - public object Instantiate(Type controllerType, params object[] parameters) + public object Instantiate(Type type) { - var instance = Activator.CreateInstance(controllerType, parameters); // CreateInstance(controllerType, parameters); // 创建目标类型的实例 + var constructor = type.GetConstructors().First(); // 获取第一个构造函数 + var parameters = constructor.GetParameters(); // 获取参数列表 + var parameterValues = parameters.Select(param => ResolveDependency(param.ParameterType)).ToArray(); + var instance = Activator.CreateInstance(type, parameterValues); + + //var instance =CreateInstance(controllerType, parameters); // CreateInstance(controllerType, parameters); // 创建目标类型的实例 if (instance != null) { - InjectDependencies(instance, false); // 完成创建后注入实例需要的依赖项 + InjectDependencies(instance, false); // 完成创建后注入实例需要的特性依赖项 } return instance; } + public T Instantiate() + { + return (T)Instantiate(typeof(T)); + } #region 通过名称记录或获取一个实例 /// @@ -177,15 +191,17 @@ namespace Serein.Library.Utils return Get(type.FullName); } - + public T Get() + { + return (T)Get(typeof(T).FullName); + } public T Get(string name) { return (T)Get(name); } private object Get(string name) { - object value; - if (!_dependencies.TryGetValue(name, out value)) + if (!_dependencies.TryGetValue(name, out object value)) { value = null; } @@ -194,9 +210,6 @@ namespace Serein.Library.Utils #endregion - - - #region 容器管理(清空,绑定) /// @@ -224,9 +237,9 @@ namespace Serein.Library.Utils /// 实例化所有已注册的类型,并尝试绑定 /// /// - public bool Build() + public bool Build2() { - InitRegister(); + InitRegister(); // 遍历已注册类型 foreach (var type in _typeMappings.Values.ToArray()) { @@ -245,7 +258,105 @@ namespace Serein.Library.Utils } return true; - } + } + + public bool Build() + { + InitRegister(); + var graph = new Dictionary>(); + //var graph = new Dictionary>(); + + // 构建依赖关系图 + foreach (var type in _typeMappings.Values) + { + var constructor = type.GetConstructors() + .OrderByDescending(c => c.GetParameters().Length) + .FirstOrDefault(); + + if (constructor != null) + { + var parameters = constructor.GetParameters(); + foreach (var param in parameters) + { + var paramTypeName = param.ParameterType.FullName; + if (!graph.ContainsKey(paramTypeName)) + { + graph[paramTypeName] = new List(); + } + graph[paramTypeName].Add(type); // 使用 Type 而不是字符串 + } + } + } + + // 执行拓扑排序 + var sortedTypes = TopologicalSort(graph); + + // 创建实例并注册 + foreach (var type in sortedTypes) + { + var typeName = type.FullName; + if (!_dependencies.ContainsKey(typeName)) + { + + var value = CreateInstance(type); + CustomRegisterInstance(typeName, value); + //if (graph.ContainsKey(typeName)) + //{ + + + //} + //else + //{ + // Console.WriteLine("error:"+typeName); + //} + } + else + { + Console.WriteLine("not create:" + type); + } + } + + return true; + } + + /// + /// 执行拓扑排序 + /// + /// + /// + private List TopologicalSort(Dictionary> graph) + { + var sorted = new List(); + var visited = new HashSet(); + + void Visit(Type node) + { + var nodeName = node.FullName; + if (visited.Contains(nodeName)) return; + visited.Add(nodeName); + if (graph.TryGetValue(nodeName, out var neighbors)) + { + foreach (var neighbor in neighbors) + { + Visit(neighbor); + } + } + sorted.Add(node); + } + + foreach (var node in graph.Keys) + { + if (!_dependencies.ContainsKey(node)) + { + var type = _typeMappings[node]; // 获取对应的 Type + Visit(type); + } + + } + + sorted.Reverse(); // 反转以得到正确顺序 + return sorted; + } #endregion #region 私有方法 @@ -272,13 +383,29 @@ namespace Serein.Library.Utils /// /// 创建实例时,尝试注入到由ioc容器管理、并需要此实例的对象。 /// - private object CreateInstance(Type type, params object[] parameters) + private object CreateInstance(Type type) { - var instance = Activator.CreateInstance(type); + var constructor = type.GetConstructors().First(); // 获取第一个构造函数 + var parameters = constructor.GetParameters(); // 获取参数列表 + var parameterValues = parameters.Select(param => ResolveDependency(param.ParameterType)).ToArray(); + var instance = Activator.CreateInstance(type, parameterValues); InjectUnfinishedDependencies(type.FullName, instance); return instance; } + private object ResolveDependency(Type parameterType) + { + var obj = Get(parameterType); + if (obj is null) + { + throw new InvalidOperationException($"构造函数注入时类型[{parameterType}]不存在实例"); + } + return obj; + } + + /// + /// 如果其它实例想要该对象时,注入过去 + /// private void InjectUnfinishedDependencies(string key,object instance) { if (_unfinishedDependencies.TryGetValue(key, out var unfinishedPropertyList)) @@ -379,7 +506,7 @@ namespace Serein.Library.Utils public void Run(Action action) { - var service = GetOrRegisterInstantiate(); + var service = Get(); if (service != null) { action(service); @@ -388,72 +515,72 @@ namespace Serein.Library.Utils public void Run(Action action) { - var service1 = GetOrRegisterInstantiate(); - var service2 = GetOrRegisterInstantiate(); + var service1 = Get(); + var service2 = Get(); action(service1, service2); } public void Run(Action action) { - var service1 = GetOrRegisterInstantiate(); - var service2 = GetOrRegisterInstantiate(); - var service3 = GetOrRegisterInstantiate(); + var service1 = Get(); + var service2 = Get(); + var service3 = Get(); action(service1, service2, service3); } - public void Run(Action action) + public void Run(Action action) { - var service1 = GetOrRegisterInstantiate(); - var service2 = GetOrRegisterInstantiate(); - var service3 = GetOrRegisterInstantiate(); - var service4 = GetOrRegisterInstantiate(); + var service1 = Get(); + var service2 = Get(); + var service3 = Get(); + var service4 = Get(); action(service1, service2, service3, service4); } public void Run(Action action) { - var service1 = GetOrRegisterInstantiate(); - var service2 = GetOrRegisterInstantiate(); - var service3 = GetOrRegisterInstantiate(); - var service4 = GetOrRegisterInstantiate(); - var service5 = GetOrRegisterInstantiate(); + var service1 = Get(); + var service2 = Get(); + var service3 = Get(); + var service4 = Get(); + var service5 = Get(); action(service1, service2, service3, service4, service5); } public void Run(Action action) { - var service1 = GetOrRegisterInstantiate(); - var service2 = GetOrRegisterInstantiate(); - var service3 = GetOrRegisterInstantiate(); - var service4 = GetOrRegisterInstantiate(); - var service5 = GetOrRegisterInstantiate(); - var service6 = GetOrRegisterInstantiate(); + var service1 = Get(); + var service2 = Get(); + var service3 = Get(); + var service4 = Get(); + var service5 = Get(); + var service6 = Get(); action(service1, service2, service3, service4, service5, service6); } public void Run(Action action) { - var service1 = GetOrRegisterInstantiate(); - var service2 = GetOrRegisterInstantiate(); - var service3 = GetOrRegisterInstantiate(); - var service4 = GetOrRegisterInstantiate(); - var service5 = GetOrRegisterInstantiate(); - var service6 = GetOrRegisterInstantiate(); - var service7 = GetOrRegisterInstantiate(); + var service1 = Get(); + var service2 = Get(); + var service3 = Get(); + var service4 = Get(); + var service5 = Get(); + var service6 = Get(); + var service7 = Get(); action(service1, service2, service3, service4, service5, service6, service7); } public void Run(Action action) { - var service1 = GetOrRegisterInstantiate(); - var service2 = GetOrRegisterInstantiate(); - var service3 = GetOrRegisterInstantiate(); - var service4 = GetOrRegisterInstantiate(); - var service5 = GetOrRegisterInstantiate(); - var service6 = GetOrRegisterInstantiate(); - var service7 = GetOrRegisterInstantiate(); - var service8 = GetOrRegisterInstantiate(); + var service1 = Get(); + var service2 = Get(); + var service3 = Get(); + var service4 = Get(); + var service5 = Get(); + var service6 = Get(); + var service7 = Get(); + var service8 = Get(); action(service1, service2, service3, service4, service5, service6, service7, service8); } diff --git a/Library/Web/Router.cs b/Library/Web/Router.cs index b640c19..12192e9 100644 --- a/Library/Web/Router.cs +++ b/Library/Web/Router.cs @@ -29,6 +29,12 @@ namespace Serein.Library.Web /// public class Router : IRouter { + private readonly ISereinIOC SereinIOC; // 用于存储路由信息 + + public Router(ISereinIOC SereinIOC) + { + this.SereinIOC = SereinIOC; + } /// /// 控制器实例对象的类型,每次调用都会重新实例化,[Url - ControllerType] /// @@ -39,8 +45,7 @@ namespace Serein.Library.Web /// private readonly ConcurrentDictionary> _routes; - [AutoInjection] - public ISereinIOC SereinIOC { get; set; } // 用于存储路由信息 + // private readonly ILoggerService loggerService; // 用于存储路由信息 //private Type PostRequest; diff --git a/Library/Web/WebServer.cs b/Library/Web/WebServer.cs index f627dd6..e0ff7e0 100644 --- a/Library/Web/WebServer.cs +++ b/Library/Web/WebServer.cs @@ -13,13 +13,18 @@ namespace Serein.Library.Web /// /// HTTP接口监听类 /// + [AutoRegister] public class WebServer { - [AutoInjection] - public IRouter Router { get; set; } // 路由器 + private readonly IRouter Router;// 路由器 + public WebServer(IRouter router) + { + this.Router = router; + } - [AutoInjection] - public NodeRunCts nodeRunCts { get; set; } + + //[AutoInjection] + //public NodeRunCts nodeRunCts { get; set; } private HttpListener listener; // HTTP 监听器 private RequestLimiter requestLimiter; //接口防刷 diff --git a/Net461DllTest/Device/SiemensPlcDevice.cs b/Net461DllTest/Device/SiemensPlcDevice.cs index b573e15..a0991f8 100644 --- a/Net461DllTest/Device/SiemensPlcDevice.cs +++ b/Net461DllTest/Device/SiemensPlcDevice.cs @@ -2,6 +2,7 @@ using Net461DllTest.Enums; using Net461DllTest.Signal; using Net461DllTest.Utils; +using Serein.Library.Attributes; using Serein.Library.NodeFlow.Tool; using System; @@ -11,6 +12,7 @@ namespace Net461DllTest.Device /// /// 官方文档:如果没有主动Open,则会每次读写操作的时候自动打开自动和关闭连接,这样会使读写效率大大减低。所以建议手动Open和Close。 /// + [AutoRegister] public class SiemensPlcDevice : ChannelFlowTrigger { public SiemensClient Client { get; set; } diff --git a/Net461DllTest/LogicControl/ParkingLogicControl.cs b/Net461DllTest/LogicControl/ParkingLogicControl.cs index 291e700..0b011cb 100644 --- a/Net461DllTest/LogicControl/ParkingLogicControl.cs +++ b/Net461DllTest/LogicControl/ParkingLogicControl.cs @@ -21,23 +21,18 @@ namespace Net461DllTest.LogicControl GetPparkingSpace, } - + [AutoRegister] [DynamicFlow] public class ParkingLogicControl { - [AutoInjection] - public PrakingDevice PrakingDevice { get; set; } + private readonly PrakingDevice PrakingDevice; - - [NodeAction(NodeType.Init)] - public void Init(IDynamicContext context) + public ParkingLogicControl(PrakingDevice PrakingDevice) { - - context.Env.IOC.Register(); + this.PrakingDevice = PrakingDevice; } - [NodeAction(NodeType.Flipflop, "等待车位调取命令",ReturnType=typeof(string))] public async Task GetPparkingSpace(ParkingCommand parkingCommand = ParkingCommand.GetPparkingSpace) { diff --git a/Net461DllTest/LogicControl/PlcLogicControl.cs b/Net461DllTest/LogicControl/PlcLogicControl.cs index 7d784df..29a98dc 100644 --- a/Net461DllTest/LogicControl/PlcLogicControl.cs +++ b/Net461DllTest/LogicControl/PlcLogicControl.cs @@ -19,21 +19,21 @@ using System.Threading.Tasks; namespace Net461DllTest.LogicControl { + [AutoRegister] [DynamicFlow] public class PlcLogicControl { - [AutoInjection] - public SiemensPlcDevice MyPlc { get; set; } - - + private readonly SiemensPlcDevice MyPlc; + public PlcLogicControl(SiemensPlcDevice MyPlc) + { + this.MyPlc = MyPlc; + } #region 初始化、初始化完成以及退出的事件 [NodeAction(NodeType.Init)] // Init : 初始化事件,流程启动时执行 public void Init(IDynamicContext context) { - context.Env.IOC.Register(); // 注册Plc设备 - context.Env.IOC.Register(); // 注册Web服务 // // 注册控制器 context.Env.IOC.Run(router => { router.RegisterController(typeof(ApiController)); @@ -146,14 +146,14 @@ namespace Net461DllTest.LogicControl if (MyPlc.State == PlcState.Runing) { - if (!varInfo.IsProtected) + if (varInfo.IsProtected) { - MyPlc.Write(varInfo, value); - Console.WriteLine($"PLC变量{varInfo}写入数据:{value}"); + Console.WriteLine($"PLC变量{varInfo}当前禁止写入"); } else { - Console.WriteLine($"PLC变量{varInfo}当前禁止写入"); + MyPlc.Write(varInfo, value); + Console.WriteLine($"PLC变量{varInfo}写入数据:{value}"); } } else diff --git a/Net461DllTest/LogicControl/ViewLogicControl.cs b/Net461DllTest/LogicControl/ViewLogicControl.cs index d65c122..031495b 100644 --- a/Net461DllTest/LogicControl/ViewLogicControl.cs +++ b/Net461DllTest/LogicControl/ViewLogicControl.cs @@ -1,4 +1,5 @@ -using Net461DllTest.Signal; +using Net461DllTest.Device; +using Net461DllTest.Signal; using Net461DllTest.ViewModel; using Serein.Library.Api; using Serein.Library.Attributes; @@ -11,7 +12,7 @@ using System.Windows.Forms; namespace Net461DllTest.LogicControl { - + [AutoRegister] public class ViewManagement { @@ -46,8 +47,11 @@ namespace Net461DllTest.LogicControl [DynamicFlow] public class ViewLogicControl { - [AutoInjection] - public ViewManagement ViewManagement { get; set; } + private readonly ViewManagement ViewManagement; + public ViewLogicControl(ViewManagement ViewManagement) + { + this.ViewManagement = ViewManagement; + } [NodeAction(NodeType.Init)] public void Init(IDynamicContext context) diff --git a/Net461DllTest/View/FromWorkBenchView.cs b/Net461DllTest/View/FromWorkBenchView.cs index 4719625..0eaca8f 100644 --- a/Net461DllTest/View/FromWorkBenchView.cs +++ b/Net461DllTest/View/FromWorkBenchView.cs @@ -1,6 +1,7 @@ using Net461DllTest.Device; using Net461DllTest.Signal; using Net461DllTest.ViewModel; +using Serein.Library.Api; using Serein.Library.Attributes; using System; using System.Collections.Generic; @@ -16,11 +17,17 @@ namespace Net461DllTest { public partial class FromWorkBenchView : Form { - [AutoInjection] - public FromWorkBenchViewModel ViewModel { get; set; } - public FromWorkBenchView() + private FromWorkBenchViewModel ViewModel; + + public FromWorkBenchView(IFlowEnvironment env) { + ViewModel = env.IOC.Instantiate(); InitializeComponent(); + Init(); + } + + public void Init() + { listBox1.Items.Clear(); var enumValues = Enum.GetValues(typeof(OrderSignal)).Cast(); foreach (var value in enumValues) diff --git a/Net461DllTest/ViewModel/FromWorkBenchViewModel.cs b/Net461DllTest/ViewModel/FromWorkBenchViewModel.cs index 31c1652..8715120 100644 --- a/Net461DllTest/ViewModel/FromWorkBenchViewModel.cs +++ b/Net461DllTest/ViewModel/FromWorkBenchViewModel.cs @@ -11,8 +11,12 @@ namespace Net461DllTest.ViewModel { public class FromWorkBenchViewModel { - [AutoInjection] - public SiemensPlcDevice Device { get; set; } + public FromWorkBenchViewModel(SiemensPlcDevice Device) + { + this.Device = Device; + } + private SiemensPlcDevice Device; + public string Name { get; set; } public string GetDeviceInfo() @@ -20,7 +24,6 @@ namespace Net461DllTest.ViewModel return Device?.ToString(); } - public void Trigger(OrderSignal signal,string spcaeNumber) { _ = Task.Run(() => diff --git a/NodeFlow/Base/NodeModelBaseFunc.cs b/NodeFlow/Base/NodeModelBaseFunc.cs index db835e7..e7178f8 100644 --- a/NodeFlow/Base/NodeModelBaseFunc.cs +++ b/NodeFlow/Base/NodeModelBaseFunc.cs @@ -200,8 +200,12 @@ namespace Serein.NodeFlow.Base #endregion MethodDetails md = MethodDetails; - var del = md.MethodDelegate.Clone(); - md.ActingInstance ??= context.Env.IOC.GetOrRegisterInstantiate(MethodDetails.ActingInstanceType); + //var del = md.MethodDelegate.Clone(); + if (!context.Env.TryGetDelegate(md.MethodName, out var del)) + { + throw new Exception("不存在对应委托"); + } + md.ActingInstance ??= context.Env.IOC.Get(MethodDetails.ActingInstanceType); object instance = md.ActingInstance; var haveParameter = md.ExplicitDatas.Length > 0; diff --git a/NodeFlow/FlowEnvironment.cs b/NodeFlow/FlowEnvironment.cs index c1e0e32..986989f 100644 --- a/NodeFlow/FlowEnvironment.cs +++ b/NodeFlow/FlowEnvironment.cs @@ -36,8 +36,7 @@ namespace Serein.NodeFlow - - + /// /// 运行环境 @@ -47,12 +46,12 @@ namespace Serein.NodeFlow public FlowEnvironment() { sereinIOC = new SereinIOC(); - ChannelFlowInterrupt = new ChannelFlowInterrupt(); - LoadedAssemblyPaths = new List(); - LoadedAssemblies = new List(); - MethodDetailss = new List(); - Nodes = new Dictionary(); - FlipflopNodes = new List(); + //ChannelFlowInterrupt = new ChannelFlowInterrupt(); + //LoadedAssemblyPaths = new List(); + //LoadedAssemblies = new List(); + //MethodDetailss = new List(); + //Nodes = new Dictionary(); + //FlipflopNodes = new List(); IsGlobalInterrupt = false; flowStarter = null; @@ -70,7 +69,12 @@ namespace Serein.NodeFlow /// /// 加载Dll /// - public event LoadDLLHandler OnDllLoad; + public event LoadDllHandler OnDllLoad; + + /// + /// 移除DLL + /// + public event RemoteDllHandler OnDllRemote; /// /// 项目加载完成 @@ -158,27 +162,36 @@ namespace Serein.NodeFlow /// /// 存储加载的程序集路径 /// - private List LoadedAssemblyPaths { get; } /// /// 存储加载的程序集 /// - private List LoadedAssemblies { get; } + private List NodeLibrarys { get; } = []; /// /// 存储所有方法信息 /// - private List MethodDetailss { get; } + //private MethodDetailss { get; } = []; + private Dictionary> MethodDetailss { get; } = []; /// /// 环境加载的节点集合 + /// Node Guid - Node Model /// - private Dictionary Nodes { get; } + private Dictionary Nodes { get; } = []; /// /// 存放触发器节点(运行时全部调用) /// - private List FlipflopNodes { get; } + private List FlipflopNodes { get; } = []; + private List AutoRegisterTypes { get; } = []; + + /// + /// 存放委托 + /// + /// md.Methodname - delegate + /// + private ConcurrentDictionary MethodDelegates { get; } = []; /// /// 起始节点私有属性 @@ -225,14 +238,25 @@ namespace Serein.NodeFlow flowStarter = new FlowStarter(); var nodes = Nodes.Values.ToList(); - List initMethods; - List loadingMethods; - List exitMethods; - initMethods = MethodDetailss.Where(it => it.MethodDynamicType == NodeType.Init).ToList(); - loadingMethods = MethodDetailss.Where(it => it.MethodDynamicType == NodeType.Loading).ToList(); - exitMethods = MethodDetailss.Where(it => it.MethodDynamicType == NodeType.Exit).ToList(); - - await flowStarter.RunAsync(this, nodes, initMethods, loadingMethods, exitMethods); + List initMethods = []; + List loadMethods = []; + List exitMethods = []; + foreach(var mds in MethodDetailss.Values) + { + var initMds = mds.Where(it => it.MethodDynamicType == NodeType.Init); + var loadMds = mds.Where(it => it.MethodDynamicType == NodeType.Loading); + var exitMds = mds.Where(it => it.MethodDynamicType == NodeType.Exit); + initMethods.AddRange(initMds); + loadMethods.AddRange(loadMds); + exitMethods.AddRange(exitMds); + } + this.IOC.Reset(); // 开始运行时清空ioc中注册的实例 + this.IOC.CustomRegisterInstance(typeof(IFlowEnvironment).FullName,this); + foreach (var type in AutoRegisterTypes) + { + this.IOC.Register(type); + } + await flowStarter.RunAsync(this, nodes, initMethods, loadMethods, exitMethods); if (flowStarter?.FlipFlopState == RunState.NoStart) { @@ -289,8 +313,8 @@ namespace Serein.NodeFlow /// public void ClearAll() { - LoadedAssemblyPaths.Clear(); - LoadedAssemblies.Clear(); + //LoadedAssemblyPaths.Clear(); + NodeLibrarys.Clear(); MethodDetailss.Clear(); } @@ -311,12 +335,7 @@ namespace Serein.NodeFlow foreach (var dll in dllPaths) { var dllFilePath = System.IO.Path.GetFullPath(System.IO.Path.Combine(filePath, dll)); - (var assembly, var registerTypes, var mdlist) = LoadAssembly(dllFilePath); - if (assembly is not null && mdlist.Count > 0) - { - MethodDetailss.AddRange(mdlist); // 暂存方法描述 - OnDllLoad?.Invoke(new LoadDLLEventArgs(assembly, mdlist)); // 通知UI创建dll面板显示 - } + LoadDllNodeInfo(dllFilePath); } // 方法加载完成,缓存到运行环境中。 //MethodDetailss.AddRange(methodDetailss); @@ -434,8 +453,7 @@ namespace Serein.NodeFlow SetStartNode(project.StartNode); OnProjectLoaded?.Invoke(new ProjectLoadedEventArgs()); } - - + /// /// 保存项目为项目文件 /// @@ -444,7 +462,7 @@ namespace Serein.NodeFlow { var projectData = new SereinProjectData() { - Librarys = LoadedAssemblies.Select(assemblies => assemblies.ToLibrary()).ToArray(), + Librarys = NodeLibrarys.Select(assemblies => assemblies.Assembly.ToLibrary()).ToArray(), Nodes = Nodes.Values.Select(node => node.ToInfo()).Where(info => info is not null).ToArray(), StartNode = Nodes.Values.FirstOrDefault(it => it.IsStart)?.Guid, }; @@ -458,14 +476,45 @@ namespace Serein.NodeFlow /// public void LoadDll(string dllPath) { - (var assembly, _, var list) = LoadAssembly(dllPath); - if (assembly is not null && list.Count > 0) + LoadDllNodeInfo(dllPath); + } + + public bool RemoteDll(string assemblyFullName) + { + var library = NodeLibrarys.FirstOrDefault(nl => nl.Assembly.FullName.Equals(assemblyFullName)); + if(library is null) { - MethodDetailss.AddRange(list); - OnDllLoad?.Invoke(new LoadDLLEventArgs(assembly, list)); + return false; + } + + var nodes = Nodes.Values.ToDictionary( + key => key.MethodDetails.MethodName, + value => value + ); + if(nodes.Count == 0) + { + return true; // 当前无节点,可以直接删除 + } + + if (MethodDetailss.TryGetValue(library,out var mds)) // 存在方法 + { + foreach(var md in mds) + { + if (nodes.ContainsKey(md.MethodName)) + { + return false; // 创建过相关的节点 + } + } + MethodDetailss.Remove(library); + return true; // 没有创建相关的节点 + } + else + { + return true; } } + /// /// 运行时创建节点 /// @@ -503,10 +552,10 @@ namespace Serein.NodeFlow { var remoteNode = GuidToModel(nodeGuid); if (remoteNode is null) return; - if (remoteNode.IsStart) - { - return; - } + //if (remoteNode.IsStart) + //{ + // return; + //} if (remoteNode is SingleFlipflopNode flipflopNode) { flowStarter?.TerminateGlobalFlipflopRuning(flipflopNode); // 假设被移除的是全局触发器,尝试从启动器移除 @@ -618,8 +667,16 @@ namespace Serein.NodeFlow { if (!string.IsNullOrEmpty(name)) { - md = MethodDetailss.FirstOrDefault(it => it.MethodName == name); - return md != null; + foreach(var mds in MethodDetailss.Values) + { + md = mds.FirstOrDefault(it => it.MethodName == name); + if(md != null) + { + return true; + } + } + md = null; + return false; } else { @@ -628,6 +685,19 @@ namespace Serein.NodeFlow } } + public bool TryGetDelegate(string methodName, out Delegate del) + { + if (MethodDelegates.TryGetValue(methodName, out del)) + { + return del != null; + } + else + { + del = null; + return false; + } + } + /// /// 设置起点控件 /// @@ -850,7 +920,23 @@ namespace Serein.NodeFlow /// 加载指定路径的DLL文件 /// /// - private (Assembly?, List ,List) LoadAssembly(string dllPath) + + private void LoadDllNodeInfo(string dllPath) + { + (var nodeLibrary, var registerTypes, var mdlist) = LoadAssembly(dllPath); + if (nodeLibrary is not null && mdlist.Count > 0) + { + MethodDetailss.Add(nodeLibrary, mdlist); + NodeLibrarys.Add(nodeLibrary); + AutoRegisterTypes.AddRange(registerTypes); + + OnDllLoad?.Invoke(new LoadDllEventArgs(nodeLibrary, mdlist)); // 通知UI创建dll面板显示 + } + + } + + + private (NodeLibrary?, List ,List) LoadAssembly(string dllPath) { try { @@ -867,22 +953,36 @@ namespace Serein.NodeFlow List methodDetails = new List(); // 遍历扫描的类型 - foreach (var item in scanTypes) + foreach (var type in scanTypes) { // 加载DLL,创建 MethodDetails、实例作用对象、委托方法 - var itemMethodDetails = MethodDetailsHelperTmp.GetList(item); - methodDetails.AddRange(itemMethodDetails); - //foreach (var md in itemMethodDetails) - //{ - // // var instanceType = - // // Activator.CreateInstance(md.ActingInstanceType); - // // SereinIoc.RegisterInstantiate(md.ActingInstance); - // SereinIoc.Register(md.ActingInstanceType); - //} + var assemblyName = type.Assembly.GetName().Name; + var methods = MethodDetailsHelperTmp.GetMethodsToProcess(type); + foreach(var method in methods) + { + (var md, var del) = MethodDetailsHelperTmp.CreateMethodDetails(type, method, assemblyName); + + if (MethodDelegates.TryAdd(md.MethodName, del)) + { + methodDetails.Add(md); + } + else + { + Console.WriteLine($"节点委托创建失败:{md.MethodName}"); + } + } + + //methodDetails.AddRange(itemMethodDetails); } - LoadedAssemblies.Add(assembly); // 将加载的程序集添加到列表中 - LoadedAssemblyPaths.Add(dllPath); // 记录加载的DLL路径 - return (assembly, autoRegisterTypes , methodDetails); + + var nodeLibrary = new NodeLibrary + { + Assembly = assembly, + Path = dllPath, + }; + //LoadedAssemblies.Add(assembly); // 将加载的程序集添加到列表中 + //LoadedAssemblyPaths.Add(dllPath); // 记录加载的DLL路径 + return (nodeLibrary, autoRegisterTypes , methodDetails); } catch (Exception ex) { @@ -1068,8 +1168,6 @@ namespace Serein.NodeFlow #endregion - - #region IOC容器相关 ISereinIOC ISereinIOC.Reset() { @@ -1095,38 +1193,45 @@ namespace Serein.NodeFlow return this; } - T ISereinIOC.GetOrRegisterInstantiate() - { - return sereinIOC.GetOrRegisterInstantiate(); + //T ISereinIOC.GetOrRegisterInstantiate() + //{ + // return sereinIOC.GetOrRegisterInstantiate(); - } + //} - object ISereinIOC.GetOrRegisterInstantiate(Type type) - { - return sereinIOC.GetOrRegisterInstantiate(type); - } + //object ISereinIOC.GetOrRegisterInstantiate(Type type) + //{ + // return sereinIOC.GetOrRegisterInstantiate(type); + //} object ISereinIOC.Get(Type type) { return sereinIOC.Get(type); } - + T ISereinIOC.Get() + { + return (T)sereinIOC.Get(typeof(T)); + } T ISereinIOC.Get(string key) { return sereinIOC.Get(key); } + void ISereinIOC.CustomRegisterInstance(string key, object instance, bool needInjectProperty) { sereinIOC.CustomRegisterInstance(key, instance, needInjectProperty); } - object ISereinIOC.Instantiate(Type type, params object[] parameters) + object ISereinIOC.Instantiate(Type type) { - return sereinIOC.Instantiate(type, parameters); + return sereinIOC.Instantiate(type); + } + T ISereinIOC.Instantiate() + { + return sereinIOC.Instantiate(); } - ISereinIOC ISereinIOC.Build() { sereinIOC.Build(); diff --git a/NodeFlow/FlowStarter.cs b/NodeFlow/FlowStarter.cs index d6721b6..40ada7d 100644 --- a/NodeFlow/FlowStarter.cs +++ b/NodeFlow/FlowStarter.cs @@ -161,7 +161,7 @@ namespace Serein.NodeFlow { nodeMd.ActingInstance = null; } - env.IOC.Reset(); // 开始运行时清空ioc中注册的实例 + env.IOC.CustomRegisterInstance(typeof(ISereinIOC).FullName, env); // 初始化ioc容器中的类型对象 foreach (var md in thisRuningMds) @@ -178,12 +178,11 @@ namespace Serein.NodeFlow } CheckStartState(); // 初始化IOC后检查状态 - env.IOC.Build(); // 流程启动前的初始化 foreach (var md in thisRuningMds) { - md.ActingInstance = env.IOC.GetOrRegisterInstantiate(md.ActingInstanceType); + md.ActingInstance = env.IOC.Get(md.ActingInstanceType); if(md.ActingInstance is null) { await Console.Out.WriteLineAsync($"{md.MethodName} - 无法获取类型[{md.ActingInstanceType}]的实例"); @@ -215,14 +214,22 @@ namespace Serein.NodeFlow //object?[]? args = [Context]; foreach (var md in initMethods) // 初始化 { - ((Action)md.MethodDelegate).Invoke(md.ActingInstance, [Context]); + if (!env.TryGetDelegate(md.MethodName, out var del)) + { + throw new Exception("不存在对应委托"); + } + ((Action)del).Invoke(md.ActingInstance, [Context]); } Context.Env.IOC.Build(); // 绑定初始化时注册的类型 foreach (var md in loadingMethods) // 加载 { //object?[]? data = [md.ActingInstance, args]; //md.MethodDelegate.DynamicInvoke(data); - ((Action)md.MethodDelegate).Invoke(md.ActingInstance, [Context]); + if (!env.TryGetDelegate(md.MethodName, out var del)) + { + throw new Exception("不存在对应委托"); + } + ((Action)del).Invoke(md.ActingInstance, [Context]); } Context.Env.IOC.Build(); // 预防有人在加载时才注册类型,再绑定一次 #endregion @@ -236,7 +243,11 @@ namespace Serein.NodeFlow foreach (MethodDetails? md in exitMethods) { - ((Action)md.MethodDelegate).Invoke(md.ActingInstance, [Context]); + if (!env.TryGetDelegate(md.MethodName, out var del)) + { + throw new Exception("不存在对应委托"); + } + ((Action)del).Invoke(md.ActingInstance, [Context]); } TerminateAllGlobalFlipflop(); @@ -303,7 +314,7 @@ namespace Serein.NodeFlow { if (dictGlobalFlipflop.TryAdd(singleFlipFlopNode, new CancellationTokenSource())) { - singleFlipFlopNode.MethodDetails.ActingInstance ??= env.IOC.GetOrRegisterInstantiate(singleFlipFlopNode.MethodDetails.ActingInstanceType); + singleFlipFlopNode.MethodDetails.ActingInstance ??= env.IOC.Get(singleFlipFlopNode.MethodDetails.ActingInstanceType); await FlipflopExecuteAsync(env, singleFlipFlopNode, dictGlobalFlipflop[singleFlipFlopNode]); } } diff --git a/NodeFlow/Model/SingleFlipflopNode.cs b/NodeFlow/Model/SingleFlipflopNode.cs index 3161a1b..f530e74 100644 --- a/NodeFlow/Model/SingleFlipflopNode.cs +++ b/NodeFlow/Model/SingleFlipflopNode.cs @@ -32,7 +32,10 @@ namespace Serein.NodeFlow.Model #endregion MethodDetails md = MethodDetails; - var del = md.MethodDelegate.Clone(); + if (!context.Env.TryGetDelegate(md.MethodName, out var del)) + { + throw new Exception("不存在对应委托"); + } object instance = md.ActingInstance; // Task? flipflopTask = null; try diff --git a/NodeFlow/Tool/MethodDetailsHelper.cs b/NodeFlow/Tool/MethodDetailsHelper.cs index d5cb962..632ed1e 100644 --- a/NodeFlow/Tool/MethodDetailsHelper.cs +++ b/NodeFlow/Tool/MethodDetailsHelper.cs @@ -11,31 +11,39 @@ namespace Serein.NodeFlow.Tool; public static class MethodDetailsHelperTmp { + /// /// 生成方法信息 /// /// /// /// - public static List GetList(Type type) - { - var methodDetailsDictionary = new List(); - var assemblyName = type.Assembly.GetName().Name; - var methods = GetMethodsToProcess(type); + //public static List GetList(Type type) + //{ + // var methodDetailsDictionary = new List(); + // var delegateDictionary = new List(); + // var assemblyName = type.Assembly.GetName().Name; + // var methods = GetMethodsToProcess(type); - foreach (var method in methods) - { + // foreach (var method in methods) + // { - var methodDetails = CreateMethodDetails(type, method, assemblyName); - methodDetailsDictionary.Add(methodDetails); - } + // (var methodDetails,var methodDelegate) = CreateMethodDetails(type, method, assemblyName); + + // methodDetailsDictionary.Add(methodDetails); + // delegateDictionary.Add(methodDelegate); + // } - return methodDetailsDictionary.OrderBy(it => it.MethodName).ToList(); - } + // var mds = methodDetailsDictionary.OrderBy(it => it.MethodName).ToList(); + // var dels = delegateDictionary; + + // return mds; + //} + /// /// 获取处理方法 /// - private static IEnumerable GetMethodsToProcess(Type type) + public static IEnumerable GetMethodsToProcess(Type type) { return type.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) .Where(m => m.GetCustomAttribute()?.Scan == true); @@ -44,17 +52,17 @@ public static class MethodDetailsHelperTmp /// 创建方法信息 /// /// - private static MethodDetails CreateMethodDetails(Type type, MethodInfo method, string assemblyName) + public static (MethodDetails,Delegate) CreateMethodDetails(Type type, MethodInfo method, string assemblyName) { var methodName = method.Name; var attribute = method.GetCustomAttribute(); if(attribute is null) { - return null; + return (null, null); } var explicitDataOfParameters = GetExplicitDataOfParameters(method.GetParameters()); - // 生成委托 + //// 生成委托 var methodDelegate = GenerateMethodDelegate(type, // 方法所在的对象类型 method, // 方法信息 method.GetParameters(),// 方法参数 @@ -75,12 +83,11 @@ public static class MethodDetailsHelperTmp // object instance = Activator.CreateInstance(type); var dllTypeMethodName = $"{assemblyName}.{type.Name}.{method.Name}"; - return new MethodDetails + var md = new MethodDetails { ActingInstanceType = type, // ActingInstance = instance, MethodName = dllTypeMethodName, - MethodDelegate = methodDelegate, MethodDynamicType = attribute.MethodDynamicType, MethodLockName = attribute.LockName, MethodTips = attribute.MethodTips, @@ -88,6 +95,8 @@ public static class MethodDetailsHelperTmp ReturnType = returnType, }; + return (md, methodDelegate); + } diff --git a/WorkBench/MainWindow.xaml.cs b/WorkBench/MainWindow.xaml.cs index c41dbfd..5d4dccb 100644 --- a/WorkBench/MainWindow.xaml.cs +++ b/WorkBench/MainWindow.xaml.cs @@ -283,16 +283,13 @@ namespace Serein.WorkBench /// /// 加载了DLL文件,dll内容 /// - private void FlowEnvironment_DllLoadEvent(LoadDLLEventArgs eventArgs) + private void FlowEnvironment_DllLoadEvent(LoadDllEventArgs eventArgs) { this.Dispatcher.Invoke(() => { - Assembly assembly = eventArgs.Assembly; + NodeLibrary nodeLibrary = eventArgs.NodeLibrary; List methodDetailss = eventArgs.MethodDetailss; - var dllControl = new DllControl - { - Header = "DLL name : " + assembly.GetName().Name // 设置控件标题为程序集名称 - }; + var dllControl = new DllControl(nodeLibrary); foreach (var methodDetails in methodDetailss) { @@ -306,6 +303,21 @@ namespace Serein.WorkBench break; } } + var menu = new ContextMenu(); + menu.Items.Add(CreateMenuItem("卸载", (s,e) => + { + if (this.FlowEnvironment.RemoteDll(nodeLibrary.Assembly.FullName)) + { + DllStackPanel.Children.Remove(dllControl); + } + else + { + Console.WriteLine("卸载失败"); + } + })); + + dllControl.ContextMenu = menu; + DllStackPanel.Children.Add(dllControl); // 将控件添加到界面上显示 }); @@ -775,26 +787,26 @@ namespace Serein.WorkBench /// /// /// - private void AddNodeControlInRegeionControl(NodeControlBase regionControl, NodeInfo[] childNodes) - { - foreach (var childNode in childNodes) - { - if (FlowEnvironment.TryGetMethodDetails(childNode.MethodName, out MethodDetails md)) - { - var childNodeControl = CreateNodeControlOfNodeInfo(childNode, md); - if (childNodeControl is null) - { - Console.WriteLine($"无法为节点类型创建节点控件: {childNode.MethodName}\r\n"); - continue; - } + //private void AddNodeControlInRegeionControl(NodeControlBase regionControl, NodeInfo[] childNodes) + //{ + // foreach (var childNode in childNodes) + // { + // if (FlowEnvironment.TryGetMethodDetails(childNode.MethodName, out MethodDetails md)) + // { + // var childNodeControl = CreateNodeControlOfNodeInfo(childNode, md); + // if (childNodeControl is null) + // { + // Console.WriteLine($"无法为节点类型创建节点控件: {childNode.MethodName}\r\n"); + // continue; + // } - if (regionControl is ConditionRegionControl conditionRegion) - { - conditionRegion.AddCondition(childNodeControl); - } - } - } - } + // if (regionControl is ConditionRegionControl conditionRegion) + // { + // conditionRegion.AddCondition(childNodeControl); + // } + // } + // } + //} #endregion diff --git a/WorkBench/Node/View/DllControlControl.xaml.cs b/WorkBench/Node/View/DllControlControl.xaml.cs index 353b2e0..fc119d9 100644 --- a/WorkBench/Node/View/DllControlControl.xaml.cs +++ b/WorkBench/Node/View/DllControlControl.xaml.cs @@ -1,6 +1,8 @@ -using Serein.Library.Entity; +using Serein.Library.Api; +using Serein.Library.Entity; using Serein.Library.Enums; using Serein.NodeFlow; +using System.Reflection; using System.Windows; using System.Windows.Automation; using System.Windows.Controls; @@ -18,12 +20,20 @@ namespace Serein.WorkBench.Node.View /// public partial class DllControl : UserControl { + private readonly NodeLibrary nodeLibrary; public DllControl() { Header = "DLL文件"; // 设置初始值 InitializeComponent(); } + public DllControl(NodeLibrary nodeLibrary) + { + this.nodeLibrary = nodeLibrary; + Header = "DLL name : " + nodeLibrary.Assembly.GetName().Name; + InitializeComponent(); + } + /// @@ -39,10 +49,6 @@ namespace Serein.WorkBench.Node.View DependencyProperty.Register("Header", typeof(string), typeof(DllControl), new PropertyMetadata(string.Empty)); - - - - /// /// 向动作面板添加类型的文本块 ///