IssacVIEW头像

C#标准程序

项目

ExControl

包含所有界面的控件

界面

用户界面

用户登录界面

        public static void showlogin()
        {
            ExControl.User.Form1 instance = ExControl.User.Form1.instance;
            if (instance == null)
            {
                instance = new ExControl.User.Form1();
                instance.OnUserChanged += F_OnUserChanged;
                instance.Show();
            }
            else
            {
                instance.Activate();
                instance.WindowState = FormWindowState.Normal;
            }
        }
  • 单例模式:Form1.instance 是 Form1 类内部维护的一个静态引用,保证全局只有一个登录窗口。第二次调用 showlogin() 时不会重复创建,而是激活已有窗口。在代码中有instance = this;,可以保证如果打开了,就会有记录
public Form1()
{
    try
    {
        InitializeComponent();
        instance = this;
        if (!userData.LoadDone)
        {
            userData.Readfile();
        }
        user = userData.CurrentUser;
        base.StartPosition = FormStartPosition.CenterScreen;
        base.ShowIcon = false;
        fixedWindowText = "用户管理";
        Text = fixedWindowText;
        base.MaximizeBox = false;
        setVisble();
        base.FormClosed += Form1_FormClosed;
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message);
    }
}
  • 其中base.FormClosed += Form1_FormClosed;,是父类的窗口关闭事件,意思是当窗口关闭完了之后,就要调用Form1_FormClosed
  • 默认用户:admin,密码:123a

DevExpress

BarManager

BarManager 管菜单和工具栏

DockManager

DockManager 管可停靠面板。

using DevExpress.XtraBars.Docking;
DockManager dm = new DockManager();
dm.Form = this;
DockPanel leftPanel = dm.AddPanel(DockingStyle.Left);
leftPanel.Text = "设备列表";
DockPanel rightPanel = dm.AddPanel(DockingStyle.Right);
rightPanel.Text = "相机预览";
  • 用了这个之后,就能拖曳窗口

AccessAssisstant

timer

用于刷新前面板的仪器状态

Timer timer = new Timer() { Interval = 100 };
        private void LoadDevice()
        {
            var edit = (getItem("edit")) as DevExpress.XtraBars.BarSubItem;
            if (edit != null)
            {
                var set = new DevExpress.XtraBars.BarButtonItem(BarMana, "外部设备");
                //edit.LinksPersistInfo.Add(new DevExpress.XtraBars.LinkPersistInfo(set, true));
                edit.AddItem(set);
                SetBeginGroup(edit, set);
                set.ItemClick += ItemClick;
            }
            TickDevice();
        }
  • getItem(“edit”):就是找到菜单栏的设置

类

MainTask

  1. 就是包含所有管理类,其中包括
  • CamMana
  • SQLMana
  • DeviceMana

WriteAble

  1. 继承WriteAble要重写filename
  • public override string fileName => “proxy.dat”;
  • 写用Write,例如proxy.param.Write();
[Serializable]
public abstract class WriteAble<T>
{        
    public abstract string fileName { get; }
    private static string GetFileName()
    {
      return (System.Activator.CreateInstance<T>() as WriteAble<T>).fileName;
    }
    public virtual void Write(string filePath = "")
    {
        if (filePath == null || filePath == "")
        {
            filePath = AppDomain.CurrentDomain.BaseDirectory + fileName;
        }
        if (File.Exists(filePath) == false)
        {
            DirectoryInfo infor = new DirectoryInfo(filePath);
            Directory.CreateDirectory(infor.Parent.FullName);
        }
        using (FileStream fs = new FileStream(filePath, FileMode.Create))
        {
            BinaryFormatter bf = new BinaryFormatter();              
            bf.Serialize(fs, this);
            fs.Close();
        }
    }
    public static T Read(string filePath = "")
    {
        try
        {
            if (filePath == null || filePath == "") filePath = AppDomain.CurrentDomain.BaseDirectory + GetFileName();
            using (FileStream fs = new FileStream(filePath, FileMode.Open))
            {
                BinaryFormatter bf = new BinaryFormatter();
                return (T)bf.Deserialize(fs);
            }
        }
        catch (Exception ex)
        {
            Log.print($"[{filePath}]"+ ex.Message, MsgTpye.Error);           
            return System.Activator.CreateInstance<T>();
        }           
    }
    public static T1 Read<T1>(string filePath = "")
    {
        try
        {
            if (filePath == null || filePath == "") filePath = AppDomain.CurrentDomain.BaseDirectory +
                    (System.Activator.CreateInstance<T1>() as WriteAble<T>).fileName;
            using (FileStream fs = new FileStream(filePath, FileMode.Open))
            {
                BinaryFormatter bf = new BinaryFormatter();   
                return (T1)bf.Deserialize(fs);                   
            }
        }
        catch (Exception ex)
        {
            Log.print(ex.Message, MsgTpye.Error);
            return Activator.CreateInstance<T1>();
        }
    }
}

