Add an reflection method in machine

This commit is contained in:
luosheng
2023-03-28 19:04:50 +08:00
parent c20809c3fb
commit 1778bd59a0
8 changed files with 82 additions and 27 deletions

View File

@@ -1,7 +1,4 @@
using System; using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace Modbus.Net.Modbus.SelfDefinedSample namespace Modbus.Net.Modbus.SelfDefinedSample

View File

@@ -1,8 +1,5 @@
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using System; using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace Modbus.Net.Modbus.SelfDefinedSample namespace Modbus.Net.Modbus.SelfDefinedSample

View File

@@ -28,7 +28,7 @@ namespace Modbus.Net.Modbus
/// 读输入寄存器 /// 读输入寄存器
/// </summary> /// </summary>
ReadInputRegister = 4, ReadInputRegister = 4,
/// <summary> /// <summary>
/// 写单个线圈 /// 写单个线圈
/// </summary> /// </summary>

View File

@@ -13,7 +13,7 @@ namespace Modbus.Net
/// 设备的抽象 /// 设备的抽象
/// </summary> /// </summary>
/// <typeparam name="TKey"></typeparam> /// <typeparam name="TKey"></typeparam>
public interface IMachine<TKey> : IMachineProperty<TKey>, IMachineMethodData where TKey : IEquatable<TKey> public interface IMachine<TKey> : IMachineProperty<TKey>, IMachineMethodData, IMachineReflectionCall where TKey : IEquatable<TKey>
{ {
} }
} }

View File

@@ -0,0 +1,29 @@
using System.Threading.Tasks;
namespace Modbus.Net
{
/// <summary>
/// 设备的反射调用接口
/// </summary>
public interface IMachineReflectionCall
{
/// <summary>
/// 反射方式调用获取方法
/// </summary>
/// <typeparam name="T">要返回的数据类型</typeparam>
/// <param name="functionName">方法名</param>
/// <param name="parameters">参数</param>
/// <returns>返回的数据</returns>
Task<ReturnStruct<T>> InvokeGet<T>(string functionName, object[] parameters);
/// <summary>
/// 反射方式调用设置方法
/// </summary>
/// <typeparam name="T">要设置的数据类型</typeparam>
/// <param name="functionName">方法名</param>
/// <param name="parameters">参数</param>
/// <param name="datas">要设置的数据</param>
/// <returns>设置是否成功</returns>
Task<ReturnStruct<bool>> InvokeSet<T>(string functionName, object[] parameters, T datas);
}
}

View File

