using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Text; using System.Threading.Tasks; namespace WCS.Core { public abstract class SystemBase: DescriptionClass { public World World { get; private set; } public SystemBase() { var attr = this.GetType().GetCustomAttribute(); var wt = typeof(World); if (attr != null) { wt = attr.WorldType; } this.World = World.Worlds.Where(v => v.GetType() == wt).First(); } public abstract List GetObjects(); public abstract void Update(List list); public void Log(string msg) { Ltc.Log(msg, LogLevel.低, ErrorType.已知); } public void Error(string msg,LogLevel level) { throw new KnownException(msg, level); } } public abstract class SystemBase : SystemBase { public List Objects { get; set; } /// /// 对所有Objects并行循环执行Do /// protected abstract bool ParallelDo { get; } /// /// 保存日志到文件 /// protected abstract bool SaveLogsToFile { get; } public SystemBase() { Objects = Create();//.Select(v=>Activator.CreateInstance(typeof(T),v)).OfType().ToList(); } public override void Update(List list) { var logs = new List(); if (ParallelDo) { Parallel.ForEach(Objects, new ParallelOptions { MaxDegreeOfParallelism = 256 }, obj => { var sw= new Stopwatch(); sw.Start(); InvokeDo(obj); sw.Stop(); list.AddSafe(new WorkTimes { Key = $"{obj?.ToString()}", Total = sw.ElapsedMilliseconds }); //var log = Ltc.GetLogStr(); logs.AddSafe(Ltc.GetLogInfo()); }); } else { foreach (var obj in Objects) { var sw = new Stopwatch(); sw.Start(); InvokeDo(obj); sw.Stop(); list.AddSafe(new WorkTimes { Key = $"{obj?.ToString()}", Total = sw.ElapsedMilliseconds }); //var log = Ltc.GetLogStr(); logs.AddSafe(Ltc.GetLogInfo()); } } if (SaveLogsToFile) { var arr = logs.GroupBy(v => v.Channel).Select(v => new LogInfo { Channel = v.Key, Level = v.Max(d => d.Level), Type = v.Any(d => d.Type == ErrorType.未知) ? ErrorType.未知 : ErrorType.已知, Message = "\n"+string.Join('\n', v.Select(d => d.Message)) }).ToArray(); Configs.OnLog?.Invoke(arr); } } void InvokeDo(T obj) { var channel = new Channel { World = World.Description, System = Description, Item = obj.ToString() }; try { Ltc.SetChannel(channel); Ltc.ClearChannel(); Ltc.Log("开始", LogLevel.低, ErrorType.已知); Do(obj); } catch (KnownException ex) { Ltc.Log(ex.Message, ex.Level, ErrorType.已知); } catch (Exception ex) { //Console.WriteLine($"{channel}:\n{ex.GetBaseException().Message}"); Ltc.Log(ex.GetBaseException().Message, LogLevel.高, ErrorType.未知); } finally { Ltc.Log("结束", LogLevel.低, ErrorType.已知); Ltc.Publish(this.World); } } public abstract List Create(); public abstract void Do(T obj); public override List GetObjects() { return Objects.OfType().ToList(); } } public abstract class DeviceSystem : SystemBase where T : EntityEx { public override List Create() { var types = typeof(T).GetGenericArguments(); var list= World.Devices.Where(v => types.All(d => v.HasProtocol(d))) .Where(v => Select(v)) .Select(v => Activator.CreateInstance(typeof(T), v)).OfType().ToList();//此时才实例化Protocol if (list.Count == 0) { Log($"{GetType().Name}系统未匹配到任何设备"); } return list; } /// /// 筛选出需要实例化Protocol的Device /// /// /// public abstract bool Select(Device dev); //public abstract List CreateDevices(); } public abstract class ServiceSystem : SystemBase { ConcurrentQueue>> Actions = new ConcurrentQueue>>(); public TR Invoke(T obj) { var flag = false; TR result = default(TR); Actions.Enqueue(list => { var sw = new Stopwatch(); sw.Start(); try { result = InvokeDo(obj); } finally { sw.Stop(); list.AddSafe(new WorkTimes { Key = $"{obj?.ToString()}", Total = sw.ElapsedMilliseconds }); flag = true; } }); SpinWait.SpinUntil(() => flag); return result; } protected abstract TR Do(T obj); public override List GetObjects() { return new List(); } public override void Update(List list) { var logs = new List(); while (Actions.TryDequeue(out var act)) { act(list); logs.AddSafe(Ltc.GetLogInfo()); } if (logs.Count > 0) { var arr = logs.GroupBy(v => v.Channel).Select(v => new LogInfo { Channel = v.Key, Level = v.Max(d => d.Level), Type = v.Any(d => d.Type == ErrorType.未知) ? ErrorType.未知 : ErrorType.已知, Message = "\n" + string.Join('\n', v.Select(d => d.Message)) }).ToArray(); Configs.OnLog?.Invoke(arr); } } TR InvokeDo(T obj) { var channel = new Channel { World = World.Description, System = Description, Item = obj.ToString() }; try { Ltc.SetChannel(channel); Ltc.ClearChannel(); Ltc.Log("开始", LogLevel.低, ErrorType.已知); return Do(obj); } catch (KnownException ex) { Ltc.Log(ex.Message, ex.Level, ErrorType.已知); throw; } catch (Exception ex) { //Console.WriteLine($"{channel}:\n{ex.GetBaseException().Message}"); Ltc.Log(ex.GetBaseException().Message, LogLevel.高, ErrorType.未知); throw; } finally { Ltc.Log("结束", LogLevel.低, ErrorType.已知); Ltc.Publish(this.World); } } } }