程序媛日记

程序媛日记

  1. internal修饰的类?

    internal也是一各类型/成员修饰符(被修饰的类型或者成员称为内部类型或成员),只是它所修饰的类只能在同一个程序集中被访问,而同一个程序集表示同一个dll程序集或同一个exe程序集。

  2. C#基类的重写(关键字virtual,override,abstract)

    c#支持重写实例方法和属性,但是不支持重写字段和任何静态成员,为了进行重写,需要将需要重写的成员用virtual关键字标记。在子类中使用override关键字重写。

    如果不想让一个类的成员被重写,就将这个成员用sealed修饰符修饰。

    如果我们就是想在父类中声明一些虚的成员(抽象成员),至于具体的实现都是在子类中,我们就可以将父类声明为抽象类(abstract修饰),然后在抽象类中声明抽象成员,这些抽象成员使用abstract修饰就好,或者virtual。

    这里说说一下virtual和abstract修饰的成员的区别:
    1)virtual修饰的成员比如方法必须有实现,哪怕是只有一对大括号的空实现,但是abstract修饰的成员不允许有实现;
    2)virtual修饰的成员可以被子类重写,也可以不被重写,程序不会报错,但是abstract修饰的成员一定要在子类中实现;
    3)抽象类中virtual修饰的已经在父类中实现地成员没有意义,因为抽象类无法实例化。

  3. 将xml文本快速序列化成类

    复制xml文本内容,在vs中点击编辑->选择性粘贴->将xml粘贴为类。

  4. 一个类对应一个实体时,类的构造函数应该使用private关键字修饰。

    private static Lazy<ConfigViewModel> _instance = new Lazy<ConfigViewModel>(() => new ConfigViewModel());
    public static ConfigViewModel Instance => _instance.Value;
    private ConfigViewModel()
    {
    }
    
  5. 在窗口中可以直接将写好的用户控件放在里面,不把所有的东西都放在窗口上。

    但注意:不要写页面Page,要写用户控件UserControl。

  6. 打开 文件/ 文件夹路径 选择窗口:

    //选择文件
    OpenFileDialog fileDialog = new OpenFileDialog();
    fileDialog.ShowDialog();
    fileDialog.Filter = "文本文件|*.txt"//选择的文件类型
    string fileName = fileDialog.FileName;
    
    //选择文件夹、路径
    FolderBrowserDialog folderBrowser = new FolderBrowserDialog();
    folderBrowser.ShowDialog();
    string SavePath = folderBrowser.SelectedPath;
    
  7. Dictionary字典的用法,key - value

    // 创建一个字典,将LightSource映射到相应的操作
    Dictionary<LightSource, Action> LightActions = new Dictionary<LightSource, Action> { 
    	{ LightSource.预扫, () => OpenLight(Presweep.预扫) },
        { LightSource.出料, () => OpenLight(Presweep.出料) }
        };
    // 使用字典来执行适当的操作
    if (GetDic.LightActions.ContainsKey(LightSource))
    {
        GetDic.LightActions[LightSource]();
    }
    
    
  8. xml配置文件的加载和保存

    //配置文件的加载
    public int LoadConfig()
    {
        try
        {
            string filePath = AppDomain.CurrentDomain.BaseDirectory;
            filePath += "\\Config\\AOIConfig.xml";
            var fs = new FileStream(filePath, FileMode.Open);
            var ser = new XmlSerializer(typeof(AOIConfig));
            _config = ser.Deserialize(fs) as AOIConfig;
            fs.Close();
            return 0;
        }
        catch (Exception ex)
        {
            return -1;
        }
    }
    //写入保存xml文件
    public void SaveConfig()
    {
        try
        {
            string filePath = AppDomain.CurrentDomain.BaseDirectory;
            filePath += "\\Config\\AOIConfig.xml";
            if (!File.Exists(filePath))
            {
                var fp = File.Create(filePath);
                fp.Close();
            }
    
            SerializeToXml(filePath, Config);
            HandyControl.Controls.MessageBox.Show("保存成功");
        }
        catch (Exception ex)
        {
            HandyControl.Controls.MessageBox.Show("保存失败");
        }
    }
    private void SerializeToXml<T>(string filePath, T obj)
    {
        //高级用法没看懂
        using (StreamWriter streamWriter = new StreamWriter(filePath))
            new XmlSerializer(typeof(T)).Serialize(streamWriter, obj);
    }
    
  9. 隐藏控件 Visibility=“Hidden”

  10. 串口通信,通信协议的使用和封装

    public class Light
    {
        private ILight _lightType;
        private SerialPort serial = new SerialPort();
        private AutoResetEvent _autoEvent;
        string _strRecv;
    
        public bool IsOpen => serial?.IsOpen ?? false;
        //串口通信
        public int Open(string port, int baudRate)
        {
            try
            {
                serial.PortName = port;
                serial.BaudRate = baudRate;
                serial.Open();
                if (serial.IsOpen)
                {
                    serial.DataReceived += Serial_DataReceived;
                    _autoEvent = new AutoResetEvent(false);
                }
                return 0;
            }
            catch (Exception)
            {
                return -1;
            }
        }
    
        public int Close()
        {
            try
            {
                if (IsOpen)
                {
                    serial.Close();
                    serial.DataReceived -= Serial_DataReceived;
                    _autoEvent.Close();
                }
                return 0;
            }
            catch (Exception)
            {
                return -1;
            }
        }
    
        private void Serial_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            byte[] array = new byte[serial.BytesToRead];
            int num = serial.Read(array, 0, array.Length);
            if (num > 0)
            {
                string receiveStr = Encoding.UTF8.GetString(array, 0, array.Length);
                serial.DiscardInBuffer();
                _strRecv = receiveStr;
                _autoEvent.Set();
            }
        }
    
        private int WriteAndRecv(string cmd, int timeout, out string recv)
        {
            if (IsOpen)
            {
                _autoEvent.Reset();
                serial.Write(cmd);
                if (!_autoEvent.WaitOne(timeout))
                {
                    recv = "串口返回超时";
                    return -1;
                }
                _autoEvent.Reset();
                recv = _strRecv;
            }
            else
            {
                recv = "串口未连接";
            }
            return 0;
        }
    
        public void SetLuminance(char channel, int value)
        {
            string protocol = _lightType.SetLuminance(channel, value);
            WriteAndRecv(protocol, 1000, out string recv);
        }
    
        public string GetLuminance(char channel)
        {
            string protocol = _lightType.GetLuminance(channel, 0);
            WriteAndRecv(protocol, 1000, out string recv);
            return recv;
        }
    }
    
    
    public class Light_Navitar : ILight
    {
        public string GetLuminance(char channel, int value)
        {
            //#4      读取对应通道亮度参数 成功返回亮度,失败返回&
            int ch = GetChancel(channel);
            string protocol = $"#4{ch}000";
            return protocol;
        }
    
    	//通信协议
        public string SetLuminance(char channel, int value)
        {
            if (value < 0 || value > 255)
                return "";
            //#1      打开对应通道亮度 成功返回$,失败返回&
            //#2      关闭对应通道亮度
            //#3      设置对应通道亮度参数
            int ch = GetChancel(channel);
            string protocol = $"#3{ch}0{value:X2}";
            string send = GetSend(protocol);
            return send;
        }
    
        private int GetChancel(char channel)
        {
            switch (channel)
            {
                case 'A':
                    return 1;
                case 'B':
                    return 2;
                case 'C':
                    return 3;
                case 'D':
                    return 4;
                default:
                    return 1;
            }
        }
    
        private string GetSend(string str)
        {
            int temp = 0;//校验和
            byte[] ascii = Encoding.ASCII.GetBytes(str);
            foreach (byte b in ascii) 
            {
                temp = temp ^ b;
            }
            var h = (temp & 0xf0) >> 4;
            var l = temp & 0x0f;
            string send = str + h + l;
            return send;
        }
    }
    
  11. 三方库的使用,把库放到\bin\debug目录下,在资源里添加引用即可

  12. 三目运算符:bool类型 ? bool为真返回内容 :bool为假返回内容;

    如:string s = 猪 == 八戒 ?唐僧徒弟 :其他猪;

  13. 依赖属性

