增强了实例工程的抽象逻辑

This commit is contained in:
fengjiayi
2024-10-07 15:15:18 +08:00
parent 7a9f7b7bf3
commit 878b1c5893
39 changed files with 1361 additions and 826 deletions

View 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;
}
}
}

View 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);
}
}
}

View File

@@ -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);
}
}
}
}