From d0de36fbab08b43a05e5892ba5d6f67d95e28f07 Mon Sep 17 00:00:00 2001 From: luosheng Date: Tue, 11 Apr 2023 16:35:34 +0800 Subject: [PATCH] Change machine and utility extension method --- .../{Async => Helper}/AsyncHelper.cs | 0 .../Modbus.Net/Helper/ExtendedMethodHelper.cs | 32 ++++++++++++++ .../Modbus.Net/Job/MachineJobScheduler.cs | 35 +++++++--------- .../Machine/MachineMethodReflectionCall.cs | 42 ++++++++++++++++++- .../Utility/UtilityMethodReflectionCall.cs | 41 +++++++++++++++++- 5 files changed, 127 insertions(+), 23 deletions(-) rename Modbus.Net/Modbus.Net/{Async => Helper}/AsyncHelper.cs (100%) create mode 100644 Modbus.Net/Modbus.Net/Helper/ExtendedMethodHelper.cs diff --git a/Modbus.Net/Modbus.Net/Async/AsyncHelper.cs b/Modbus.Net/Modbus.Net/Helper/AsyncHelper.cs similarity index 100% rename from Modbus.Net/Modbus.Net/Async/AsyncHelper.cs rename to Modbus.Net/Modbus.Net/Helper/AsyncHelper.cs diff --git a/Modbus.Net/Modbus.Net/Helper/ExtendedMethodHelper.cs b/Modbus.Net/Modbus.Net/Helper/ExtendedMethodHelper.cs new file mode 100644 index 0000000..9f1beed --- /dev/null +++ b/Modbus.Net/Modbus.Net/Helper/ExtendedMethodHelper.cs @@ -0,0 +1,32 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Runtime.CompilerServices; + +namespace Modbus.Net +{ + /// + /// 获取扩展方法的类 + /// + public static class ExtendedMethodHelper + { + /// + /// 获取程序集中的所有扩展方法 + /// + /// 扩展方法的第一个参数类即扩展类 + /// 程序集 + /// + public static IEnumerable 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(); + } + } +} diff --git a/Modbus.Net/Modbus.Net/Job/MachineJobScheduler.cs b/Modbus.Net/Modbus.Net/Job/MachineJobScheduler.cs index ef4032b..4e4ef05 100644 --- a/Modbus.Net/Modbus.Net/Job/MachineJobScheduler.cs +++ b/Modbus.Net/Modbus.Net/Job/MachineJobScheduler.cs @@ -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"); @@ -366,7 +360,7 @@ namespace Modbus.Net /// 处理写返回任务 /// public sealed class MachineDealJobScheduler where TMachineKey : IEquatable where TReturnUnit : struct where TMachineMethod : class, IMachineMethod - { + { private IScheduler _scheduler; private ITrigger _trigger; @@ -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>>((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>)); + var values = await (Task>>>)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>>)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)valuesSet); + MethodInfo invokeGetGenericMethod = typeof(IMachineMethod).GetExtensionMethods(GetType().Assembly).First(p => p.Name == "InvokeSet").MakeGenericMethod((Type)methodType, typeof(Dictionary)); + var success = await (Task>)invokeGetGenericMethod.Invoke(machine, new object[] { machine, new object[] { (MachineDataType)machineDataType }, (Dictionary)valuesSet }); context.JobDetail.JobDataMap.Put("Success", success); } diff --git a/Modbus.Net/Modbus.Net/Machine/MachineMethodReflectionCall.cs b/Modbus.Net/Modbus.Net/Machine/MachineMethodReflectionCall.cs index f7a77b3..be24917 100644 --- a/Modbus.Net/Modbus.Net/Machine/MachineMethodReflectionCall.cs +++ b/Modbus.Net/Modbus.Net/Machine/MachineMethodReflectionCall.cs @@ -3,11 +3,30 @@ using System.Threading.Tasks; namespace Modbus.Net { + /// /// 设备的反射调用接口 /// public static class MachineMethodReflectionCall { + /// + /// 反射方式调用获取方法 + /// + /// 方法组的类型 + /// 要返回的数据类型 + /// 方法组 + /// 参数 + /// 返回的数据 + public static Task> InvokeGet(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(machineMethod, functionName, parameters); + } + /// /// 反射方式调用获取方法 /// @@ -19,11 +38,30 @@ namespace Modbus.Net public static Task> InvokeGet(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>)ans; } + /// + /// 反射方式调用设置方法 + /// + /// 方法组的类型 + /// 要设置的数据类型 + /// 方法组 + /// 参数 + /// 要设置的数据 + /// 设置是否成功 + public static Task> InvokeSet(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); + } + /// /// 反射方式调用设置方法 /// @@ -36,7 +74,7 @@ namespace Modbus.Net public static Task> InvokeSet(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; diff --git a/Modbus.Net/Modbus.Net/Utility/UtilityMethodReflectionCall.cs b/Modbus.Net/Modbus.Net/Utility/UtilityMethodReflectionCall.cs index 088ea58..03ae572 100644 --- a/Modbus.Net/Modbus.Net/Utility/UtilityMethodReflectionCall.cs +++ b/Modbus.Net/Modbus.Net/Utility/UtilityMethodReflectionCall.cs @@ -8,6 +8,24 @@ namespace Modbus.Net /// public static class UtilityMethodReflectionCall { + /// + /// 反射方式调用获取方法 + /// + /// 方法组的类型 + /// 要返回的数据类型 + /// 方法组 + /// 参数 + /// 返回的数据 + public static Task> InvokeGet(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(utilityMethod, functionName, parameters); + } + /// /// 反射方式调用获取方法 /// @@ -19,11 +37,30 @@ namespace Modbus.Net public static Task> InvokeGet(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>)ans; } + /// + /// 反射方式调用设置方法 + /// + /// 方法组的类型 + /// 要设置的数据类型 + /// 方法组 + /// 参数 + /// 要设置的数据 + /// 设置是否成功 + public static Task> InvokeSet(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); + } + /// /// 反射方式调用设置方法 /// @@ -36,7 +73,7 @@ namespace Modbus.Net public static Task> InvokeSet(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;