| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152 | using System.ComponentModel.DataAnnotations;using System.Reflection;using System.Runtime.InteropServices;namespace WCS.Core;public abstract class ProtocolProxyBase : IProtocolProxy{    public DateTime ChangedTime;    private byte[] Data = new byte[0];    public DateTime Frame;    private readonly string Id = Guid.NewGuid().ToString();    public Dictionary<string, PlcItem> Items = new();    public Type ProtocolType, ProtocolDataType;    public ProtocolProxyBase(Device dev, ProtocolInfo info, Type protocolType, World world)    {        World = world;        Frame = world.Frame;        ChangedTime = world.Frame;        Device = dev;        Info = info;        Db = info.DBInfo.Ex(world);        Db.DbChanged += Db_DbChanged;        ProtocolType = protocolType;        var bitStart = info.Position * 8; //偏移量,按位算        //this.Start = start;        //PlcDB db = new PlcDB(null, 50, 100);        var lst = GetType().GetInterfaces().ToList();        var ps = lst.SelectMany(v => v.GetProperties()).ToArray();        foreach (var p in ps)        {            if (p.GetIndexParameters().Length > 0) continue;            if (typeof(ProtocolProxyBase).GetProperty(p.Name,                    BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) != null) continue;            #region 计算偏移量            var modeNum = 0;            var t = p.PropertyType;            if (t.IsEnum)                t = t.GetEnumUnderlyingType();            if (t == typeof(bool)) //bit类型,db块中无须补齐16位                modeNum = 1;            else if (t.IsPrimitive && Marshal.SizeOf(t) == 1) //byte char 等单字节类型,db块中无须补齐16位                modeNum = 8;            else //其他类型,db块中必须补齐16位                modeNum = 16;            var mod = bitStart % modeNum;            if (mod > 0) bitStart += modeNum - mod;            #endregion 计算偏移量            byte arrlen = 0;            byte strLen = 0;            if (t.IsArray)            {                var attr =                    p.GetCustomAttributes(typeof(MaxLengthAttribute), true).FirstOrDefault() as MaxLengthAttribute;                if (attr != null)                    arrlen = (byte)attr.Length;            }            else if (p.PropertyType == typeof(string))            {                var attr =                    p.GetCustomAttributes(typeof(StringLengthAttribute), true)                        .FirstOrDefault() as StringLengthAttribute;                strLen = (byte)attr.MaximumLength;            }            var m = typeof(DataBlock).GetMethod("Regist");            m = m.MakeGenericMethod(p.PropertyType);            var item = m.Invoke(Db, new object[] { this, Id, p.Name, bitStart, arrlen, strLen }) as PlcItem;            Items.Add(p.Name, item);            bitStart += item.DataSizeOfBits;            BytesCount += item.DataSize;        }        ProtocolDataType = ProtocolType.Assembly.GetTypes().Where(v => v.IsClass || v.IsValueType)            .First(v => v.GetInterface(ProtocolType.Name) != null && v != GetType());    }    public ProtocolInfo Info { get; }    public int BytesCount { get; }    public Device Device { get; }    public World World { get; }    public DataBlock Db { get; }    public string Code => Device.Code;    private void Db_DbChanged(byte[] data)    {        var pos = Info.Position - Db.Start;        var bytes = data.Skip(pos).Take(BytesCount).ToArray();        if (Data.SequenceEqual(bytes))            return;        Frame = World.Frame;        ChangedTime = World.Frame;        Data = bytes;        DataChanged();    }    protected abstract void DataChanged();    #region    public void AddEvent(string eventName, Delegate delgate)    {        throw new NotImplementedException();    }    public void RemoveEvent(string eventName, Delegate delgate)    {        throw new NotImplementedException();    }    public T CallReturn<T>(string methodName, params object[] args)    {        throw new NotImplementedException();    }    public void CallVoid(string methodName, params object[] args)    {        throw new NotImplementedException();    }    public T Get<T>(string propertyName)    {        var item = Items[propertyName] as PlcItem<T>;        var res = item.Value;        var channel = Ltc.GetChannel();        return res;    }    public void Set<T>(string propertyName, T value)    {        var item = Items[propertyName] as PlcItem<T>;        item.Value = value;        var channel = Ltc.GetChannel();        if (channel != null)World.OnInternalLog(channel, $"设置值:设置{Device.Code}.{ProtocolType.Name}.{propertyName} 值:{value}");        Frame = World.Frame;        ChangedTime = World.Frame;        DataChanged();    }    #endregion}
 |