using System.Collections; using System.Runtime.InteropServices; namespace WCS.Core { public delegate void ValueChangedHandler(PlcItem sender, T value); public delegate void ValueChangedHandler(PlcItem sender, object value); public abstract class PlcItem { protected DataBlock Db; public int Start;//按位计算 如,第2个字节,Start=8 public byte ArrayLength, StringLength; public string Id; public string Name; public string IP; public ushort DB; public Type DataType { get; private set; } /// /// 数据类型所占的字节数 /// public byte DataSize { get; private set; } public int DataSizeOfBits { get; private set; } public PlcItem(string id, string name, DataBlock db, Type type, int start, byte arrLen = 1, byte strLength = 0) { this.Id = id; this.Name = name; this.Db = db; this.DataType = type; //this.Db.DBChanged += Db_DBChanged; this.Start = start; this.ArrayLength = arrLen; this.StringLength = strLength; DataSize = (byte)GetTypeLen(DataType); DataSizeOfBits = _getBitLen(DataType); } private int GetTypeLen(Type type) { var bitLen = _getBitLen(type); var mod = bitLen % 8; if (mod > 0) bitLen += 8 - mod; return bitLen / 8; } private int _getBitLen(Type type) { if (type.IsArray) return _getBitLen(type.GetElementType()) * ArrayLength; if (type == typeof(bool)) return 1; if (type.IsEnum) return Marshal.SizeOf(type.GetEnumUnderlyingType()) * 8; if (type == typeof(string)) return (StringLength) * 8; if (typeof(IList).IsAssignableFrom(type)) return 0; return Marshal.SizeOf(type) * 8; } public object Value { get => getValue(); set => setValue(value); } protected abstract void setValue(object value); protected abstract object getValue(); private object lastValue; private bool ValueEquals(object obj1, object obj2) { if (obj1.GetType().IsArray) { var arr1 = obj1 as Array; if (obj2 is Array arr2) { return !arr1.Cast().Where((t, i) => !arr1.GetValue(i).Equals(arr2.GetValue(2))).Any(); } return true; } else { return obj1.Equals(obj2); } } } public class PlcItem : PlcItem { public PlcItem(string id, string name, DataBlock db, int start, byte arrLen = 1, byte strLen = 0) : base(id, name, db, typeof(T), start, arrLen, strLen) { } public new T Value { get => (T)base.Value; set => base.Value = value; } protected override void setValue(object value) { var i = 0; while (true) { try { Db.Write(Start, (T)value, StringLength, ArrayLength); return; } catch (Exception ex) { if (i >= 3) throw new Exception($"写入出错{ex.Message}--{Start}--{(T)value}--{StringLength}--{ArrayLength}--{Db.Entity.No}"); i++; Thread.Sleep(100); } } } protected override object getValue() { return Db.Read(Start, StringLength, ArrayLength); } } }