Change machine and utility extension method

This commit is contained in:
luosheng
2023-04-11 16:35:34 +08:00
parent 7ae3b88eaa
commit d0de36fbab
5 changed files with 127 additions and 23 deletions

View File

@@ -0,0 +1,32 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
namespace Modbus.Net
{
/// <summary>
/// 获取扩展方法的类
/// </summary>
public static class ExtendedMethodHelper
{
/// <summary>
/// 获取程序集中的所有扩展方法
/// </summary>
/// <param name="extendedType">扩展方法的第一个参数类即扩展类</param>
/// <param name="assembly">程序集</param>
/// <returns></returns>
public static IEnumerable<MethodInfo> GetExtensionMethods(this Type extendedType, Assembly assembly)
{
var query = from type in assembly.GetTypes()
where type.IsSealed && !type.IsGenericType && !type.IsNested
from method in type.GetMethods(BindingFlags.Static
| BindingFlags.Public | BindingFlags.NonPublic)
where method.IsDefined(typeof(ExtensionAttribute), false)
where method.GetParameters()[0].ParameterType == extendedType
select method;
return query.ToList();
}
}
}

View File

@@ -3,6 +3,8 @@ using Quartz.Impl;
using Quartz.Impl.Matchers;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
namespace Modbus.Net
@@ -149,14 +151,10 @@ namespace Modbus.Net
.StoreDurably(true)
.Build();
string methodName = typeof(TMachineMethod).Name;
if (methodName.Substring(0, 14) != "IMachineMethod")
{
throw new FormatException("IMachineMethod Name not match format exception");
}
Type methodType = typeof(TMachineMethod);
job.JobDataMap.Put("DataType", machineDataType);
job.JobDataMap.Put("Machine", machine);
job.JobDataMap.Put("Function", methodName.Remove(0, 14));
job.JobDataMap.Put("MethodType", methodType);
if (_parentJobKey != null)
{
@@ -323,13 +321,9 @@ namespace Modbus.Net
.StoreDurably(true)
.Build();
string methodName = typeof(TMachineMethod).Name;
if (methodName.Substring(0, 14) != "IMachineMethod")
{
throw new FormatException("IMachineMethod Name not match format exception");
}
Type methodType = typeof(TMachineMethod);
job.JobDataMap.Put("Machine", machine);
job.JobDataMap.Put("Function", methodName.Remove(0, 14));
job.JobDataMap.Put("MethodType", methodType);
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");
@@ -429,11 +423,13 @@ namespace Modbus.Net
{
object machine;
object machineDataType;
object callFunction;
object methodType;
context.JobDetail.JobDataMap.TryGetValue("Machine", out machine);
context.JobDetail.JobDataMap.TryGetValue("DataType", out machineDataType);
context.JobDetail.JobDataMap.TryGetValue("Function", out callFunction);
var values = await (machine as IMachineMethod)!.InvokeGet<Dictionary<string, ReturnUnit<TReturnUnit>>>((string)callFunction, new object[] { (MachineDataType)machineDataType });
context.JobDetail.JobDataMap.TryGetValue("MethodType", out methodType);
MethodInfo invokeGetGenericMethod = typeof(IMachineMethod).GetExtensionMethods(GetType().Assembly).First(p => p.Name == "InvokeGet").MakeGenericMethod((Type)methodType, typeof(Dictionary<string, ReturnUnit<TReturnUnit>>));
var values = await (Task<ReturnStruct<Dictionary<string, ReturnUnit<TReturnUnit>>>>)invokeGetGenericMethod.Invoke(machine, new object[] { machine, new object[] { (MachineDataType)machineDataType } });
context.JobDetail.JobDataMap.Put("Value", values);
await context.Scheduler.AddJob(context.JobDetail, true, false);
@@ -476,12 +472,12 @@ namespace Modbus.Net
object machineDataType;
object values;
object valuesSet;
object callFunction;
object methodType;
context.JobDetail.JobDataMap.TryGetValue("Machine", out machine);
context.JobDetail.JobDataMap.TryGetValue("DataType", out machineDataType);
context.JobDetail.JobDataMap.TryGetValue("Value", out values);
context.JobDetail.JobDataMap.TryGetValue("SetValue", out valuesSet);
context.JobDetail.JobDataMap.TryGetValue("Function", out callFunction);
context.JobDetail.JobDataMap.TryGetValue("MethodType", out methodType);
if (valuesSet == null && values != null)
{
valuesSet = ((ReturnStruct<Dictionary<string, ReturnUnit<TReturnUnit>>>)values).Datas.MapGetValuesToSetValues();
@@ -492,7 +488,8 @@ namespace Modbus.Net
context.JobDetail.JobDataMap.Put("Success", false);
return;
}
var success = await (machine as IMachineMethod)!.InvokeSet((string)callFunction, new object[] { (MachineDataType)machineDataType }, (Dictionary<string, double>)valuesSet);
MethodInfo invokeGetGenericMethod = typeof(IMachineMethod).GetExtensionMethods(GetType().Assembly).First(p => p.Name == "InvokeSet").MakeGenericMethod((Type)methodType, typeof(Dictionary<string, double>));
var success = await (Task<ReturnStruct<bool>>)invokeGetGenericMethod.Invoke(machine, new object[] { machine, new object[] { (MachineDataType)machineDataType }, (Dictionary<string, double>)valuesSet });
context.JobDetail.JobDataMap.Put("Success", success);
}

View File

@@ -3,11 +3,30 @@ using System.Threading.Tasks;
namespace Modbus.Net
{
/// <summary>
/// 设备的反射调用接口
/// </summary>
public static class MachineMethodReflectionCall
{
/// <summary>
/// 反射方式调用获取方法
/// </summary>
/// <typeparam name="TMachineMethod">方法组的类型</typeparam>
/// <typeparam name="T">要返回的数据类型</typeparam>
/// <param name="machineMethod">方法组</param>
/// <param name="parameters">参数</param>
/// <returns>返回的数据</returns>
public static Task<ReturnStruct<T>> InvokeGet<TMachineMethod, T>(this IMachineMethod machineMethod, object[] parameters) where TMachineMethod : IMachineMethod
{
if (typeof(TMachineMethod).Name[..14] != "IMachineMethod")
{
throw new NotSupportedException("IMachineMethod type name not begin with IMachineMethod");
}
var functionName = "Get" + typeof(TMachineMethod).Name[14..] + "Async";
return InvokeGet<T>(machineMethod, functionName, parameters);
}
/// <summary>
/// 反射方式调用获取方法
/// </summary>
@@ -19,11 +38,30 @@ namespace Modbus.Net
public static Task<ReturnStruct<T>> InvokeGet<T>(this IMachineMethod machineMethod, string functionName, object[] parameters)
{
var machineMethodType = machineMethod.GetType();
var machineGetMethod = machineMethodType.GetMethod("Get" + functionName + "Async");
var machineGetMethod = machineMethodType.GetMethod(functionName);
var ans = machineGetMethod.Invoke(machineMethod, parameters);
return (Task<ReturnStruct<T>>)ans;
}
/// <summary>
/// 反射方式调用设置方法
/// </summary>
/// <typeparam name="TMachineMethod">方法组的类型</typeparam>
/// <typeparam name="T">要设置的数据类型</typeparam>
/// <param name="machineMethod">方法组</param>
/// <param name="parameters">参数</param>
/// <param name="datas">要设置的数据</param>
/// <returns>设置是否成功</returns>
public static Task<ReturnStruct<bool>> InvokeSet<TMachineMethod, T>(this IMachineMethod machineMethod, object[] parameters, T datas) where TMachineMethod : IMachineMethod
{
if (typeof(TMachineMethod).Name[..14] != "IMachineMethod")
{
throw new NotSupportedException("IMachineMethod type name not begin with IMachineMethod");
}
var functionName = "Set" + typeof(TMachineMethod).Name[14..] + "Async";
return InvokeSet(machineMethod, functionName, parameters, datas);
}
/// <summary>
/// 反射方式调用设置方法
/// </summary>
@@ -36,7 +74,7 @@ namespace Modbus.Net
public static Task<ReturnStruct<bool>> InvokeSet<T>(this IMachineMethod machineMethod, string functionName, object[] parameters, T datas)
{
var machineMethodType = machineMethod.GetType();
var machineSetMethod = machineMethodType.GetMethod("Set" + functionName + "Async");
var machineSetMethod = machineMethodType.GetMethod(functionName);
object[] allParams = new object[parameters.Length + 1];
Array.Copy(parameters, allParams, parameters.Length);
allParams[parameters.Length] = datas;

View File

@@ -8,6 +8,24 @@ namespace Modbus.Net
/// </summary>
public static class UtilityMethodReflectionCall
{
/// <summary>
/// 反射方式调用获取方法
/// </summary>
/// <typeparam name="TUtilityMethod">方法组的类型</typeparam>
/// <typeparam name="T">要返回的数据类型</typeparam>
/// <param name="utilityMethod">方法组</param>
/// <param name="parameters">参数</param>
/// <returns>返回的数据</returns>
public static Task<ReturnStruct<T>> InvokeGet<TUtilityMethod, T>(this IUtilityMethod utilityMethod, object[] parameters) where TUtilityMethod : IUtilityMethod
{
if (typeof(TUtilityMethod).Name[..14] != "IUtilityMethod")
{
throw new NotSupportedException("IUtilityMethod type name not begin with IUtilityMethod");
}
var functionName = "Get" + typeof(TUtilityMethod).Name[14..] + "Async";
return InvokeGet<T>(utilityMethod, functionName, parameters);
}
/// <summary>
/// 反射方式调用获取方法
/// </summary>
@@ -19,11 +37,30 @@ namespace Modbus.Net
public static Task<ReturnStruct<T>> InvokeGet<T>(this IUtilityMethod utilityMethod, string functionName, object[] parameters)
{
var utilityMethodType = utilityMethod.GetType();
var utilityGetMethod = utilityMethodType.GetMethod("Get" + functionName + "Async");
var utilityGetMethod = utilityMethodType.GetMethod(functionName);
var ans = utilityGetMethod.Invoke(utilityMethod, parameters);
return (Task<ReturnStruct<T>>)ans;
}
/// <summary>
/// 反射方式调用设置方法
/// </summary>
/// <typeparam name="TUtilityMethod">方法组的类型</typeparam>
/// <typeparam name="T">要设置的数据类型</typeparam>
/// <param name="utilityMethod">方法组</param>
/// <param name="parameters">参数</param>
/// <param name="datas">要设置的数据</param>
/// <returns>设置是否成功</returns>
public static Task<ReturnStruct<bool>> InvokeSet<TUtilityMethod, T>(this IUtilityMethod utilityMethod, object[] parameters, T datas) where TUtilityMethod : IUtilityMethod
{
if (typeof(TUtilityMethod).Name[..14] != "IUtilityMethod")
{
throw new NotSupportedException("IUtilityMethod type name not begin with IUtilityMethod");
}
var functionName = "Set" + typeof(TUtilityMethod).Name[14..] + "Async";
return InvokeSet(utilityMethod, functionName, parameters, datas);
}
/// <summary>
/// 反射方式调用设置方法
/// </summary>
@@ -36,7 +73,7 @@ namespace Modbus.Net
public static Task<ReturnStruct<bool>> InvokeSet<T>(this IUtilityMethod utilityMethod, string functionName, object[] parameters, T datas)
{
var utilityMethodType = utilityMethod.GetType();
var utilitySetMethod = utilityMethodType.GetMethod("Set" + functionName + "Async");
var utilitySetMethod = utilityMethodType.GetMethod(functionName);
object[] allParams = new object[parameters.Length + 1];
Array.Copy(parameters, allParams, parameters.Length);
allParams[parameters.Length] = datas;