public LightSource LightSource
{
    get { return (LightSource)GetValue(LightSourceProperty); }
    set { SetValue(LightSourceProperty, value); }
}

// Using a DependencyProperty as the backing store for LightSource.  This enables animation, styling, binding, etc...
public static readonly DependencyProperty LightSourceProperty =
    DependencyProperty.Register("LightSource", typeof(LightSource), typeof(LightControl1), new PropertyMetadata(null));


  1. 实现INotifyPropertyChanged接口和ICommand接口
internal class PersonViewModel :INotifyPropertyChanged
    {
        private Person _person;

        public string Name
        {
            get { return _person.Name; }
            set
            {
                _person.Name = value;
                OnPropertyChanged(nameof(Name));
            }
        }

        public int Age
        {
            get { return _person.Age; }
            set
            {
                _person.Age = value;
                OnPropertyChanged(nameof(Age));
            }
        }

        public PersonViewModel()
        {
            _person = new Person() { Name = "张三", Age = 13 };

            //将Button的Command属性绑定到ViewModel中的实现了ICommand接口的命令属性来实现按钮的命令绑定
            ShowCommand = new Command(ExecuteShowCommand, CanExecuteShowCommand);
            ChangeCommand = new Command(ExecuteChangeCommand, CanExecuteChangeCommand);
        }

        //显示当前Person的属性值
        public ICommand ShowCommand { get; set; }
        private void ExecuteShowCommand(object parameter)
        {
            // 执行命令逻辑
            MessageBox.Show($"姓名:{Name}" + $"   年龄:{Age}");
        }
        private bool CanExecuteShowCommand(object parameter)
        {
            // 确定命令是否可以执行的逻辑
            return true;
        }

        //更改Person的属性值
        public ICommand ChangeCommand { get; set; }
        private void ExecuteChangeCommand(object parameter)
        {
            // 执行命令逻辑
            Name = "刘亦菲";
            Age = 18;
        }
        private bool CanExecuteChangeCommand(object parameter)
        {
            return true;
        }

        //实现了INotifyPropertyChanged接口,于通知绑定源对象的属性值已更改
        public event PropertyChangedEventHandler PropertyChanged;
        protected virtual void OnPropertyChanged(string propertyName)
        {
            //触发事件,在又订阅者的情况下才会触发,如果有订阅者就会调用Invoke方法,将当前对象和包含属性 名称 的PropertyChangedEventArgs传递给订阅者
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }

    //实现ICommand接口
    public class Command : ICommand
    {
        private readonly Action<object> _execute;//Action委托表示将要执行的命令
        private readonly Func<object, bool> _canExecute;

        public Command(Action<object> execute, Func<object, bool> canExecute = null)
        {
            _execute = execute ?? throw new ArgumentNullException(nameof(execute));
            _canExecute = canExecute;
        }

        public event EventHandler CanExecuteChanged;

        public bool CanExecute(object parameter) => _canExecute == null || _canExecute(parameter);

        public void Execute(object parameter) => _execute(parameter);

        public void RaiseCanExecuteChanged() => CanExecuteChanged?.Invoke(this, EventArgs.Empty);
    }
  1. 字典用法

    // 创建一个字典,将LightSource映射到相应的操作
            Dictionary<LightSource, Action> LightActions = new Dictionary<LightSource, Action>
        {
            { LightSource.预扫, () => OptLightDevice.GetInstance().OpenLight(Presweep.预扫, ckbLight.IsChecked == true ? 255 : 0) },
            { LightSource.出料, () => OptLightDevice.GetInstance().OpenLight(Presweep.出料, ckbLight.IsChecked == true ? 255 : 0) },
            { LightSource.上料, () => OptLightDevice.GetInstance2().OpenLight(Monitor.上料, ckbLight.IsChecked == true ? 255 : 0) },
            { LightSource.转台, () => OptLightDevice.GetInstance2().OpenLight(Monitor.转台, ckbLight.IsChecked == true ? 255 : 0) },
            { LightSource.前端, () => LightDevice.GetInstance().OpenLight(EndDetect.前端, ckbLight.IsChecked == true ? 255 : 0) },
            { LightSource.后端, () => LightDevice.GetInstance().OpenLight(EndDetect.后端, ckbLight.IsChecked == true ? 255 : 0) },
        };
    // 使用字典来执行适当的操作
    if (GetDic.LightActions.ContainsKey(LightSource))
    {
        GetDic.LightActions[LightSource]();
    }
    
    
  2. 关于Lock:确保代码块完成运行,而不会被其他线程中断;一般有多个线程需要访问数组的时候,需要上锁

这种情况会造成死锁:

using System;
using System.Threading;

class DeadlockExample
{
    static object lock1 = new object();
    static object lock2 = new object();

    static void Main()
    {
        Thread thread1 = new Thread(Method1);
        Thread thread2 = new Thread(Method2);

        thread1.Start();
        thread2.Start();

        thread1.Join();
        thread2.Join();

        Console.WriteLine("Main thread finished.");
    }

    static void Method1()
    {
        lock (lock1)
        {
            Console.WriteLine("Method1 acquired lock1.");
            Thread.Sleep(1000);

            Console.WriteLine("Method1 trying to acquire lock2.");
            lock (lock2)
            {
                Console.WriteLine("Method1 acquired lock2.");
            }
        }
    }

    static void Method2()
    {
        lock (lock2)
        {
            Console.WriteLine("Method2 acquired lock2.");
            Thread.Sleep(1000);

            Console.WriteLine("Method2 trying to acquire lock1.");
            lock (lock1)
            {
                Console.WriteLine("Method2 acquired lock1.");
            }
        }
    }
}

  1. ToString(“X2”) 为C#中的字符串格式控制符

大写X:ToString(“X2”)即转化为大写的16进制。
小写x:ToString(“x2”)即转化为小写的16进制。
2表示每次输出两位,不足2位的前面补0,如 0x0A 如果没有2,就只会输出0xA
假设有两个数10和26,正常情况十六进制显示0xA、0x1A,这样看起来不整齐,为了好看,可以指定"X2",这样显示出来就是:0x0A、0x1A

二进制在C#中无法直接表示,我们一般用0和1的字符串来表示一个数的二进制形式,

十进制转换为二进制:

System.Convert.ToString(d, 2);// d为int类型 以4为例,输出为100

十六进制转换为二进制:

System.Convert.ToString(d, 2);// d为int类型 以0X14为例,输出为10100

二进制转换为十进制(string–>int):

System.Convert.ToInt32(s, 2);// d为string类型 以“1010”为例,输出为10

十六进制转换为十进制(string–>int、int–>int)

System.Convert.ToString(0xa,10);// 以0XA为例,输出为10

System.Convert.ToInt32(“0x41”, 16);//以"0x41"为例,输出为65

System.Int32.Parse(s, System.Globalization.NumberStyles.HexNumber);//s为string类型,以“41”为例,输出为65(注意这里的s中不能带有“0X”或者“0x”,区别于上面的方法。)

    1. Modbus协议计算CRC校验码
    #region 计算CRC校验码
    /// <summary>
    /// 计算CRC校验码,并转换为十六进制字符串
    /// Cyclic Redundancy Check 循环冗余校验码
    /// 特征是信息字段和校验字段的长度可以任意选定
    /// 此校验计算 高位在前,低位在后
    /// </summary>
    /// <returns></returns>
    public static byte[] get_CRC16_C(byte[] data)
    {
    
        byte num = 0xff;
        byte num2 = 0xff;
        byte num3 = 1;
        byte num4 = 160;
        byte[] buffer = data;
        for (int i = 0; i < buffer.Length; i++)
        {
            //位异或运算
            num = (byte)(num ^ buffer[i]);
    
            for (int j = 0; j <= 7; j++)
            {
                byte num5 = num2;
                byte num6 = num;
    
                //位右移运算
                num2 = (byte)(num2 >> 1);
                num = (byte)(num >> 1);
    
                //位与运算
                if ((num5 & 1) == 1)
                {
                    //位或运算
                    num = (byte)(num | 0x80);
                }
                if ((num6 & 1) == 1)
                {
                    num2 = (byte)(num2 ^ num4);
                    num = (byte)(num ^ num3);
                }
            }
        }
        return new byte[] { num, num2 };
        //return byteToHexStr(new byte[] { num, num2 }, 2);
    }
    
    #endregion
    
    
  1. 在程序集中无法添加资源文件
    解决办法:先卸载该程序集,在弹出的界面添加该语句:
    {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
    若不知道该添加在哪,可以卸载一个正常的程序集 ,对照添加,完成后重新加载程序集即可。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值