mirror of
https://gitee.com/langsisi_admin/serein-flow
synced 2026-04-27 18:23:23 +08:00
重写IOC容器绑定逻辑
This commit is contained in:
@@ -5,6 +5,7 @@ using Serein.Library.Web;
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Xml;
|
using System.Xml;
|
||||||
@@ -12,6 +13,7 @@ using System.Xml.Schema;
|
|||||||
|
|
||||||
namespace Serein.Library.Utils
|
namespace Serein.Library.Utils
|
||||||
{
|
{
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// IOC管理容器
|
/// IOC管理容器
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -44,20 +46,7 @@ namespace Serein.Library.Utils
|
|||||||
_unfinishedDependencies = new ConcurrentDictionary<string, List<(object, PropertyInfo)>>();
|
_unfinishedDependencies = new ConcurrentDictionary<string, List<(object, PropertyInfo)>>();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 绑定之前进行的默认绑定
|
|
||||||
/// </summary>
|
|
||||||
public void InitRegister()
|
|
||||||
{
|
|
||||||
_dependencies[typeof(ISereinIOC).FullName] = this;
|
|
||||||
Register<IRouter, Router>();
|
|
||||||
|
|
||||||
//foreach (var type in _typeMappings.Values)
|
|
||||||
//{
|
|
||||||
// Register(type);
|
|
||||||
//}
|
|
||||||
//Build();
|
|
||||||
}
|
|
||||||
|
|
||||||
#region 类型的注册
|
#region 类型的注册
|
||||||
|
|
||||||
@@ -93,51 +82,6 @@ namespace Serein.Library.Utils
|
|||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 尝试从容器中获取对象,如果不存在目标类型的对象,则将类型信息登记到容器,并实例化注入依赖项。如果依然无法注册,则返回null。
|
|
||||||
/// </summary>
|
|
||||||
//public T GetOrRegisterInstantiate<T>()
|
|
||||||
//{
|
|
||||||
// return (T)GetOrRegisterInstantiate(typeof(T));
|
|
||||||
//}
|
|
||||||
|
|
||||||
///// <summary>
|
|
||||||
///// 尝试从容器中获取对象,如果不存在目标类型的对象,则将类型信息登记到容器,并实例化注入依赖项。如果依然无法注册,则返回null。
|
|
||||||
///// </summary>
|
|
||||||
//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;
|
|
||||||
//}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 用于临时实例的创建,不登记到IOC容器中,依赖项注入失败时也不记录。
|
/// 用于临时实例的创建,不登记到IOC容器中,依赖项注入失败时也不记录。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -229,134 +173,157 @@ namespace Serein.Library.Utils
|
|||||||
_unfinishedDependencies?.Clear();
|
_unfinishedDependencies?.Clear();
|
||||||
_typeMappings?.Clear();
|
_typeMappings?.Clear();
|
||||||
_dependencies?.Clear();
|
_dependencies?.Clear();
|
||||||
// _waitingForInstantiation?.Clear();
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
public class TypeKeyValue
|
||||||
/// <summary>
|
|
||||||
/// 实例化所有已注册的类型,并尝试绑定
|
|
||||||
/// </summary>
|
|
||||||
/// <returns></returns>
|
|
||||||
public bool Build2()
|
|
||||||
{
|
{
|
||||||
InitRegister();
|
public TypeKeyValue(string name, Type type)
|
||||||
// 遍历已注册类型
|
|
||||||
foreach (var type in _typeMappings.Values.ToArray())
|
|
||||||
{
|
{
|
||||||
if (!_dependencies.ContainsKey(type.FullName))
|
this.Type = type;
|
||||||
{
|
this.Name = name;
|
||||||
var value = CreateInstance(type); // 绑定时注册的类型如果没有创建实例,则创建对应的实例
|
|
||||||
CustomRegisterInstance(type.FullName, value);// 登记到IOC容器中
|
|
||||||
}
|
|
||||||
_typeMappings.TryRemove(type.FullName, out _); // 移除类型的注册记录
|
|
||||||
}
|
}
|
||||||
|
public string Name { get; set; }
|
||||||
|
public Type Type { get; set; }
|
||||||
foreach (var instance in _dependencies.Values)
|
|
||||||
{
|
|
||||||
InjectDependencies(instance); // 绑定时注入实例的依赖项
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Dictionary<string, List<string>> BuildDependencyTree()
|
||||||
|
{
|
||||||
|
var dependencyMap = new Dictionary<string, List<string>>();
|
||||||
|
|
||||||
|
foreach (var typeMapping in _typeMappings)
|
||||||
|
{
|
||||||
|
var constructor = GetConstructorWithMostParameters(typeMapping.Value); // 获取参数最多的构造函数
|
||||||
|
if (constructor != null)
|
||||||
|
{
|
||||||
|
var parameters = constructor.GetParameters()
|
||||||
|
.Select(p => p.ParameterType)
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
foreach (var param in parameters)
|
||||||
|
{
|
||||||
|
if (!dependencyMap.ContainsKey(param.FullName))
|
||||||
|
{
|
||||||
|
dependencyMap[param.FullName] = new List<string>();
|
||||||
|
}
|
||||||
|
dependencyMap[param.FullName].Add(typeMapping.Key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return dependencyMap;
|
||||||
|
}
|
||||||
|
// 获取参数最多的构造函数
|
||||||
|
private ConstructorInfo GetConstructorWithMostParameters(Type type)
|
||||||
|
{
|
||||||
|
return type.GetConstructors()
|
||||||
|
.OrderByDescending(c => c.GetParameters().Length)
|
||||||
|
.FirstOrDefault();
|
||||||
|
}
|
||||||
|
// 生成顺序
|
||||||
|
public List<string> GetCreationOrder(Dictionary<string, List<string>> dependencyMap)
|
||||||
|
{
|
||||||
|
var graph = new Dictionary<string, List<string>>();
|
||||||
|
var indegree = new Dictionary<string, int>();
|
||||||
|
|
||||||
|
foreach (var entry in dependencyMap)
|
||||||
|
{
|
||||||
|
var key = entry.Key;
|
||||||
|
if (!graph.ContainsKey(key))
|
||||||
|
{
|
||||||
|
graph[key] = new List<string>();
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var dependent in entry.Value)
|
||||||
|
{
|
||||||
|
if (!graph.ContainsKey(dependent))
|
||||||
|
{
|
||||||
|
graph[dependent] = new List<string>();
|
||||||
|
}
|
||||||
|
graph[key].Add(dependent);
|
||||||
|
|
||||||
|
// 更新入度
|
||||||
|
if (!indegree.ContainsKey(dependent))
|
||||||
|
{
|
||||||
|
indegree[dependent] = 0;
|
||||||
|
}
|
||||||
|
indegree[dependent]++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!indegree.ContainsKey(key))
|
||||||
|
{
|
||||||
|
indegree[key] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 拓扑排序
|
||||||
|
var creationOrder = new List<string>();
|
||||||
|
var queue = new Queue<string>(indegree.Where(x => x.Value == 0).Select(x => x.Key));
|
||||||
|
|
||||||
|
while (queue.Count > 0)
|
||||||
|
{
|
||||||
|
var current = queue.Dequeue();
|
||||||
|
creationOrder.Add(current);
|
||||||
|
|
||||||
|
foreach (var neighbor in graph[current])
|
||||||
|
{
|
||||||
|
indegree[neighbor]--;
|
||||||
|
if (indegree[neighbor] == 0)
|
||||||
|
{
|
||||||
|
queue.Enqueue(neighbor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return creationOrder;
|
||||||
|
}
|
||||||
|
|
||||||
|
public object CreateInstance(string typeName)
|
||||||
|
{
|
||||||
|
if (_typeMappings.TryGetValue(typeName, out var type))
|
||||||
|
{
|
||||||
|
var constructor = GetConstructorWithMostParameters(type);
|
||||||
|
var parameters = constructor.GetParameters();
|
||||||
|
var args = new object[parameters.Length];
|
||||||
|
|
||||||
|
|
||||||
|
for (int i = 0; i < parameters.Length; i++)
|
||||||
|
{
|
||||||
|
var fullName = parameters[i].ParameterType.FullName;
|
||||||
|
if (!_dependencies.TryGetValue(fullName, out var argObj))
|
||||||
|
{
|
||||||
|
argObj = CreateInstance(parameters[i].ParameterType.FullName);
|
||||||
|
}
|
||||||
|
args[i] = argObj;
|
||||||
|
}
|
||||||
|
var value = Activator.CreateInstance(type, args);
|
||||||
|
_dependencies[typeName] = value;
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public bool Build()
|
public bool Build()
|
||||||
{
|
{
|
||||||
InitRegister();
|
var dependencyTree = BuildDependencyTree();
|
||||||
var graph = new Dictionary<string, List<Type>>();
|
var creationOrder = GetCreationOrder(dependencyTree);
|
||||||
//var graph = new Dictionary<string, List<string>>();
|
|
||||||
|
|
||||||
// 构建依赖关系图
|
// 输出创建顺序
|
||||||
foreach (var type in _typeMappings.Values)
|
Debug.WriteLine("创建顺序: " + string.Join(" → ", creationOrder));
|
||||||
|
|
||||||
|
// 创建对象
|
||||||
|
foreach (var typeName in creationOrder)
|
||||||
{
|
{
|
||||||
var constructor = type.GetConstructors()
|
var value = CreateInstance(typeName);
|
||||||
.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<Type>();
|
|
||||||
}
|
|
||||||
graph[paramTypeName].Add(type); // 使用 Type 而不是字符串
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
_typeMappings.Clear();
|
||||||
// 执行拓扑排序
|
|
||||||
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;
|
return true;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 执行拓扑排序
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="graph"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
private List<Type> TopologicalSort(Dictionary<string, List<Type>> graph)
|
|
||||||
{
|
|
||||||
var sorted = new List<Type>();
|
|
||||||
var visited = new HashSet<string>();
|
|
||||||
|
|
||||||
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
|
#endregion
|
||||||
|
|
||||||
#region 私有方法
|
#region 私有方法
|
||||||
@@ -380,19 +347,6 @@ namespace Serein.Library.Utils
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 创建实例时,尝试注入到由ioc容器管理、并需要此实例的对象。
|
|
||||||
/// </summary>
|
|
||||||
private object CreateInstance(Type 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)
|
private object ResolveDependency(Type parameterType)
|
||||||
{
|
{
|
||||||
var obj = Get(parameterType);
|
var obj = Get(parameterType);
|
||||||
@@ -459,55 +413,16 @@ namespace Serein.Library.Utils
|
|||||||
return isPass;
|
return isPass;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 再次尝试注入目标实例的依赖项
|
|
||||||
/// </summary>
|
|
||||||
//private void TryInstantiateWaitingDependencies()
|
|
||||||
//{
|
|
||||||
// foreach (var waitingType in _waitingForInstantiation.ToList())
|
|
||||||
// {
|
|
||||||
// if (_typeMappings.TryGetValue(waitingType.FullName, out var implementationType))
|
|
||||||
// {
|
|
||||||
// var instance = Instantiate(implementationType);
|
|
||||||
// if (instance != null)
|
|
||||||
// {
|
|
||||||
|
|
||||||
// _dependencies[waitingType.FullName] = instance;
|
|
||||||
|
|
||||||
// _waitingForInstantiation.Remove(waitingType);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region run()
|
|
||||||
//public bool Run<T>(string name, Action<T> action)
|
|
||||||
//{
|
|
||||||
// var obj = Get(name);
|
|
||||||
// if (obj != null)
|
|
||||||
// {
|
|
||||||
// if(obj is T service)
|
|
||||||
// {
|
|
||||||
// try
|
|
||||||
// {
|
|
||||||
// action(service);
|
|
||||||
// }
|
|
||||||
// catch (Exception ex)
|
|
||||||
// {
|
|
||||||
// Console.WriteLine(ex.Message);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// return this;
|
|
||||||
//}
|
|
||||||
|
|
||||||
|
|
||||||
public void Run<T>(Action<T> action)
|
public void Run<T>(Action<T> action)
|
||||||
{
|
{
|
||||||
var service = Get<T>();
|
var service = Get<T>();
|
||||||
if (service != null)
|
if (service == null)
|
||||||
|
{
|
||||||
|
throw new Exception("类型没有注册:"+typeof(T).FullName);
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
action(service);
|
action(service);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,10 +31,7 @@ namespace Serein.Library.Web
|
|||||||
{
|
{
|
||||||
private readonly ISereinIOC SereinIOC; // 用于存储路由信息
|
private readonly ISereinIOC SereinIOC; // 用于存储路由信息
|
||||||
|
|
||||||
public Router(ISereinIOC SereinIOC)
|
|
||||||
{
|
|
||||||
this.SereinIOC = SereinIOC;
|
|
||||||
}
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 控制器实例对象的类型,每次调用都会重新实例化,[Url - ControllerType]
|
/// 控制器实例对象的类型,每次调用都会重新实例化,[Url - ControllerType]
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -50,9 +47,9 @@ namespace Serein.Library.Web
|
|||||||
|
|
||||||
//private Type PostRequest;
|
//private Type PostRequest;
|
||||||
|
|
||||||
public Router()
|
public Router(ISereinIOC SereinIOC)
|
||||||
{
|
{
|
||||||
|
this.SereinIOC = SereinIOC;
|
||||||
_routes = new ConcurrentDictionary<string, ConcurrentDictionary<string, MethodInfo>>(); // 初始化路由字典
|
_routes = new ConcurrentDictionary<string, ConcurrentDictionary<string, MethodInfo>>(); // 初始化路由字典
|
||||||
_controllerTypes = new ConcurrentDictionary<string, Type>(); // 初始化控制器实例对象字典
|
_controllerTypes = new ConcurrentDictionary<string, Type>(); // 初始化控制器实例对象字典
|
||||||
foreach (API method in Enum.GetValues(typeof(API))) // 遍历 HTTP 枚举类型的所有值
|
foreach (API method in Enum.GetValues(typeof(API))) // 遍历 HTTP 枚举类型的所有值
|
||||||
|
|||||||
@@ -20,6 +20,8 @@ namespace Serein.Library.Web
|
|||||||
public WebServer(IRouter router)
|
public WebServer(IRouter router)
|
||||||
{
|
{
|
||||||
this.Router = router;
|
this.Router = router;
|
||||||
|
listener = new HttpListener();
|
||||||
|
requestLimiter = new RequestLimiter(5, 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -29,11 +31,6 @@ namespace Serein.Library.Web
|
|||||||
private HttpListener listener; // HTTP 监听器
|
private HttpListener listener; // HTTP 监听器
|
||||||
private RequestLimiter requestLimiter; //接口防刷
|
private RequestLimiter requestLimiter; //接口防刷
|
||||||
|
|
||||||
public WebServer()
|
|
||||||
{
|
|
||||||
listener = new HttpListener();
|
|
||||||
requestLimiter = new RequestLimiter(5, 8);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 启动服务器
|
// 启动服务器
|
||||||
public WebServer Start(string prefixe)
|
public WebServer Start(string prefixe)
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
using IoTClient.Clients.PLC;
|
using IoTClient;
|
||||||
|
using IoTClient.Clients.PLC;
|
||||||
|
using IoTClient.Enums;
|
||||||
using Net461DllTest.Enums;
|
using Net461DllTest.Enums;
|
||||||
using Net461DllTest.Signal;
|
using Net461DllTest.Signal;
|
||||||
using Net461DllTest.Utils;
|
|
||||||
using Serein.Library.Attributes;
|
using Serein.Library.Attributes;
|
||||||
using Serein.Library.NodeFlow.Tool;
|
using Serein.Library.NodeFlow.Tool;
|
||||||
using System;
|
using System;
|
||||||
@@ -13,7 +14,7 @@ namespace Net461DllTest.Device
|
|||||||
/// 官方文档:如果没有主动Open,则会每次读写操作的时候自动打开自动和关闭连接,这样会使读写效率大大减低。所以建议手动Open和Close。
|
/// 官方文档:如果没有主动Open,则会每次读写操作的时候自动打开自动和关闭连接,这样会使读写效率大大减低。所以建议手动Open和Close。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[AutoRegister]
|
[AutoRegister]
|
||||||
public class SiemensPlcDevice : ChannelFlowTrigger<OrderSignal>
|
public class SiemensPlcDevice : ChannelFlowTrigger<CommandSignal>
|
||||||
{
|
{
|
||||||
public SiemensClient Client { get; set; }
|
public SiemensClient Client { get; set; }
|
||||||
|
|
||||||
@@ -69,4 +70,224 @@ namespace Net461DllTest.Device
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// PLC方法
|
||||||
|
/// </summary>
|
||||||
|
public static class PlcExtension
|
||||||
|
{
|
||||||
|
public static DataTypeEnum ToDataTypeEnum(this PlcVarInfo varInfo)
|
||||||
|
{
|
||||||
|
Type dataType = varInfo.DataType;
|
||||||
|
DataTypeEnum plcDataType;
|
||||||
|
switch (dataType)
|
||||||
|
{
|
||||||
|
case Type _ when dataType == typeof(string):
|
||||||
|
plcDataType = DataTypeEnum.String;
|
||||||
|
break;
|
||||||
|
case Type _ when dataType == typeof(char):
|
||||||
|
plcDataType = DataTypeEnum.String;
|
||||||
|
break;
|
||||||
|
case Type _ when dataType == typeof(bool):
|
||||||
|
plcDataType = DataTypeEnum.Bool;
|
||||||
|
break;
|
||||||
|
case Type _ when dataType == typeof(float):
|
||||||
|
plcDataType = DataTypeEnum.Float;
|
||||||
|
break;
|
||||||
|
case Type _ when dataType == typeof(double):
|
||||||
|
plcDataType = DataTypeEnum.Double;
|
||||||
|
break;
|
||||||
|
case Type _ when dataType == typeof(byte):
|
||||||
|
plcDataType = DataTypeEnum.Byte;
|
||||||
|
break;
|
||||||
|
case Type _ when dataType == typeof(short):
|
||||||
|
plcDataType = DataTypeEnum.Int16;
|
||||||
|
break;
|
||||||
|
case Type _ when dataType == typeof(ushort):
|
||||||
|
plcDataType = DataTypeEnum.UInt16;
|
||||||
|
break;
|
||||||
|
case Type _ when dataType == typeof(int):
|
||||||
|
plcDataType = DataTypeEnum.Int32;
|
||||||
|
break;
|
||||||
|
case Type _ when dataType == typeof(uint):
|
||||||
|
plcDataType = DataTypeEnum.UInt32;
|
||||||
|
break;
|
||||||
|
case Type _ when dataType == typeof(long):
|
||||||
|
plcDataType = DataTypeEnum.Int64;
|
||||||
|
break;
|
||||||
|
case Type _ when dataType == typeof(ulong):
|
||||||
|
plcDataType = DataTypeEnum.UInt64;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
plcDataType = DataTypeEnum.None;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return plcDataType;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 读取设备的值
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="client"></param>
|
||||||
|
/// <param name="varInfo"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
/// <exception cref="Exception"></exception>
|
||||||
|
public static object ReadToPlcValue(this SiemensClient client, PlcVarInfo varInfo)
|
||||||
|
{
|
||||||
|
Type dataType = varInfo.DataType;
|
||||||
|
object resultvalue;
|
||||||
|
if (dataType == typeof(string))
|
||||||
|
{
|
||||||
|
var result = client.ReadString(varInfo.VarAddress);
|
||||||
|
if (!result.IsSucceed) throw new Exception(result.Err);
|
||||||
|
resultvalue = result.Value;
|
||||||
|
}
|
||||||
|
else if (dataType == typeof(char))
|
||||||
|
{
|
||||||
|
var result = client.ReadString(varInfo.VarAddress);
|
||||||
|
if (!result.IsSucceed) throw new Exception(result.Err);
|
||||||
|
resultvalue = result.Value;
|
||||||
|
}
|
||||||
|
else if (dataType == typeof(bool))
|
||||||
|
{
|
||||||
|
var result = client.ReadBoolean(varInfo.VarAddress);
|
||||||
|
if (!result.IsSucceed) throw new Exception(result.Err);
|
||||||
|
resultvalue = result.Value;
|
||||||
|
}
|
||||||
|
else if (dataType == typeof(float))
|
||||||
|
{
|
||||||
|
var result = client.ReadFloat(varInfo.VarAddress);
|
||||||
|
if (!result.IsSucceed) throw new Exception(result.Err);
|
||||||
|
resultvalue = result.Value;
|
||||||
|
}
|
||||||
|
else if (dataType == typeof(double))
|
||||||
|
{
|
||||||
|
var result = client.ReadDouble(varInfo.VarAddress);
|
||||||
|
if (!result.IsSucceed) throw new Exception(result.Err);
|
||||||
|
resultvalue = result.Value;
|
||||||
|
}
|
||||||
|
else if (dataType == typeof(byte))
|
||||||
|
{
|
||||||
|
var result = client.ReadByte(varInfo.VarAddress);
|
||||||
|
if (!result.IsSucceed) throw new Exception(result.Err);
|
||||||
|
resultvalue = result.Value;
|
||||||
|
}
|
||||||
|
else if (dataType == typeof(short))
|
||||||
|
{
|
||||||
|
var result = client.ReadInt16(varInfo.VarAddress);
|
||||||
|
if (!result.IsSucceed) throw new Exception(result.Err);
|
||||||
|
resultvalue = result.Value;
|
||||||
|
}
|
||||||
|
else if (dataType == typeof(ushort))
|
||||||
|
{
|
||||||
|
var result = client.ReadUInt16(varInfo.VarAddress);
|
||||||
|
if (!result.IsSucceed) throw new Exception(result.Err);
|
||||||
|
resultvalue = result.Value;
|
||||||
|
}
|
||||||
|
else if (dataType == typeof(int))
|
||||||
|
{
|
||||||
|
var result = client.ReadInt32(varInfo.VarAddress);
|
||||||
|
if (!result.IsSucceed) throw new Exception(result.Err);
|
||||||
|
resultvalue = result.Value;
|
||||||
|
}
|
||||||
|
else if (dataType == typeof(uint))
|
||||||
|
{
|
||||||
|
var result = client.ReadUInt32(varInfo.VarAddress);
|
||||||
|
if (!result.IsSucceed) throw new Exception(result.Err);
|
||||||
|
resultvalue = result.Value;
|
||||||
|
}
|
||||||
|
else if (dataType == typeof(long))
|
||||||
|
{
|
||||||
|
var result = client.ReadInt64(varInfo.VarAddress);
|
||||||
|
if (!result.IsSucceed) throw new Exception(result.Err);
|
||||||
|
resultvalue = result.Value;
|
||||||
|
}
|
||||||
|
else if (dataType == typeof(ulong))
|
||||||
|
{
|
||||||
|
var result = client.ReadUInt64(varInfo.VarAddress);
|
||||||
|
if (!result.IsSucceed) throw new Exception(result.Err);
|
||||||
|
resultvalue = result.Value;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
resultvalue = default;
|
||||||
|
}
|
||||||
|
return resultvalue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void WriteToPlcValue(this SiemensClient client, PlcVarInfo varInfo, object value)
|
||||||
|
{
|
||||||
|
if (client == null) throw new ArgumentNullException("client");
|
||||||
|
Type dataType = varInfo.DataType;
|
||||||
|
Result result = null;
|
||||||
|
if (dataType == typeof(string))
|
||||||
|
{
|
||||||
|
result = client.Write(varInfo.VarAddress, value.ToString());
|
||||||
|
}
|
||||||
|
else if (dataType == typeof(char))
|
||||||
|
{
|
||||||
|
result = client.Write(varInfo.VarAddress, value.ToString());
|
||||||
|
}
|
||||||
|
else if (dataType == typeof(bool))
|
||||||
|
{
|
||||||
|
var @bool = bool.Parse(value.ToString());
|
||||||
|
result = client.Write(varInfo.VarAddress, @bool);
|
||||||
|
}
|
||||||
|
else if (dataType == typeof(float))
|
||||||
|
{
|
||||||
|
var @float = float.Parse(value.ToString());
|
||||||
|
result = client.Write(varInfo.VarAddress, @float);
|
||||||
|
}
|
||||||
|
else if (dataType == typeof(double))
|
||||||
|
{
|
||||||
|
var @double = double.Parse(value.ToString());
|
||||||
|
result = client.Write(varInfo.VarAddress, @double);
|
||||||
|
}
|
||||||
|
else if (dataType == typeof(byte))
|
||||||
|
{
|
||||||
|
var @byte = byte.Parse(value.ToString());
|
||||||
|
result = client.Write(varInfo.VarAddress, @byte);
|
||||||
|
}
|
||||||
|
else if (dataType == typeof(short))
|
||||||
|
{
|
||||||
|
var @short = short.Parse(value.ToString());
|
||||||
|
result = client.Write(varInfo.VarAddress, @short);
|
||||||
|
}
|
||||||
|
else if (dataType == typeof(ushort))
|
||||||
|
{
|
||||||
|
var @ushort = ushort.Parse(value.ToString());
|
||||||
|
result = client.Write(varInfo.VarAddress, @ushort);
|
||||||
|
}
|
||||||
|
else if (dataType == typeof(int))
|
||||||
|
{
|
||||||
|
var @int = int.Parse(value.ToString());
|
||||||
|
result = client.Write(varInfo.VarAddress, @int);
|
||||||
|
}
|
||||||
|
else if (dataType == typeof(uint))
|
||||||
|
{
|
||||||
|
var @uint = uint.Parse(value.ToString());
|
||||||
|
result = client.Write(varInfo.VarAddress, @uint);
|
||||||
|
}
|
||||||
|
else if (dataType == typeof(long))
|
||||||
|
{
|
||||||
|
var @long = long.Parse(value.ToString());
|
||||||
|
result = client.Write(varInfo.VarAddress, @long);
|
||||||
|
}
|
||||||
|
else if (dataType == typeof(ulong))
|
||||||
|
{
|
||||||
|
var @ulong = ulong.Parse(value.ToString());
|
||||||
|
result = client.Write(varInfo.VarAddress, @ulong);
|
||||||
|
}
|
||||||
|
if (result is null)
|
||||||
|
{
|
||||||
|
throw new Exception($"未定义的数据类型");
|
||||||
|
}
|
||||||
|
if (!result.IsSucceed)
|
||||||
|
{
|
||||||
|
throw new Exception(result.Err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,18 +17,35 @@ namespace Net461DllTest.Enums
|
|||||||
public enum PlcVarEnum
|
public enum PlcVarEnum
|
||||||
{
|
{
|
||||||
None,
|
None,
|
||||||
|
/// <summary>
|
||||||
|
/// 车位号
|
||||||
|
/// </summary>
|
||||||
|
[PlcValue(typeof(short), "V100", VarType.Writable)]
|
||||||
|
SpaceNum,
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 上位机指令
|
/// 上位机指令
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[PlcValue(typeof(short), "V102", VarType.Writable)]
|
[PlcValue(typeof(short), "V102", VarType.Writable)]
|
||||||
CmdForPLC,
|
CmdForPLC,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// PLC当前存取车位号
|
||||||
|
/// </summary>
|
||||||
|
[PlcValue(typeof(short), "V110", VarType.ReadOnly)]
|
||||||
|
DoingSpaceNum,
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 下位机状态
|
/// 下位机状态
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[PlcValue(typeof(short), "V112", VarType.ReadOnly)]
|
[PlcValue(typeof(short), "V112", VarType.ReadOnly)]
|
||||||
PLCState,
|
PLCState,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 门1正常待机车位号,存车完成地面车位0
|
||||||
|
/// </summary>
|
||||||
|
[PlcValue(typeof(short), "V114", VarType.ReadOnly)]
|
||||||
|
Door1CurSpaceNum,
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 门2正常待机车位号,存车完成地面车位0
|
/// 门2正常待机车位号,存车完成地面车位0
|
||||||
@@ -73,6 +90,17 @@ namespace Net461DllTest.Enums
|
|||||||
[PlcValue(typeof(bool), "V207.4", VarType.ReadOnly)]
|
[PlcValue(typeof(bool), "V207.4", VarType.ReadOnly)]
|
||||||
IsDoor2ClosedDone,
|
IsDoor2ClosedDone,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 通道1是否有车
|
||||||
|
/// </summary>
|
||||||
|
[PlcValue(typeof(bool), "V284.7", VarType.ReadOnly)]
|
||||||
|
HasCarInTone1,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 通道2是否有车
|
||||||
|
/// </summary>
|
||||||
|
[PlcValue(typeof(bool), "V286.7", VarType.ReadOnly)]
|
||||||
|
HasCarInTone2,
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 下位机异常代码
|
/// 下位机异常代码
|
||||||
@@ -80,6 +108,12 @@ namespace Net461DllTest.Enums
|
|||||||
[PlcValue(typeof(short), "V2", VarType.ReadOnly)]
|
[PlcValue(typeof(short), "V2", VarType.ReadOnly)]
|
||||||
ErrorCode,
|
ErrorCode,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 2层以上的空板是否在待机
|
||||||
|
/// </summary>
|
||||||
|
[PlcValue(typeof(bool), "V200.7", VarType.ReadOnly)]
|
||||||
|
IsOver2FlowStanded,
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 1号门指示灯
|
/// 1号门指示灯
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -29,30 +29,43 @@ namespace Net461DllTest.LogicControl
|
|||||||
public PlcLogicControl(SiemensPlcDevice MyPlc)
|
public PlcLogicControl(SiemensPlcDevice MyPlc)
|
||||||
{
|
{
|
||||||
this.MyPlc = MyPlc;
|
this.MyPlc = MyPlc;
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#region 初始化、初始化完成以及退出的事件
|
#region 初始化、初始化完成以及退出的事件
|
||||||
[NodeAction(NodeType.Init)] // Init : 初始化事件,流程启动时执行
|
[NodeAction(NodeType.Init)] // Init : 初始化事件,流程启动时执行
|
||||||
public void Init(IDynamicContext context)
|
public void Init(IDynamicContext context)
|
||||||
{
|
{
|
||||||
// // 注册控制器
|
context.Env.IOC.Register<IRouter, Router>();
|
||||||
context.Env.IOC.Run<IRouter>(router => {
|
context.Env.IOC.Register<WebServer>();
|
||||||
router.RegisterController(typeof(ApiController));
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[NodeAction(NodeType.Loading)] // Loading 初始化完成已注入依赖项,可以开始逻辑上的操作
|
[NodeAction(NodeType.Loading)] // Loading 初始化完成已注入依赖项,可以开始逻辑上的操作
|
||||||
public void Loading(IDynamicContext context)
|
public void Loading(IDynamicContext context)
|
||||||
{
|
{
|
||||||
context.Env.IOC.Run<WebServer>((web) =>
|
// 注册控制器
|
||||||
{
|
context.Env.IOC.Run<IRouter, WebServer>((router, web) => {
|
||||||
web.Start("http://*:8089/"); // 开启 Web 服务
|
try
|
||||||
|
{
|
||||||
|
router.RegisterController(typeof(CommandController));
|
||||||
|
web.Start("http://*:8089/"); // 开启 Web 服务
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine(ex);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
[NodeAction(NodeType.Exit)] // 流程结束时自动执行
|
[NodeAction(NodeType.Exit)] // 流程结束时自动执行
|
||||||
public void Exit(IDynamicContext context)
|
public void Exit(IDynamicContext context)
|
||||||
{
|
{
|
||||||
|
context.Env.IOC.Run<WebServer>((web) =>
|
||||||
|
{
|
||||||
|
web?.Stop(); // 关闭 Web 服务
|
||||||
|
});
|
||||||
MyPlc.ResetDevice();
|
MyPlc.ResetDevice();
|
||||||
MyPlc.CancelAllTasks();
|
MyPlc.CancelAllTasks();
|
||||||
}
|
}
|
||||||
@@ -62,7 +75,7 @@ namespace Net461DllTest.LogicControl
|
|||||||
#region 触发器节点
|
#region 触发器节点
|
||||||
|
|
||||||
[NodeAction(NodeType.Flipflop, "等待信号触发", ReturnType = typeof(int))]
|
[NodeAction(NodeType.Flipflop, "等待信号触发", ReturnType = typeof(int))]
|
||||||
public async Task<IFlipflopContext> WaitTask(OrderSignal order = OrderSignal.Command_1)
|
public async Task<IFlipflopContext> WaitTask(CommandSignal order = CommandSignal.Command_1)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -113,7 +126,6 @@ namespace Net461DllTest.LogicControl
|
|||||||
return MyPlc;
|
return MyPlc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
[NodeAction(NodeType.Action, "设置PLC状态")]
|
[NodeAction(NodeType.Action, "设置PLC状态")]
|
||||||
public SiemensPlcDevice SetState(PlcState state = PlcState.PowerOff)
|
public SiemensPlcDevice SetState(PlcState state = PlcState.PowerOff)
|
||||||
{
|
{
|
||||||
@@ -129,14 +141,12 @@ namespace Net461DllTest.LogicControl
|
|||||||
Console.WriteLine($"PLC尚未初始化");
|
Console.WriteLine($"PLC尚未初始化");
|
||||||
return MyPlc;
|
return MyPlc;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// [BindConvertor(typeof(PlcVarEnum), typeof(PlcVarConvertor))]
|
|
||||||
[NodeAction(NodeType.Action, "PLC获取变量")]
|
[NodeAction(NodeType.Action, "PLC获取变量")]
|
||||||
public object ReadVar(PlcVarEnum plcVarEnum)
|
public object ReadVar(PlcVarEnum plcVarEnum)
|
||||||
{
|
{
|
||||||
var varInfo = Convertor(plcVarEnum);
|
var varInfo = ToVarInfo(plcVarEnum);
|
||||||
var result = MyPlc.Read(varInfo);
|
var result = MyPlc.Read(varInfo);
|
||||||
Console.WriteLine($"获取变量成功:({varInfo})\t result = {result}");
|
Console.WriteLine($"获取变量成功:({varInfo})\t result = {result}");
|
||||||
return result;
|
return result;
|
||||||
@@ -145,7 +155,7 @@ namespace Net461DllTest.LogicControl
|
|||||||
[NodeAction(NodeType.Action, "PLC写入变量")]
|
[NodeAction(NodeType.Action, "PLC写入变量")]
|
||||||
public SiemensPlcDevice WriteVar2(object value, PlcVarEnum plcVarEnum)
|
public SiemensPlcDevice WriteVar2(object value, PlcVarEnum plcVarEnum)
|
||||||
{
|
{
|
||||||
var varInfo = Convertor(plcVarEnum);
|
var varInfo = ToVarInfo(plcVarEnum);
|
||||||
if (MyPlc.State == PlcState.Runing)
|
if (MyPlc.State == PlcState.Runing)
|
||||||
{
|
{
|
||||||
if (varInfo.IsProtected)
|
if (varInfo.IsProtected)
|
||||||
@@ -165,9 +175,12 @@ namespace Net461DllTest.LogicControl
|
|||||||
return MyPlc;
|
return MyPlc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
private readonly Dictionary<PlcVarEnum, PlcVarInfo> VarInfoDict;
|
/// 缓存变量信息
|
||||||
public PlcVarInfo Convertor(PlcVarEnum plcVarEnum)
|
/// </summary>
|
||||||
|
private readonly Dictionary<PlcVarEnum, PlcVarInfo> VarInfoDict = new Dictionary<PlcVarEnum, PlcVarInfo>();
|
||||||
|
|
||||||
|
private PlcVarInfo ToVarInfo(PlcVarEnum plcVarEnum)
|
||||||
{
|
{
|
||||||
if (VarInfoDict.ContainsKey(plcVarEnum))
|
if (VarInfoDict.ContainsKey(plcVarEnum))
|
||||||
{
|
{
|
||||||
@@ -187,28 +200,6 @@ namespace Net461DllTest.LogicControl
|
|||||||
return plcValue;
|
return plcValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 转换器,用于将枚举转为自定义特性中的数据
|
|
||||||
/// </summary>
|
|
||||||
//public class PlcVarConvertor: IEnumConvertor<PlcVarEnum, PlcVarInfo>
|
|
||||||
//{
|
|
||||||
// public PlcVarInfo Convertor(PlcVarEnum plcVarValue)
|
|
||||||
// {
|
|
||||||
// if (plcVarValue == PlcVarEnum.None)
|
|
||||||
// {
|
|
||||||
// throw new Exception("非预期枚举值");
|
|
||||||
// }
|
|
||||||
// var plcValue = EnumHelper.GetBoundValue<PlcVarEnum, PlcValueAttribute, PlcVarInfo>(plcVarValue, attr => attr.PlcInfo)
|
|
||||||
// ?? throw new Exception($"获取变量异常:{plcVarValue},没有标记PlcValueAttribute");
|
|
||||||
// if (string.IsNullOrEmpty(plcValue.VarAddress))
|
|
||||||
// {
|
|
||||||
// throw new Exception($"获取变量异常:{plcVarValue},变量地址为空");
|
|
||||||
// }
|
|
||||||
// return plcValue;
|
|
||||||
// }
|
|
||||||
|
|
||||||
//}
|
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,19 +10,23 @@ using System.Collections.Generic;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
|
|
||||||
namespace Net461DllTest.LogicControl
|
namespace Net461DllTest.LogicControl
|
||||||
{
|
{
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 视图管理
|
||||||
|
/// </summary>
|
||||||
[AutoRegister]
|
[AutoRegister]
|
||||||
public class ViewManagement
|
public class ViewManagement
|
||||||
{
|
{
|
||||||
|
|
||||||
private List<Form> forms = new List<Form>();
|
private List<Form> forms = new List<Form>();
|
||||||
|
/// <summary>
|
||||||
|
/// 打开窗口
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="form">要打开的窗口类型</param>
|
||||||
|
/// <param name="isTop">是否置顶</param>
|
||||||
public void OpenView(Form form, bool isTop)
|
public void OpenView(Form form, bool isTop)
|
||||||
{
|
{
|
||||||
form.FormClosing += (s, e) =>
|
|
||||||
{
|
|
||||||
// 关闭窗体时执行一些关于逻辑层的操作
|
|
||||||
};
|
|
||||||
form.TopMost = isTop;
|
form.TopMost = isTop;
|
||||||
form.Show();
|
form.Show();
|
||||||
forms.Add(form);
|
forms.Add(form);
|
||||||
@@ -36,8 +40,6 @@ namespace Net461DllTest.LogicControl
|
|||||||
f.Dispose();
|
f.Dispose();
|
||||||
this.forms.Remove(f);
|
this.forms.Remove(f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -68,7 +68,7 @@
|
|||||||
<Compile Include="LogicControl\ParkingLogicControl.cs" />
|
<Compile Include="LogicControl\ParkingLogicControl.cs" />
|
||||||
<Compile Include="LogicControl\ViewLogicControl.cs" />
|
<Compile Include="LogicControl\ViewLogicControl.cs" />
|
||||||
<Compile Include="Enums\FromValue.cs" />
|
<Compile Include="Enums\FromValue.cs" />
|
||||||
<Compile Include="Signal\OrderSignal.cs" />
|
<Compile Include="Signal\CommandSignal_1.cs" />
|
||||||
<Compile Include="Signal\PLCVarSignal.cs" />
|
<Compile Include="Signal\PLCVarSignal.cs" />
|
||||||
<Compile Include="Utils\ToValue.cs" />
|
<Compile Include="Utils\ToValue.cs" />
|
||||||
<Compile Include="ViewModel\FromWorkBenchViewModel.cs" />
|
<Compile Include="ViewModel\FromWorkBenchViewModel.cs" />
|
||||||
@@ -84,7 +84,7 @@
|
|||||||
<Compile Include="View\TestFormView.Designer.cs">
|
<Compile Include="View\TestFormView.Designer.cs">
|
||||||
<DependentUpon>TestFormView.cs</DependentUpon>
|
<DependentUpon>TestFormView.cs</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
<Compile Include="Web\ApiController.cs" />
|
<Compile Include="Web\CommandController_1.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\..\..\DynamicControl\SereinFlow\Library.Framework\Serein.Library.Framework.csproj">
|
<ProjectReference Include="..\..\..\DynamicControl\SereinFlow\Library.Framework\Serein.Library.Framework.csproj">
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
namespace Net461DllTest.Signal
|
namespace Net461DllTest.Signal
|
||||||
{
|
{
|
||||||
public enum OrderSignal
|
public enum CommandSignal
|
||||||
{
|
{
|
||||||
Command_1,
|
Command_1,
|
||||||
Command_2,
|
Command_2,
|
||||||
15
Net461DllTest/Signal/CommandSignal_1.cs
Normal file
15
Net461DllTest/Signal/CommandSignal_1.cs
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
namespace Net461DllTest.Signal
|
||||||
|
{
|
||||||
|
public enum CommandSignal
|
||||||
|
{
|
||||||
|
Command_1,
|
||||||
|
Command_2,
|
||||||
|
Command_3,
|
||||||
|
Command_4,
|
||||||
|
Command_5,
|
||||||
|
Command_6,
|
||||||
|
Command_7,
|
||||||
|
Command_8,
|
||||||
|
Command_9,
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -21,7 +21,7 @@ namespace Net461DllTest
|
|||||||
|
|
||||||
public FromWorkBenchView(IFlowEnvironment env)
|
public FromWorkBenchView(IFlowEnvironment env)
|
||||||
{
|
{
|
||||||
ViewModel = env.IOC.Instantiate<FromWorkBenchViewModel>();
|
ViewModel = env.IOC.Instantiate<FromWorkBenchViewModel>(); // 创建对象并注入依赖项
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
Init();
|
Init();
|
||||||
}
|
}
|
||||||
@@ -29,7 +29,7 @@ namespace Net461DllTest
|
|||||||
public void Init()
|
public void Init()
|
||||||
{
|
{
|
||||||
listBox1.Items.Clear();
|
listBox1.Items.Clear();
|
||||||
var enumValues = Enum.GetValues(typeof(OrderSignal)).Cast<OrderSignal>();
|
var enumValues = Enum.GetValues(typeof(CommandSignal)).Cast<CommandSignal>();
|
||||||
foreach (var value in enumValues)
|
foreach (var value in enumValues)
|
||||||
{
|
{
|
||||||
listBox1.Items.Add(value.ToString());
|
listBox1.Items.Add(value.ToString());
|
||||||
@@ -49,7 +49,7 @@ namespace Net461DllTest
|
|||||||
}
|
}
|
||||||
string type = listBox1.SelectedItem.ToString();
|
string type = listBox1.SelectedItem.ToString();
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(type) && Enum.TryParse(type, out OrderSignal signal) && Enum.IsDefined(typeof(OrderSignal), signal))
|
if (!string.IsNullOrEmpty(type) && Enum.TryParse(type, out CommandSignal signal) && Enum.IsDefined(typeof(CommandSignal), signal))
|
||||||
{
|
{
|
||||||
Console.WriteLine($"Trigger : {type}");
|
Console.WriteLine($"Trigger : {type}");
|
||||||
ViewModel.Trigger(signal,textBoxSpaceNum.Text);
|
ViewModel.Trigger(signal,textBoxSpaceNum.Text);
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ namespace Net461DllTest.ViewModel
|
|||||||
return Device?.ToString();
|
return Device?.ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Trigger(OrderSignal signal,string spcaeNumber)
|
public void Trigger(CommandSignal signal,string spcaeNumber)
|
||||||
{
|
{
|
||||||
_ = Task.Run(() =>
|
_ = Task.Run(() =>
|
||||||
{
|
{
|
||||||
|
|||||||
47
Net461DllTest/Web/CommandController.cs
Normal file
47
Net461DllTest/Web/CommandController.cs
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
using Net461DllTest.Device;
|
||||||
|
using Net461DllTest.Signal;
|
||||||
|
using Serein.Library.Attributes;
|
||||||
|
using Serein.Library.Web;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Net461DllTest.Web
|
||||||
|
{
|
||||||
|
[AutoHosting]
|
||||||
|
public class CommandController : ControllerBase
|
||||||
|
{
|
||||||
|
private SiemensPlcDevice PlcDevice;
|
||||||
|
|
||||||
|
public CommandController(SiemensPlcDevice PlcDevice)
|
||||||
|
{
|
||||||
|
this.PlcDevice = PlcDevice;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 类型 :POST
|
||||||
|
* url : http://127.0.0.1:8089/command/trigger?command=
|
||||||
|
* body :[JSON]
|
||||||
|
*
|
||||||
|
* {
|
||||||
|
* "value":0,
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
[WebApi(API.POST)]
|
||||||
|
public dynamic Trigger([Url] string command, int value)
|
||||||
|
{
|
||||||
|
if (Enum.TryParse(command, out CommandSignal signal) && Enum.IsDefined(typeof(CommandSignal), signal))
|
||||||
|
{
|
||||||
|
Console.WriteLine($"外部触发 {signal} 信号,信号内容 : {value} ");
|
||||||
|
PlcDevice.TriggerSignal(signal, value);// 通过 Web Api 模拟外部输入信号
|
||||||
|
return new { state = "succeed" };
|
||||||
|
}
|
||||||
|
return new { state = "fail" };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -11,15 +11,25 @@ using System.Threading.Tasks;
|
|||||||
namespace Net461DllTest.Web
|
namespace Net461DllTest.Web
|
||||||
{
|
{
|
||||||
[AutoHosting]
|
[AutoHosting]
|
||||||
public class ApiController : ControllerBase
|
public class CommandController : ControllerBase
|
||||||
{
|
{
|
||||||
[AutoInjection]
|
[AutoInjection]
|
||||||
public SiemensPlcDevice PlcDevice { get; set; }
|
public SiemensPlcDevice PlcDevice { get; set; }
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 类型 :POST
|
||||||
|
* url : http://127.0.0.1:8089/command/trigger?command=
|
||||||
|
* body :[JSON]
|
||||||
|
*
|
||||||
|
* {
|
||||||
|
* "value":0,
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
*/
|
||||||
[WebApi(API.POST)]
|
[WebApi(API.POST)]
|
||||||
public dynamic Trigger([Url] string type, int value)
|
public dynamic Trigger([Url] string command, int value)
|
||||||
{
|
{
|
||||||
if (Enum.TryParse(type, out OrderSignal signal) && Enum.IsDefined(typeof(OrderSignal), signal))
|
if (Enum.TryParse(command, out CommandSignal signal) && Enum.IsDefined(typeof(CommandSignal), signal))
|
||||||
{
|
{
|
||||||
Console.WriteLine($"外部触发 {signal} 信号,信号内容 : {value} ");
|
Console.WriteLine($"外部触发 {signal} 信号,信号内容 : {value} ");
|
||||||
PlcDevice.TriggerSignal(signal, value);// 通过 Web Api 模拟外部输入信号
|
PlcDevice.TriggerSignal(signal, value);// 通过 Web Api 模拟外部输入信号
|
||||||
Reference in New Issue
Block a user