@@ -145,9 +145,10 @@ namespace Modbus.Net
/// <param name="queryId">任务ID每个触发器唯一</param> /// <param name="queryId">任务ID每个触发器唯一</param>
/// <param name="machine">要获取数据的设备实例</param> /// <param name="machine">要获取数据的设备实例</param>
/// <param name="machineDataType">获取数据的方式</param> /// <param name="machineDataType">获取数据的方式</param>
/// <param name="callFunction">调用函数的名称</param>
/// <returns></returns> /// <returns></returns>
/// <exception cref="NullReferenceException"></exception> /// <exception cref="NullReferenceException"></exception>
public async Task<MachineQueryJobScheduler> From(string queryId, IMachineMethodData machine, MachineDataType machineDataType) public async Task<MachineQueryJobScheduler> From(string queryId, IMachineReflectionCall machine, MachineDataType machineDataType, string callFunction = "Datas")
{ {
JobKey jobKey = JobKey.Create("Modbus.Net.DataQuery.Job." + queryId, "Modbus.Net.DataQuery.Group." + _trigger.Key.Name); JobKey jobKey = JobKey.Create("Modbus.Net.DataQuery.Job." + queryId, "Modbus.Net.DataQuery.Group." + _trigger.Key.Name);
@@ -158,6 +159,7 @@ namespace Modbus.Net
job.JobDataMap.Put("DataType", machineDataType); job.JobDataMap.Put("DataType", machineDataType);
job.JobDataMap.Put("Machine", machine); job.JobDataMap.Put("Machine", machine);
job.JobDataMap.Put("Function", callFunction);
if (_parentJobKey != null) if (_parentJobKey != null)
{ {
@@ -351,9 +353,10 @@ namespace Modbus.Net
/// </summary> /// </summary>
/// <param name="queryId">任务ID每个触发器唯一</param> /// <param name="queryId">任务ID每个触发器唯一</param>
/// <param name="machine">写入数据的设备实例</param> /// <param name="machine">写入数据的设备实例</param>
/// <param name="callFunction">调用函数的名称</param>
/// <returns></returns> /// <returns></returns>
/// <exception cref="NullReferenceException"></exception> /// <exception cref="NullReferenceException"></exception>
public async Task<MachineDealJobScheduler> To(string queryId, IMachineMethodData machine) public async Task<MachineDealJobScheduler> To(string queryId, IMachineReflectionCall machine, string callFunction = "Datas")
{ {
JobKey jobKey = JobKey.Create("Modbus.Net.DataQuery.Job." + queryId, "Modbus.Net.DataQuery.Group." + _trigger.Key.Name); JobKey jobKey = JobKey.Create("Modbus.Net.DataQuery.Job." + queryId, "Modbus.Net.DataQuery.Group." + _trigger.Key.Name);
@@ -363,6 +366,7 @@ namespace Modbus.Net
.Build(); .Build();
job.JobDataMap.Put("Machine", machine); job.JobDataMap.Put("Machine", machine);
job.JobDataMap.Put("Function", callFunction);
var listener = _scheduler.ListenerManager.GetJobListener("Modbus.Net.DataQuery.Chain." + _trigger.Key.Name) as JobChainingJobListenerWithDataMap; var listener = _scheduler.ListenerManager.GetJobListener("Modbus.Net.DataQuery.Chain." + _trigger.Key.Name) as JobChainingJobListenerWithDataMap;
if (listener == null) throw new NullReferenceException("Listener " + "Modbus.Net.DataQuery.Chain." + _trigger.Key.Name + " is null"); if (listener == null) throw new NullReferenceException("Listener " + "Modbus.Net.DataQuery.Chain." + _trigger.Key.Name + " is null");
@@ -379,10 +383,11 @@ namespace Modbus.Net
/// <param name="queryId">任务ID每个触发器唯一</param> /// <param name="queryId">任务ID每个触发器唯一</param>
/// <param name="machine">要获取数据的设备实例</param> /// <param name="machine">要获取数据的设备实例</param>
/// <param name="machineDataType">获取数据的方式</param> /// <param name="machineDataType">获取数据的方式</param>
/// <param name="callFunction">调用函数的名称</param>
/// <returns></returns> /// <returns></returns>
public async Task<MachineQueryJobScheduler> From(string queryId, IMachineMethodData machine, MachineDataType machineDataType) public async Task<MachineQueryJobScheduler> From(string queryId, IMachineReflectionCall machine, MachineDataType machineDataType, string callFunction = "Datas")
{ {
return await new MachineGetJobScheduler(_scheduler, _trigger, _parentJobKey).From(queryId, machine, machineDataType); return await new MachineGetJobScheduler(_scheduler, _trigger, _parentJobKey).From(queryId, machine, machineDataType, callFunction);
} }
/// <summary> /// <summary>
@@ -476,9 +481,11 @@ namespace Modbus.Net
{ {
object machine; object machine;
object machineDataType; object machineDataType;
object callFunction;
context.JobDetail.JobDataMap.TryGetValue("Machine", out machine); context.JobDetail.JobDataMap.TryGetValue("Machine", out machine);
context.JobDetail.JobDataMap.TryGetValue("DataType", out machineDataType); context.JobDetail.JobDataMap.TryGetValue("DataType", out machineDataType);
var values = await (machine as IMachineMethodData)!.GetDatasAsync((MachineDataType)machineDataType); context.JobDetail.JobDataMap.TryGetValue("Function", out callFunction);
var values = await (machine as IMachineReflectionCall)!.InvokeGet<Dictionary<string, ReturnUnit>>((string)callFunction, new object[] { (MachineDataType)machineDataType });
context.JobDetail.JobDataMap.Put("Value", values); context.JobDetail.JobDataMap.Put("Value", values);
await context.Scheduler.AddJob(context.JobDetail, true, false); await context.Scheduler.AddJob(context.JobDetail, true, false);
@@ -522,10 +529,12 @@ namespace Modbus.Net
object machineDataType; object machineDataType;
object values; object values;
object valuesSet; object valuesSet;
object callFunction;
context.JobDetail.JobDataMap.TryGetValue("Machine", out machine); context.JobDetail.JobDataMap.TryGetValue("Machine", out machine);
context.JobDetail.JobDataMap.TryGetValue("DataType", out machineDataType); context.JobDetail.JobDataMap.TryGetValue("DataType", out machineDataType);
context.JobDetail.JobDataMap.TryGetValue("Value", out values); context.JobDetail.JobDataMap.TryGetValue("Value", out values);
context.JobDetail.JobDataMap.TryGetValue("SetValue", out valuesSet); context.JobDetail.JobDataMap.TryGetValue("SetValue", out valuesSet);
context.JobDetail.JobDataMap.TryGetValue("Function", out callFunction);
if (valuesSet == null && values != null) if (valuesSet == null && values != null)
valuesSet = ((ReturnStruct<Dictionary<string, ReturnUnit>>)values).Datas.MapGetValuesToSetValues(); valuesSet = ((ReturnStruct<Dictionary<string, ReturnUnit>>)values).Datas.MapGetValuesToSetValues();
@@ -534,7 +543,7 @@ namespace Modbus.Net
context.JobDetail.JobDataMap.Put("Success", false); context.JobDetail.JobDataMap.Put("Success", false);
return; return;
} }
var success = await (machine as IMachineMethodData)!.SetDatasAsync((MachineDataType)machineDataType, (Dictionary<string, double>)valuesSet); var success = await (machine as IMachineReflectionCall)!.InvokeSet((string)callFunction, new object[] { (MachineDataType)machineDataType }, (Dictionary<string, double>)valuesSet);
context.JobDetail.JobDataMap.Put("Success", success); context.JobDetail.JobDataMap.Put("Success", success);
} }

View File

@@ -76,7 +76,7 @@ namespace Modbus.Net
/// </summary> /// </summary>
/// <typeparam name="TKey">设备的Id类型</typeparam> /// <typeparam name="TKey">设备的Id类型</typeparam>
/// <typeparam name="TUnitKey">设备中使用的AddressUnit的Id类型</typeparam> /// <typeparam name="TUnitKey">设备中使用的AddressUnit的Id类型</typeparam>
public abstract class BaseMachine<TKey, TUnitKey> : IMachine<TKey> public abstract class BaseMachine<TKey, TUnitKey> : IMachine<TKey>, IMachineReflectionCall
where TKey : IEquatable<TKey> where TKey : IEquatable<TKey>
where TUnitKey : IEquatable<TUnitKey> where TUnitKey : IEquatable<TUnitKey>
{ {
@@ -665,6 +665,39 @@ namespace Modbus.Net
return null; return null;
} }
/// <summary>
/// 获取Utility的执行方法
/// </summary>
/// <typeparam name="TUtilityMethod">Utility实现的接口名称</typeparam>
/// <returns></returns>
public TUtilityMethod GetUtilityMethods<TUtilityMethod>() where TUtilityMethod : class, IUtilityMethod
{
return BaseUtility as TUtilityMethod;
}
/// <inheritdoc />
public async Task<ReturnStruct<T>> InvokeGet<T>(string functionName, object[] parameters)
{
var machineMethodType = GetType();
var machineMethod = this as IMachineMethod;
var machineSetMethod = machineMethodType.GetMethod("Get" + functionName + "Async");
var ans = machineSetMethod.Invoke(machineMethod, parameters);
return await (Task<ReturnStruct<T>>)ans;
}
/// <inheritdoc />
public async Task<ReturnStruct<bool>> InvokeSet<T>(string functionName, object[] parameters, T datas)
{
var machineMethodType = GetType();
var machineMethod = this as IMachineMethod;
var machineSetMethod = machineMethodType.GetMethod("Set" + functionName + "Async");
object[] allParams = new object[parameters.Length + 1];
Array.Copy(parameters, allParams, parameters.Length);
allParams[parameters.Length] = datas;
var ans = machineSetMethod.Invoke(machineMethod, allParams);
return await (Task<ReturnStruct<bool>>)ans;
}
/// <summary> /// <summary>
/// 连接设备 /// 连接设备
/// </summary> /// </summary>
@@ -709,16 +742,6 @@ namespace Modbus.Net
return null; return null;
} }
} }
/// <summary>
/// 获取Utility
/// </summary>
/// <typeparam name="TUtilityMethod">Utility实现的接口名称</typeparam>
/// <returns></returns>
public TUtilityMethod GetUtility<TUtilityMethod>() where TUtilityMethod : class, IUtilityMethod
{
return BaseUtility as TUtilityMethod;
}
} }
internal class BaseMachineEqualityComparer<TKey> : IEqualityComparer<IMachineProperty<TKey>> internal class BaseMachineEqualityComparer<TKey> : IEqualityComparer<IMachineProperty<TKey>>

