面向对象概念与方法
面向对象基本概念
-
对象(Object):
- 定义:对象是类的实例,是现实世界中具体事物的抽象。
- 特点:每个对象都有自己的状态(属性)和行为(方法)。
- 示例:一本书(对象),属性包括书名、作者,行为包括打开、阅读。
-
类(Class):
- 定义:类是对一类对象的抽象,是对象的模板或蓝图。
- 特点:类定义了对象的属性和行为。
- 示例:书(类),属性包括书名、作者,行为包括打开、阅读。
-
封装(Encapsulation):
- 定义:封装是将对象的状态(属性)和行为(方法)绑定在一起,并隐藏对象的内部实现细节。
- 优点:提高了代码的安全性和可维护性。
- 示例:一个类中定义私有属性,并通过公共方法访问这些属性。
-
继承(Inheritance):
- 定义:继承是一个类(子类)从另一个类(父类)继承属性和行为的机制。
- 优点:提高代码的复用性,建立类之间的关系。
- 示例:猫类(子类)继承动物类(父类)的属性和方法。
-
多态(Polymorphism):
- 定义:多态是指同一个方法在不同对象中有不同的实现。
- 优点:提高代码的灵活性和可扩展性。
- 示例:动物类有一个叫的方法,不同动物(猫、狗)有不同的叫声实现。
面向对象特征
-
封装(Encapsulation):
- 实现细节对外部隐藏,只提供必要的接口。
- 通过访问控制(如public、private、protected)来实现。
-
继承(Inheritance):
- 子类继承父类的属性和方法,子类可以扩展或重写父类的方法。
- 支持代码复用,简化代码维护。
-
多态(Polymorphism):
- 方法的重载和重写实现多态。
- 支持接口多态和继承多态。
-
抽象(Abstraction):
- 通过抽象类和接口来定义抽象概念。
- 隐藏实现细节,只提供接口。
示例代码(C#)
对象和类
public class Book
{
public string Title { get; set; }
public string Author { get; set; }
public void Open()
{
Console.WriteLine("Opening the book...");
}
public void Read()
{
Console.WriteLine("Reading the book...");
}
}
class Program
{
static void Main()
{
Book myBook = new Book();
myBook.Title = "C# Programming";
myBook.Author = "Author Name";
myBook.Open();
myBook.Read();
}
}
封装
public class Person
{
private string name;
private int age;
public string Name
{
get { return name; }
set { name = value; }
}
public int Age
{
get { return age; }
set { age = value; }
}
public void DisplayInfo()
{
Console.WriteLine($"Name: {name}, Age: {age}");
}
}
继承
public class Animal
{
public void Eat()
{
Console.WriteLine("Eating...");
}
}
public class Cat : Animal
{
public void Meow()
{
Console.WriteLine("Meowing...");
}
}
class Program
{
static void Main()
{
Cat myCat = new Cat();
myCat.Eat();
myCat.Meow();
}
}
多态
public class Animal
{
public virtual void MakeSound()
{
Console.WriteLine("Some generic animal sound");
}
}
public class Dog : Animal
{
public override void MakeSound()
{
Console.WriteLine("Bark");
}
}
public class Cat : Animal
{
public override void MakeSound()
{
Console.WriteLine("Meow");
}
}
class Program
{
static void Main()
{
Animal myDog = new Dog();
Animal myCat = new Cat();
myDog.MakeSound(); // 输出: Bark
myCat.MakeSound(); // 输出: Meow
}
}
设计模式
参考这个:https://refactoringguru.cn/design-patterns/catalog
定义
- 设计模式:是一套被反复使用、多数人知晓、经过分类编目的、代码设计经验的总结。使用设计模式是为了使代码可复用、让代码更容易被他人理解、确保代码可靠性。
分类
设计模式主要分为三大类:
-
创建型模式:
-
单例模式(Singleton Pattern):
-
确保一个类只有一个实例,并提供一个全局访问点。
-
示例代码:
public class Singleton { private static Singleton instance; private Singleton() { } public static Singleton Instance { get { if (instance == null) { instance = new Singleton(); } return instance; } } }
-
-
工厂方法模式(Factory Method Pattern):
-
定义一个用于创建对象的接口,让子类决定实例化哪一个类。
-
示例代码:
public abstract class Product { } public class ConcreteProductA : Product { } public class ConcreteProductB : Product { } public abstract class Creator { public abstract Product FactoryMethod(); } public class ConcreteCreatorA : Creator { public override Product FactoryMethod() => new ConcreteProductA(); } public class ConcreteCreatorB : Creator { public override Product FactoryMethod() => new ConcreteProductB(); }
-
-
抽象工厂模式(Abstract Factory Pattern):
-
提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。
-
示例代码:
public interface IAbstractFactory { IProductA CreateProductA(); IProductB CreateProductB(); } public interface IProductA { } public interface IProductB { } public class ConcreteFactory1 : IAbstractFactory { public IProductA CreateProductA() => new ProductA1(); public IProductB CreateProductB() => new ProductB1(); } public class ConcreteFactory2 : IAbstractFactory { public IProductA CreateProductA() => new ProductA2(); public IProductB CreateProductB() => new ProductB2(); } public class ProductA1 : IProductA { } public class ProductA2 : IProductA { } public class ProductB1 : IProductB { } public class ProductB2 : IProductB { }
-
-
-
结构型模式:
-
适配器模式(Adapter Pattern):
-
将一个类的接口转换成客户希望的另外一个接口,使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。
-
示例代码:
public interface ITarget { void Request(); } public class Adaptee { public void SpecificRequest() => Console.WriteLine("Specific request"); } public class Adapter : ITarget { private readonly Adaptee _adaptee; public Adapter(Adaptee adaptee) { _adaptee = adaptee; } public void Request() => _adaptee.SpecificRequest(); }
-
-
装饰器模式(Decorator Pattern):
-
动态地给一个对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更为灵活。
-
示例代码:
public abstract class Component { public abstract void Operation(); } public class ConcreteComponent : Component { public override void Operation() => Console.WriteLine("ConcreteComponent Operation"); } public abstract class Decorator : Component { protected Component component; public void SetComponent(Component component) { this.component = component; } public override void Operation() { if (component != null) { component.Operation(); } } } public class ConcreteDecoratorA : Decorator { public override void Operation() { base.Operation(); Console.WriteLine("ConcreteDecoratorA Operation"); } } public class ConcreteDecoratorB : Decorator { public override void Operation() { base.Operation(); AddedBehavior(); } void AddedBehavior() => Console.WriteLine("ConcreteDecoratorB AddedBehavior"); }
-
-
代理模式(Proxy Pattern):
-
为其他对象提供一种代理以控制对这个对象的访问。
-
示例代码:
public interface ISubject { void Request(); } public class RealSubject : ISubject { public void Request() => Console.WriteLine("RealSubject Request"); } public class Proxy : ISubject { private RealSubject realSubject; public void Request() { if (realSubject == null) { realSubject = new RealSubject(); } realSubject.Request(); } }
-
-
-
行为型模式:
-
观察者模式(Observer Pattern):
-
定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。
-
示例代码:
public interface IObserver { void Update(); } public class ConcreteObserver : IObserver { public void Update() => Console.WriteLine("Observer Updated"); } public interface ISubject { void Attach(IObserver observer); void Detach(IObserver observer); void Notify(); } public class ConcreteSubject : ISubject { private List
observers = new List (); public void Attach(IObserver observer) => observers.Add(observer); public void Detach(IObserver observer) => observers.Remove(observer); public void Notify() { foreach (var observer in observers) { observer.Update(); } } } -
-
策略模式(Strategy Pattern):
-
定义一系列算法,并将每个算法封装起来,使它们可以相互替换,算法的变化不会影响使用算法的客户。
-
示例代码:
public interface IStrategy { void AlgorithmInterface(); } public class ConcreteStrategyA : IStrategy { public void AlgorithmInterface() => Console.WriteLine("Algorithm A"); } public class ConcreteStrategyB : IStrategy { public void AlgorithmInterface() => Console.WriteLine("Algorithm B"); } public class Context { private IStrategy strategy; public Context(IStrategy strategy) { this.strategy = strategy; } public void ContextInterface() => strategy.AlgorithmInterface(); }
-
-
命令模式(Command Pattern):
-
将一个请求封装为一个对象,从而使你可以用不同的请求对客户进行参数化。
-
示例代码:
public interface ICommand { void Execute(); } public class ConcreteCommand : ICommand { private readonly Receiver receiver; public ConcreteCommand(Receiver receiver) { this.receiver = receiver; } public void Execute() => receiver.Action(); } public class Receiver { public void Action() => Console.WriteLine("Receiver Action"); } public class Invoker { private ICommand command; public void SetCommand(ICommand command) { this.command = command; } public void ExecuteCommand() => command.Execute(); }
-
-
串口助手的开发
开串口
private void btnOpen_Click(object sender, EventArgs e)
{
if (isOpen == false)
{
setSerialParam(cmbPortName.Text, Convert.ToInt32(cmbBaudRate.Text),
Convert.ToInt32(cmbDataBit.Text), (Parity)cmbParity.SelectedIndex,
(StopBits)cmbStopBit.SelectedIndex + 1);
serialPort1.Open();
isOpen = true;
btnOpen.Text = "关闭串口";
}
else
{
serialPort1.Close();
isOpen = false;
btnOpen.Text = "打开串口";
}
}
串口发送
private void btn_Send_Click(object sender, EventArgs e)
{
if(rtbSend != null && serialPort1.IsOpen)
{
serialPort1.Write(sendBuffer.ToArray(),0,sendBuffer.Count);
rtbReceive.SelectionColor = rtbReceive.ForeColor;
tsslSendCount.Text = Convert.ToString(sendCount);
rtbReceive.SelectionColor = Color.Green;
rtbReceive.AppendText("[Send] " + rtbSend.Text + "\n");
sendCount += sendBuffer.Count;
}
else
{
MessageBox.Show("串口未打开或发送框没有数据!");
}
}
串口接收
private static void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
{
SerialPort sp = (SerialPort)sender;
string dataReceived = sp.ReadExisting();
Console.WriteLine($"接收到数据: {dataReceived}");
}
数据大/小端模式
- 大端模式: 高字节在低地址,低字节在高地址。
- 小端模式: 高字节在高地址,低字节在低地址。一般PC使用小端模式。
数据校验方式
- 校验位: 确保数据传输的完整性和正确性。
- 校验算法:
- CRC: 循环冗余校验码,常用于数据通信。
- LRC: 纵向冗余校验,常用于工业领域。
- Checksum: 累加和校验。
- 异或校验(BCC): 高效的奇偶校验方法。
数据协议解析
- 关键: 队列的先进先出逻辑。
- 协议结构: 帧头(0xFF)+数据长度+数据+CRC。
- 示例: 数据样本 FF+04+31323334+0A30。
文件读取
- StreamReader 类: 实现一个 TextReader,使其以特定编码从字节流中读取字符。
- 命名空间: System.IO
- 操作: 文件读取和发送按钮点击响应。
文件写入
- StreamWriter 类: 实现一个 TextWriter,使其以特定编码向流中写入字符。
- 命名空间: System.IO
- 操作: 选择路径和保存数据按钮点击响应。
定时发送数据
- 操作: 添加定时器实现定时发送数据功能。
RTS/DTR/底部菜单栏
- RTS/DTR: 实现相应的功能。
- 底部状态栏: 用于显示相关状态信息。
// 打开文件
private void OpenFileButton_Click(object sender, EventArgs e)
{
OpenFileDialog openFileDialog = new OpenFileDialog();
if (openFileDialog.ShowDialog() == DialogResult.OK)
{
using (StreamReader reader = new StreamReader(openFileDialog.FileName))
{
displayTextBox.Text = reader.ReadToEnd();
}
}
}
// 写入文件
private void SaveFileButton_Click(object sender, EventArgs e)
{
SaveFileDialog saveFileDialog = new SaveFileDialog();
if (saveFileDialog.ShowDialog() == DialogResult.OK)
{
using (StreamWriter writer = new StreamWriter(saveFileDialog.FileName))
{
writer.Write(inputTextBox.Text);
}
}
}
窗口传值
内置委托、委托传参和事件传参详解
内置委托
-
Action:
-
无返回值。
-
可以有0到16个参数。
-
例子:
Action
action = (x, y) => Console.WriteLine($"Int: {x}, String: {y}"); action(10, "Hello");
-
-
Func:
-
有返回值。
-
可以有0到16个参数。
-
例子:
Func
func = (x, y) => x + y; int result = func(2, 3); Console.WriteLine(result);
-
-
Predicate:
-
返回布尔值。
-
常用于检查条件。
-
例子:
Predicate
isPositive = x => x > 0; bool result = isPositive(5); Console.WriteLine(result);
-
委托传参
-
传值方式:
-
通过直接传递具体的参数值调用委托方法。
-
例子:
delegate void MyDelegate(string message); MyDelegate del = (msg) => Console.WriteLine(msg); del("Hello, World!");
-
-
传递Lambda表达式:
-
使用Lambda表达式作为参数。
-
例子:
delegate int MathOperation(int x, int y); MathOperation add = (a, b) => a + b; int sum = add(10, 20); Console.WriteLine(sum);
-
事件传参
-
EventHandler:
-
标准事件处理委托类型,无参数。
-
例子:
public event EventHandler MyEvent; protected virtual void OnMyEvent() { MyEvent?.Invoke(this, EventArgs.Empty); }
-
-
EventHandler
: -
带泛型参数的事件处理委托类型,允许传递额外的事件数据。
-
例子:
public class MyEventArgs : EventArgs { public string Message { get; set; } } public event EventHandler
MyEvent; protected virtual void OnMyEvent(string message) { MyEvent?.Invoke(this, new MyEventArgs() { Message = message }); }
-
实例代码
内置委托实例
using System;
class Program
{
static void Main()
{
// Action 示例
Action<int, string> action = (x, y) => Console.WriteLine($"Int: {x}, String: {y}");
action(10, "Hello");
// Func 示例
Func<int, int, int> func = (x, y) => x + y;
int result = func(2, 3);
Console.WriteLine(result);
// Predicate 示例
Predicate<int> isPositive = x => x > 0;
bool isPos = isPositive(5);
Console.WriteLine(isPos);
}
}
委托传参实例
using System;
class Program
{
// 定义委托
delegate void MyDelegate(string message);
static void Main()
{
// 使用Lambda表达式赋值给委托
MyDelegate del = (msg) => Console.WriteLine(msg);
// 调用委托
del("Hello, World!");
}
}
事件传参实例
using System;
class Program
{
// 自定义事件数据
public class MyEventArgs : EventArgs
{
public string Message { get; set; }
}
// 定义事件
public event EventHandler<MyEventArgs> MyEvent;
protected virtual void OnMyEvent(string message)
{
MyEvent?.Invoke(this, new MyEventArgs() { Message = message });
}
static void Main()
{
Program program = new Program();
// 订阅事件
program.MyEvent += Program_MyEvent;
// 触发事件
program.OnMyEvent("Hello from event!");
}
private static void Program_MyEvent(object sender, MyEventArgs e)
{
// 处理事件
Console.WriteLine(e.Message);
}
}
数据绘图
1. Chart控件
概述
- Chart控件是Winform .Net Framework 4自带的控件,用于绘制曲线图、柱状图等各种类型的图表。
- 在任何给定的图表中,内部绘图位置是x轴和y轴线内的矩形区域,其中绘制了数据点。
属性
- ChartAreas: 可以添加多个ChartAreas,代表作图区域,默认有一个ChartAreas[0]。
- Series: 每个ChartAreas中可以有多个Series,Series是一些列点(Points)的集合,这些点与X轴和Y轴构成了图表。
示例代码
using System;
using System.Windows.Forms;
using System.Windows.Forms.DataVisualization.Charting;
public class ChartExample : Form
{
private Chart chart;
public ChartExample()
{
chart = new Chart();
chart.Dock = DockStyle.Fill;
this.Controls.Add(chart);
ChartArea chartArea = new ChartArea();
chart.ChartAreas.Add(chartArea);
Series series = new Series();
series.ChartType = SeriesChartType.Line;
series.Points.AddXY(1, 10);
series.Points.AddXY(2, 20);
series.Points.AddXY(3, 30);
chart.Series.Add(series);
}
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.Run(new ChartExample());
}
}
2. 静态绘图
概述
- 静态绘图是在图表中绘制不随时间变化的静态数据,一般用于显示历史数据或一次性数据。
示例代码
public void PlotStaticData(Chart chart)
{
Series series = new Series();
series.ChartType = SeriesChartType.Bar;
series.Points.AddXY("A", 10);
series.Points.AddXY("B", 20);
series.Points.AddXY("C", 30);
chart.Series.Add(series);
}
3. 动态绘图
概述
- 动态绘图是在图表中绘制实时更新的数据,常用于显示传感器数据、股票行情等。
示例代码
using System;
using System.Timers;
using System.Windows.Forms;
using System.Windows.Forms.DataVisualization.Charting;
public class DynamicChartExample : Form
{
private Chart chart;
private Timer timer;
private Random random = new Random();
private int xValue = 0;
public DynamicChartExample()
{
chart = new Chart();
chart.Dock = DockStyle.Fill;
this.Controls.Add(chart);
ChartArea chartArea = new ChartArea();
chart.ChartAreas.Add(chartArea);
Series series = new Series();
series.ChartType = SeriesChartType.Line;
chart.Series.Add(series);
timer = new Timer();
timer.Interval = 1000; // 每秒更新一次
timer.Elapsed += Timer_Elapsed;
timer.Start();
}
private void Timer_Elapsed(object sender, ElapsedEventArgs e)
{
if (chart.InvokeRequired)
{
chart.Invoke(new Action(() => UpdateChart()));
}
else
{
UpdateChart();
}
}
private void UpdateChart()
{
xValue++;
int yValue = random.Next(0, 100);
chart.Series[0].Points.AddXY(xValue, yValue);
if (chart.Series[0].Points.Count > 20)
{
chart.Series[0].Points.RemoveAt(0); // 保持图表数据点数量不超过20
}
chart.ChartAreas[0].RecalculateAxesScale(); // 自动调整坐标轴
}
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.Run(new DynamicChartExample());
}
}
串口接收数据-动态绘图
概述
- 实现通过串口接收数据并实时更新图表,实现动态绘图。
示例代码
using System;
using System.IO.Ports;
using System.Timers;
using System.Windows.Forms;
using System.Windows.Forms.DataVisualization.Charting;
public class SerialDynamicChartExample : Form
{
private Chart chart;
private Timer timer;
private SerialPort serialPort;
private int xValue = 0;
public SerialDynamicChartExample()
{
chart = new Chart();
chart.Dock = DockStyle.Fill;
this.Controls.Add(chart);
ChartArea chartArea = new ChartArea();
chart.ChartAreas.Add(chartArea);
Series series = new Series();
series.ChartType = SeriesChartType.Line;
chart.Series.Add(series);
serialPort = new SerialPort("COM1", 9600);
serialPort.DataReceived += SerialPort_DataReceived;
serialPort.Open();
timer = new Timer();
timer.Interval = 1000; // 每秒更新一次
timer.Elapsed += Timer_Elapsed;
timer.Start();
}
private void SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
string data = serialPort.ReadLine();
if (int.TryParse(data, out int yValue))
{
if (chart.InvokeRequired)
{
chart.Invoke(new Action(() => UpdateChart(yValue)));
}
else
{
UpdateChart(yValue);
}
}
}
private void Timer_Elapsed(object sender, ElapsedEventArgs e)
{
// 可以添加定时操作,这里暂时不需要
}
private void UpdateChart(int yValue)
{
xValue++;
chart.Series[0].Points.AddXY(xValue, yValue);
if (chart.Series[0].Points.Count > 20)
{
chart.Series[0].Points.RemoveAt(0); // 保持图表数据点数量不超过20
}
chart.ChartAreas[0].RecalculateAxesScale(); // 自动调整坐标轴
}
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.Run(new SerialDynamicChartExample());
}
}
接口开发概述
接口开发是指设计和实现软件组件之间的通信方式,使得不同系统或模块能够互相交换数据和功能。以下是接口开发的关键要点:
接口类型
-
RESTful API:
- 基于HTTP协议,使用标准的HTTP方法(GET, POST, PUT, DELETE)。
- 资源通过URL进行访问,通常返回JSON或XML格式的数据。
-
SOAP API:
- 基于XML的协议,使用HTTP、SMTP等传输协议。
- 强类型的契约定义,通常用于企业级应用。
-
GraphQL:
- 提供单一端点,通过查询语言灵活获取所需数据。
- 客户端可以指定需要的字段,减少数据传输量。
开发步骤
-
需求分析:
- 明确接口的功能和数据需求,确定接口的使用场景和目标用户。
-
设计接口:
- 定义接口的URL结构、请求方法、请求参数和返回格式。
- 制定接口文档,描述接口的用途、参数和示例。
-
实现接口:
- 使用服务器端语言(如Java, Python, Node.js)编写接口逻辑。
- 连接数据库或其他数据源,处理请求并返回响应。
-
测试接口:
- 使用工具(如Postman, Swagger)进行接口测试,确保功能正确。
- 检查错误处理和边界情况,确保接口的健壮性。
-
部署和维护:
- 将接口部署到服务器,并监控其性能和可用性。
- 定期更新接口,修复漏洞,满足新的需求。
RESTful API 示例
// 使用ASP.NET Core实现一个简单的RESTful API
using Microsoft.AspNetCore.Mvc;
[ApiController]
[Route("api/[controller]")]
public class ProductsController : ControllerBase
{
private static readonly List<Product> Products = new List<Product>
{
new Product { Id = 1, Name = "Product1", Price = 100 },
new Product { Id = 2, Name = "Product2", Price = 200 }
};
[HttpGet]
public IEnumerable<Product> Get() => Products;
[HttpGet("{id}")]
public ActionResult<Product> Get(int id)
{
var product = Products.FirstOrDefault(p => p.Id == id);
if (product == null)
{
return NotFound();
}
return product;
}
[HttpPost]
public ActionResult<Product> Post(Product product)
{
product.Id = Products.Max(p => p.Id) + 1;
Products.Add(product);
return CreatedAtAction(nameof(Get), new { id = product.Id }, product);
}
[HttpPut("{id}")]
public IActionResult Put(int id, Product product)
{
var existingProduct = Products.FirstOrDefault(p => p.Id == id);
if (existingProduct == null)
{
return NotFound();
}
existingProduct.Name = product.Name;
existingProduct.Price = product.Price;
return NoContent();
}
[HttpDelete("{id}")]
public IActionResult Delete(int id)
{
var product = Products.FirstOrDefault(p => p.Id == id);
if (product == null)
{
return NotFound();
}
Products.Remove(product);
return NoContent();
}
}
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
public decimal Price { get; set; }
}
XML
基本概念
- XML(Extensible Markup Language)是一种类似于HTML的标记语言,但没有预定义的标记。
- XML允许根据需求定义专属的标记,用于存储、搜索和共享数据。
- XML格式标准化,便于在不同系统或平台间传输数据。
基本语法
- 第一行通常为文档声明:
<?xml version="1.0" encoding="UTF-8"?>
- 必须有且仅有一个根标签,其他标签为子标签。
- 标签区分大小写,不能以数字或下划线开头,不能包含空格和冒号。
标签和属性
- 标签可以包含字母、数字和其他可见字符,但需遵守命名规范。
- 属性用于区分名称相同的标签,属性值必须用引号包裹。
- 实体引用用于替代特殊字符,如
>
表示>
。
CDATA
- 使用
<![CDATA[ 内容 ]]>
包裹不想被解析的内容。
xml写操作
using System.Xml;
public class XmlWriterExample
{
public void WriteXml()
{
XmlWriterSettings settings = new XmlWriterSettings();
settings.Indent = true;
using (XmlWriter writer = XmlWriter.Create("example.xml", settings))
{
writer.WriteStartDocument();
writer.WriteStartElement("root");
writer.WriteStartElement("element");
writer.WriteAttributeString("attribute", "value");
writer.WriteString("content");
writer.WriteEndElement();
writer.WriteEndElement();
writer.WriteEndDocument();
}
}
}
xml读操作
using System.Xml;
public class XmlReaderExample
{
public void ReadXml()
{
using (XmlReader reader = XmlReader.Create("example.xml"))
{
while (reader.Read())
{
if (reader.IsStartElement())
{
switch (reader.Name)
{
case "element":
string attribute = reader["attribute"];
string content = reader.ReadString();
Console.WriteLine($"Element: {attribute}, Content: {content}");
break;
}
}
}
}
}
}
自定义组件
NModBus4的使用
NModbus4 使用笔记
简介
NModbus4 是一个用于 .NET 的开源 Modbus 协议库。支持 Modbus TCP、RTU 和 ASCII 协议,可以在 .NET Framework 和 .NET Core 项目中使用。
基本使用
-
Modbus TCP Master
using System; using System.Net.Sockets; using NModbus; class Program { static void Main(string[] args) { using (TcpClient client = new TcpClient("127.0.0.1", 502)) { var factory = new ModbusFactory(); var master = factory.CreateMaster(client); // 读取保持寄存器 ushort startAddress = 0; ushort numberOfPoints = 5; ushort[] registers = master.ReadHoldingRegisters(1, startAddress, numberOfPoints); // 打印读取到的数据 for (int i = 0; i < registers.Length; i++) { Console.WriteLine($"Register {i + startAddress}: {registers[i]}"); } } } }
-
Modbus RTU Master
using System; using System.IO.Ports; using NModbus; using NModbus.Serial; class Program { static void Main(string[] args) { using (SerialPort port = new SerialPort("COM1")) { port.BaudRate = 9600; port.DataBits = 8; port.Parity = Parity.None; port.StopBits = StopBits.One; port.Open(); var factory = new ModbusFactory(); var adapter = new SerialPortAdapter(port); var master = factory.CreateRtuMaster(adapter); // 读取线圈 bool[] coils = master.ReadCoils(1, 0, 10); // 打印读取到的线圈状态 for (int i = 0; i < coils.Length; i++) { Console.WriteLine($"Coil {i}: {coils[i]}"); } } } }
-
Modbus Slave
using System; using System.Net; using NModbus; using NModbus.Logging; class Program { static void Main(string[] args) { var factory = new ModbusFactory(); var network = new ModbusTcpNetwork(new TcpListenerAdapter(new TcpListener(IPAddress.Any, 502))); var slave = factory.CreateSlave(network); slave.DataStore = DataStoreFactory.CreateDefaultDataStore(); slave.Logger = new ConsoleModbusLogger(LogLevel.Info); slave.ListenAsync().GetAwaiter().GetResult(); } }
主要功能
- 读取/写入寄存器和线圈:支持功能码 1, 2, 3, 4, 5, 6, 15 和 16。
- 事件驱动的从站:支持 Modbus TCP、RTU 和 ASCII 从站的事件驱动实现。
- 扩展性:可以通过实现接口扩展功能。