mirror of
https://gitee.com/langsisi_admin/serein-flow
synced 2026-04-05 15:56:33 +08:00
增强了实例工程的抽象逻辑
This commit is contained in:
143
Net462DllTest/Utils/GSModel.cs
Normal file
143
Net462DllTest/Utils/GSModel.cs
Normal file
@@ -0,0 +1,143 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection.Emit;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Serein.Library.Attributes;
|
||||
|
||||
namespace Net462DllTest.Utils
|
||||
{
|
||||
public interface IGSModel<TKey, TModel>
|
||||
{
|
||||
TModel Value { get; set; }
|
||||
void Set(TKey tEnum, object value);
|
||||
object Get(TKey tEnum);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 通过 Emit 创建 set/get 委托
|
||||
/// </summary>
|
||||
public class GSModel<TKey, TModel> : IGSModel<TKey, TModel>
|
||||
where TKey : struct, Enum
|
||||
where TModel : class
|
||||
{
|
||||
public TModel Value { get; set; }
|
||||
public GSModel(TModel Model)
|
||||
{
|
||||
this.Value = Model;
|
||||
}
|
||||
// 缓存创建好的setter和getter委托
|
||||
private readonly Dictionary<TKey, Action<TModel, object>> _setterCache = new Dictionary<TKey, Action<TModel, object>>();
|
||||
private readonly Dictionary<TKey, Func<TModel, object>> _getterCache = new Dictionary<TKey, Func<TModel, object>>();
|
||||
|
||||
// 动态创建调用Setter方法
|
||||
private Action<TModel, object> CreateSetter(PropertyInfo property)
|
||||
{
|
||||
var method = new DynamicMethod("Set" + property.Name, null, new[] { typeof(TModel), typeof(object) }, true);
|
||||
var il = method.GetILGenerator();
|
||||
|
||||
il.Emit(OpCodes.Ldarg_0); // 加载实例(PlcVarValue)
|
||||
il.Emit(OpCodes.Ldarg_1); // 加载值(object)
|
||||
|
||||
if (property.PropertyType.IsValueType)
|
||||
{
|
||||
il.Emit(OpCodes.Unbox_Any, property.PropertyType); // 解箱并转换为值类型
|
||||
}
|
||||
else
|
||||
{
|
||||
il.Emit(OpCodes.Castclass, property.PropertyType); // 引用类型转换
|
||||
}
|
||||
|
||||
il.Emit(OpCodes.Callvirt, property.GetSetMethod()); // 调用属性的Setter方法
|
||||
il.Emit(OpCodes.Ret); // 返回
|
||||
|
||||
return (Action<TModel, object>)method.CreateDelegate(typeof(Action<TModel, object>));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 动态创建调用Getter方法
|
||||
/// </summary>
|
||||
/// <param name="property"></param>
|
||||
/// <returns></returns>
|
||||
private Func<TModel, object> CreateGetter(PropertyInfo property)
|
||||
{
|
||||
var method = new DynamicMethod("Get" + property.Name, typeof(object), new[] { typeof(TModel) }, true);
|
||||
var il = method.GetILGenerator();
|
||||
|
||||
il.Emit(OpCodes.Ldarg_0); // 加载实例(PlcVarValue)
|
||||
il.Emit(OpCodes.Callvirt, property.GetGetMethod()); // 调用属性的Getter方法
|
||||
|
||||
if (property.PropertyType.IsValueType)
|
||||
{
|
||||
il.Emit(OpCodes.Box, property.PropertyType); // 值类型需要装箱
|
||||
}
|
||||
|
||||
il.Emit(OpCodes.Ret); // 返回
|
||||
|
||||
return (Func<TModel, object>)method.CreateDelegate(typeof(Func<TModel, object>));
|
||||
}
|
||||
|
||||
public void Set(TKey tEnum, object value)
|
||||
{
|
||||
if (!_setterCache.TryGetValue(tEnum, out var setter))
|
||||
{
|
||||
PropertyInfo property = GetPropertyByEnum(tEnum);
|
||||
if (property == null)
|
||||
{
|
||||
_setterCache[tEnum] = (s, o) => throw new ArgumentException($"没有对应的Model属性{{{tEnum}");
|
||||
//throw new ArgumentException($"Property not found for {plcVarEnum}");
|
||||
}
|
||||
else
|
||||
{
|
||||
// 创建并缓存setter委托
|
||||
setter = CreateSetter(property);
|
||||
_setterCache[tEnum] = setter;
|
||||
}
|
||||
}
|
||||
|
||||
// 使用缓存的setter委托设置值
|
||||
setter(Value, value);
|
||||
}
|
||||
|
||||
public object Get(TKey tEnum)
|
||||
{
|
||||
if (!_getterCache.TryGetValue(tEnum, out var getter))
|
||||
{
|
||||
PropertyInfo property = GetPropertyByEnum(tEnum);
|
||||
if (property == null)
|
||||
{
|
||||
_setterCache[tEnum] = (s, o) => throw new ArgumentException($"没有对应的Model属性{tEnum}");
|
||||
}
|
||||
else
|
||||
{
|
||||
// 创建并缓存getter委托
|
||||
getter = CreateGetter(property);
|
||||
_getterCache[tEnum] = getter;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// 使用缓存的getter委托获取值
|
||||
return getter(Value);
|
||||
}
|
||||
|
||||
private PropertyInfo GetPropertyByEnum(TKey tEnum)
|
||||
{
|
||||
foreach (var property in typeof(TModel).GetProperties())
|
||||
{
|
||||
var attribute = property.GetCustomAttribute<BindValueAttribute>();
|
||||
if (attribute?.Value?.GetType()?.IsEnum == true)
|
||||
{
|
||||
if (attribute.Value is TKey @enum && @enum.Equals(tEnum))
|
||||
{
|
||||
return property;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
38
Net462DllTest/Utils/RelayCommand.cs
Normal file
38
Net462DllTest/Utils/RelayCommand.cs
Normal file
@@ -0,0 +1,38 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace Net462DllTest.Utils
|
||||
{
|
||||
public class RelayCommand : ICommand
|
||||
{
|
||||
private readonly Action<object> _execute;
|
||||
private readonly Func<object,bool> _canExecute;
|
||||
|
||||
public RelayCommand(Action<object> execute, Func<object, bool> canExecute = null)
|
||||
{
|
||||
_execute = execute;
|
||||
_canExecute = canExecute;
|
||||
}
|
||||
|
||||
public event EventHandler CanExecuteChanged;
|
||||
|
||||
public bool CanExecute(object parameter = null)
|
||||
{
|
||||
return _canExecute == null || _canExecute(parameter);
|
||||
}
|
||||
|
||||
public void Execute(object parameter = null)
|
||||
{
|
||||
_execute(parameter);
|
||||
}
|
||||
|
||||
public void RaiseCanExecuteChanged()
|
||||
{
|
||||
CanExecuteChanged?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,231 +0,0 @@
|
||||
using IoTClient;
|
||||
using IoTClient.Clients.PLC;
|
||||
using IoTClient.Enums;
|
||||
using Net462DllTest.Signal;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Net462DllTest.Utils
|
||||
{
|
||||
internal static class MyPlcExtension
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user