View File

@@ -11,7 +11,7 @@ namespace Modbus.Net.Tests
public void GetUtility() public void GetUtility()
{ {
BaseMachine<int, int> baseMachine = new ModbusMachine<int, int>(1, ModbusType.Tcp, "192.168.3.12", null, true, 2, 0); BaseMachine<int, int> baseMachine = new ModbusMachine<int, int>(1, ModbusType.Tcp, "192.168.3.12", null, true, 2, 0);
var utility = baseMachine.GetUtility<IUtilityMethodData>(); var utility = baseMachine.GetUtilityMethods<IUtilityMethodData>();
var methods = utility.GetType().GetRuntimeMethods(); var methods = utility.GetType().GetRuntimeMethods();
Assert.AreEqual(methods.FirstOrDefault(method => method.Name == "GetDataAsync") != null, true); Assert.AreEqual(methods.FirstOrDefault(method => method.Name == "GetDataAsync") != null, true);
Assert.AreEqual(methods.FirstOrDefault(method => method.Name == "SetDataAsync") != null, true); Assert.AreEqual(methods.FirstOrDefault(method => method.Name == "SetDataAsync") != null, true);
@@ -22,7 +22,7 @@ namespace Modbus.Net.Tests
public async Task InvokeUtility() public async Task InvokeUtility()
{ {
BaseMachine<int, int> baseMachine = new ModbusMachine<int, int>(1, ModbusType.Tcp, "192.168.3.12", null, true, 2, 0); BaseMachine<int, int> baseMachine = new ModbusMachine<int, int>(1, ModbusType.Tcp, "192.168.3.12", null, true, 2, 0);
var success = await baseMachine.BaseUtility.GetUtilityMethods<IUtilityMethodData>().SetDatasAsync("4X 1", new object[] {(byte)11}); var success = await baseMachine.BaseUtility.GetUtilityMethods<IUtilityMethodData>().SetDatasAsync("4X 1", new object[] { (byte)11 });
Assert.AreEqual(success, true); Assert.AreEqual(success, true);
var datas = await baseMachine.BaseUtility.GetUtilityMethods<IUtilityMethodData>().GetDatasAsync("4X 1", 1); var datas = await baseMachine.BaseUtility.GetUtilityMethods<IUtilityMethodData>().GetDatasAsync("4X 1", 1);
Assert.AreEqual(datas.Datas[0], 11); Assert.AreEqual(datas.Datas[0], 11);