CloneAble

public class CloneAble<T>
{
    public virtual T Clone()
    {
        System.IO.Stream stream = new System.IO.MemoryStream();
        System.Runtime.Serialization.Formatters.Binary.BinaryFormatter formatter = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
        formatter.Serialize(stream, this);
        stream.Seek(0, System.IO.SeekOrigin.Begin);
        return (T)formatter.Deserialize(stream);
    }
}

继承了这个类之后,就能得到深拷贝的副本

public class Recipe : CloneAble<Recipe>
{
    public string Name { get; set; }
    public List<string> Steps { get; set; }
}
var original = new Recipe { Name = "配方A", Steps = new List<string> { "步骤1" } };
var copy = original.Clone(); // 深拷贝
copy.Name = "配方B";         // 修改副本,不影响 original

修改 copy 不会影响 original,因为它是深拷贝,内部对象也是新创建的。

CollectionElement : CloneAble

CollectionElement 继承了 CloneAble,所以它就自动拥有了父类里的 Clone() 方法,而且返回类型正好是 CollectionElement,不需要强转。

[Serializable]
public class CollectionElement : CloneAble<CollectionElement>
  • 必须要加[Serializable],否则clone里面的序列化器会报错
    写法:
var original = new CollectionElement();
var copy = original.Clone(); // 返回 CollectionElement

原理:

public virtual T Clone()

在子类里等价于:

public virtual CollectionElement Clone()

ManaCollection

这个是管理器的父类,继承并实现了集合接口

public class ManaCollection : WriteAble<ManaCollection>, IEnumerable<CollectionElement>, ICollection<CollectionElement>
  • 是包含了CollectionElement的集合,可以使用count,add等函数
  • SetEnumableItem()函数用户设置所有可枚举类型的对象实例
public virtual void SetEnumableItem()
{}

public class DeviceMana : ManaCollection

DeviceMana设备管理类在SetEnumableItem函数,新建了所有设备类

    public class DeviceMana : ManaCollection
    {
        public override string fileName => "Device.dat";
        public DeviceMana()
        {
            SetEnumableItem();
        }
        public override void SetEnumableItem()
        {
            SetEnumableItem(new CollectionElement[] { new PLCModbus(), new HsSims(),new HsMelsecMc(),new HsOmron(),
                                 new RS232(),new NetWorkBase(),new ILSerials(),new OPTLightDevice(),new SenPum()});
        }
    }

重写设备类

  1. 两把自动扫码器

WEBAPI

  1. 设置界面
  2. 调用类

主流程

接口

IEnumerable 和 ICollection

如果一个类同时继承了 IEnumerable 和 ICollection,那它本质上就是一个 标准集合类。
接口会有实现count,add,remove,clear,contains等集合函数

能力具体作用
可遍历可以用 foreach 遍历
可 LINQ能直接用 Where、Select、FirstOrDefault 等
可计数有 Count 属性
可增删有 Add、Remove、Clear、Contains
可替换能当成 ICollection<T> 或 IEnumerable<T> 传给别的方法
可绑定很多 UI 控件、序列化、数据源只认这些标准接口

问答

  1. 继承了接口的类的子类,需不需要再实现接口的函数
    | 情况 | 子类要不要再实现 Add/Remove | 说明 |
    |—|—|—|
    | 父类已经实现了 | 不需要 | 子类直接继承父类的实现即可 |
    | 父类只声明了接口,没实现 | 必须实现 | 否则子类编译会报错,除非子类也是 abstract |
    | 子类想改行为 | 可以选择重写/隐藏/重新实现 | 取决于父类方法是不是 virtual |

写法

Device

namespace StandardKit.Kit.Equipment
{
    [Serializable]
    public class DeviceParam : CloneAble<DeviceParam>
    {      

    }
    [Serializable]
    public class Device : DeviceBase
    {         
        public DeviceParam param { get; set; }    
        public Device()
        {
           param =new DeviceParam();
        }
        public virtual DeviceResult Read()
        {
            return new DeviceResult("指定的设备无效");
        }       
        public virtual DeviceResult Write(byte[] data)
        {
            return new DeviceResult("指定的设备无效");
        }
        public virtual void WaitConnect()
        {

        }
        public DeviceResult Write(string str,string codename= "ascii")
        {
            try
            {
                byte[] arr;
                if (str == null || str == "")
                    arr = new byte[0];
                else
                    arr = Encoding.GetEncoding(codename).GetBytes(str);
                return Write(arr);
            }
            catch (Exception ex)
            {
                return new DeviceResult(ex);
            }
        }
        /// <summary>
        /// 返回字符串
        /// </summary>
        /// <returns></returns>
        public string ReadString(string incodename="ascii")
        {
            try
            {
                byte[] v = Read().Content;
                if (v != null)
                    return Encoding.GetEncoding(incodename).GetString(v);
                else
                    return "";
            }
            catch
            {
                return "";
            }
        }
        public virtual void ClearBuffer()
        {
        }
    }
}
  • 设备在继承了RS232或者NetWorkBase后,这些函数在里面就会重写,所以子类本身不要重写write,最好只调用write
  • DeviceParam : CloneAble:DeviceParam在继承了CloneAble之后,就能够创建一个副本

Scanner

  1. DeviceProperty会不会显示重写类的属性
  2. 在DeviceMan添加new Scanner()
    [Serializable]
    public class DeviceMana : ManaCollection
    {
        public override string fileName => "Device.dat";
        public DeviceMana()
        {
            SetEnumableItem();
        }
        public override void SetEnumableItem()
        {
            SetEnumableItem(new CollectionElement[] { new PLCModbus(), new HsSims(),new HsMelsecMc(),new HsOmron(),
                                 new RS232(),new NetWorkBase(),new ILSerials(),new OPTLightDevice(),new SenPum(),new Scanner()});
        }

    }
  1. 增加实体类和实体类参数
namespace StandardKit.Kit.Equipment
{
    [Serializable]
    public class ScannerParam : NetWorkParam
    {
        [Browsable(true)]
        [DisplayName("启用长度校验")]
        [Category("校验设置"), DefaultValue(false)]
        public bool enableLen { get; set; }
        [Browsable(true)]
        [DisplayName("长度")]
        [Category("校验设置"), DefaultValue(0)]
        public int codeLength { get; set; }
        [Browsable(true)]
        [DisplayName("启用关键字校验")]
        [Category("校验设置"), DefaultValue(false)]
        public bool enableKeyWord { get; set; }
        [Browsable(true)]
        [DisplayName("关键字")]
        [Category("校验设置"), DefaultValue("")]
        public string keyWord { get; set; }
    }
    [Serializable]
    public class Scanner :NetWorkBase
    {
        public Scanner() {
            param = new ScannerParam();
        }

        public override string displayText
        {
            get {
                return "扫码器";
            }
        }
        public override Image Image
        {
            get
            {
                return null;
            }
        }

        private object lockobj = new object();
        public virtual bool Scan(out string barcode)
        {
            barcode = "";
            bool result = true;
            try
            {
                lock (lockobj)
                {
                    ClearBuffer();
                    var deviceResult = Write("start\r\n");
                    if (deviceResult.isSuccess != true)
                    {
                        isConnect = false;
                        return false;
                    }
                    barcode = ReadString();
                    var scannerParam = param as ScannerParam;
                    if (scannerParam.enableLen)
                        result &= barcode.Trim().Length == scannerParam.codeLength;
                    if (scannerParam.enableKeyWord)
                        result &= barcode.Trim().ToLower().Contains(scannerParam.keyWord.ToLower());
                    barcode = barcode.Trim();   
                    return result;
                }
            }
            catch (Exception ex)
            {
                return false;
            }
        }
    }
}

数据库

SQLMana

在SetEnumableItem增加数据库类

    [Serializable]
    public class SQLMana : ManaCollection
    {
        public override string fileName { get; } = "Sql.dat";
        public SQLMana()
        {
            SetEnumableItem();
        }
        public override void SetEnumableItem()
        {
            SetEnumableItem(new CollectionElement[] { new MySQL(), new SQLServer(), new SQLite()});
        }
    }

界面

主界面

RenderBase

  1. 继承XtraUserControl

注册保存事件

在ItemClickEventHandler注册事件的时候,new hotMelt.FrameSetting()实际上是没运行的,要等到点击参数设置后,才会运行,才会注册OnSave事件

access.AddMenuItem("edit", "参数设置", new DevExpress.XtraBars.ItemClickEventHandler((s, e) =>
{
      access.documentMana.AddDocument(() => new hotMelt.FrameSetting() { hotMelt = render.hotMelt, Dock = DockStyle.Fill }, "参数设置");
}));

用户

通过ExControl.ExportClass.userMama.OnUserChanged事件来广播
ExControl.ExportClass.userMama.OnUserChanged += (s, e) =>
{
render.message.RaisEventOnUserChanged(userMama.CurentUser.UserMode, null);
};

userMama

统一注册OnUserChanged事件

namespace ExControl.ExportClass
{
    public class userMama
    {
        public static event  EventHandler OnUserChanged;
        //private static readonly string[] PowerArray = new string[] { "普通", "管理员", "超级管理员", "程序员" };
        //private static readonly Color[] Colors = new Color[] { Color.Black, Color.Green, Color.DeepPink, Color.OrangeRed };
        public userMama()
        {            

        }
        public static User.UserInfor CurentUser
        {
            get
            {
                var u = ExControl.User.userData.CurrentUser;
                return new User.UserInfor() { name = u.name, password = u.password, power = u.power, tag = u.tag 		  };
            }
        }
        public static bool CheckUser(string name, string password)
        {
            bool res;
          //  var old = CurentUser;
            if (ExControl.User.userData.LoadDone == false)
                ExControl.User.userData.Readfile();
            ExControl.User.userData.checkPassword(name, password, out res);
            return res;
        }
        public static void showlogin()
        {          
            var f = ExControl.User.Form1.instance;
            if (f == null)
            {
                f = new ExControl.User.Form1();
                f.OnUserChanged += F_OnUserChanged;
                f.Show();
            }
            else
            {
                f.Activate();
                f.WindowState = System.Windows.Forms.FormWindowState.Normal;
            }
        }
        public static void logout()
        {
            ExControl.User.userData.CurrentUser = new ExControl.User.UserInfor();
            OnUserChanged?.Invoke(null, null);
        }
        public static string[,] getAllUser()
        {
            return ExControl.User.userData.table;
        }
        public static void UpdateAllUser(string[,] table)
        {
            ExControl.User.userData.UpdateData(table);
        }
        private static void F_OnUserChanged(object sender, EventArgs e)
        {
            OnUserChanged?.Invoke(sender, e);
        }
    }
}

ManaControl

笔记

  1. 控件写在ExControl,功能写在StanardKit,主界面写在Mainpoject
  2. C# 中的 [Serializable] 特性(SerializableAttribute)不会被继承。
  • 子类必须显式标记:如果基类标记了 [Serializable],派生类不会自动获得该特性。若希望子类也可序列化,必须在子类上再次显式添加 [Serializable]。
  • C# 中特性的继承性取决于 [AttributeUsage] 的 Inherited 属性,其默认值为 true,即默认是可继承的。

转载自 CSDN-专业IT技术社区

原文链接:https://blog.csdn.net/weixin_41303851/article/details/170200922

文章来源转载

评论

评论列表

微信小程序
QQ小程序

关于作者

点赞数:0
关注数:0
粉丝:0
文章:0
关注标签:0
加入于:--