InvokeMember

本文详细解析了Type.InvokeMember方法的多种重载形式及其参数意义,重点介绍了如何通过实例调用非静态方法,并通过示例说明了target参数的使用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

xxxType.InvokeMember Method

这个是一个类型去反射某个方法,但是这个的好多个重载方法,长的一匹

不去好好理解,尼玛,太难受了。这不是很正常的吗?

重载1:

InvokeMember(String,BindingFlags,Binder,Object,Object[],ParameterModifier[],CultureInfo,String[])

重载2:

InvokeMember(String, BindingFlags, Binder, Object, Object[]) 

重载3:

InvokeMember(String, BindingFlags, Binder, Object, Object[], CultureInfo)

InvokeMember(String, BindingFlags, Binder, Object, Object[], CultureInfo) 

所以这么看起来就一个需要分析,为啥?因为其他就是这个的阉割版

public abstract object InvokeMember 
(
    string name,
    System.Reflection.BindingFlags invokeAttr, 
    System.Reflection.Binder binder, 
    object target, 
    object[] args, S
    ystem.Reflection.ParameterModifier[] modifiers, 
    System.Globalization.CultureInfo culture, 
    string[] namedParameters
);

参数分析

name 故名思意就是包含要调用的构造函数、方法、属性或者字段的名称

                  构造函数 public A(){}

                  方法public void A(){}

                  属性public string A{get;set;}

                  字段public string A="";

或者用空字符串(""),表示调用默认成员

或 对于IDispatch 成员,则为一个标识DIspID 的字符串,例如"[DispID=1]"

 

invokerAttr BindingFlags

一个位屏蔽,由一个或者多个指定搜索执行方式的 BindingFlags组成。访问可以是 BindingFlags 之一,如public、nonpublic、private、InvokeMethod 和 GetField等 如果省略查找类型,则使用 BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static .

Binder

一个对象,该对象定义一组属性并启动绑定,而绑定可能涉及选择重载方法、强制参数类型和通过反射调用成员

或者- 要使用DefaultBinder的空引用(在vb为nothing)。为了成功地使用变量参数来调用方法重载,可能必须显示定义Binder对象。

target Object

对其调用指定成员的对象

args Object[]

包含传递给要调用的成员的参数的数组

modifiers ParameterModifier[]

ParameterModifier对象的数组,表示与args数组中的相关元素相关的特性。参数的相关的属性存储在成员的签名中

只有调用com组件时,默认联编程序才处理此参数

culture CultureInfo

表示要使用的全局化区域设置的 CultureInfo对象,他对区域设置特定的转换可能是必须的,比如将数字string转换为double。

或-要使用当前线程nothing的空引用

namedParameters String[]

包含参数名称的数组,args 数组的值传递给这些参数。

public object InvokeMember
 (
    string name, 
    System.Reflection.BindingFlags invokeAttr, 
    System.Reflection.Binder binder, 
    object target, 
    object[] args
);

来举个例子吧

Type.InvokeMember(
                methodName, BindingFlags.Public | BindingFlags.Instance | BindingFlags.InvokeMethod, null, xxx, newObject);

主要是对target不太熟悉,target就是对其调用指定成员的对象。

怎么说呢?就是说这个方法是一个类下的方法,但这个类不是静态类,这个方法也不是静态方法,那么就需要通过实例进行调用,那么target就是这个实例。建立这个实例instance的时候,用那个调用默认成员,也就是methodName为空的时候“”,就可以了。

 

 

 

 

 

using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Diagnostics; using System.Drawing; using System.Drawing.Drawing2D; using System.IO.Ports; using System.Linq; using System.Reflection; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; using Microsoft.Win32; namespace loading { public partial class _11111111 : Form { private bool isopen = false; // 绘图相关变量 private List<PointF> dataPoints = new List<PointF>(); private Pen axisPen = new Pen(Color.Black, 2); private Pen gridPen = new Pen(Color.LightGray, 1) { DashStyle = DashStyle.Dash }; private Pen dataPen = new Pen(Color.Red, 2); private Font axisFont = new Font("Arial", 8); private SolidBrush textBrush = new SolidBrush(Color.Black); private SolidBrush pointBrush = new SolidBrush(Color.Blue); private int padding = 40; // 坐标系边距 private StringBuilder serialBuffer = new StringBuilder(); // 串口数据缓冲区 public _11111111() { InitializeComponent(); InitializeDrawingPanel(); } private void InitializeDrawingPanel() { // 启用双缓冲(通过反射) typeof(Panel).InvokeMember("DoubleBuffered", BindingFlags.SetProperty | BindingFlags.Instance | BindingFlags.NonPublic, null, drawingPanel, new object[] { true }); drawingPanel.Paint += DrawingPanel_Paint; drawingPanel.SizeChanged += (s, e) => { drawingPanel.Invalidate(); }; } private void DrawingPanel_Paint(object sender, PaintEventArgs e) { Graphics g = e.Graphics; g.SmoothingMode = SmoothingMode.AntiAlias; g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias; if (drawingPanel.Width <= 0 || drawingPanel.Height <= 0) return; // 1. 绘制坐标系(原点在左中位置,显示第一和第二象限) DrawCoordinateSystem(g); // 2. 绘制数据点(如果有数据) if (dataPoints.Count > 0) { DrawDataPoints(g); } // 3. 绘制调试信息 DrawDebugInfo(g); } // 修复后的坐标系绘制(显示第一和第二象限) private void DrawCoordinateSystem(Graphics g) { // 原点定位到面板中心(实现对称分布) int originX = drawingPanel.Width / 2; int originY = drawingPanel.Height / 2; // 计算动态可用区域 int axisWidth = drawingPanel.Width - padding * 2; int axisHeight = drawingPanel.Height - padding * 2; // 绘制X轴(居中延伸) g.DrawLine(axisPen, originX - axisWidth / 2, originY, originX + axisWidth / 2, originY); // 绘制Y轴(居中延伸) g.DrawLine(axisPen, originX, originY - axisHeight / 2, originX, originY + axisHeight / 2); // 绘制箭头 DrawArrow(g, new Point(originX + axisWidth / 2, originY), Direction.Right); // X轴正方向 DrawArrow(g, new Point(originX - axisWidth / 2, originY), Direction.Left); // X轴负方向 DrawArrow(g, new Point(originX, originY - axisHeight), Direction.Up); // Y轴正方向 // 绘制原点标记 g.DrawString("0", new Font(axisFont, FontStyle.Bold), Brushes.Red, originX - 15, originY + 5); // 绘制网格和刻度 DrawGrid(g, originX, originY, axisWidth, axisHeight); } // 修复后的网格绘制(显示第一和第二象限) private void DrawGrid(Graphics g, int originX, int originY, int axisWidth, int axisHeight) { // X轴网格数量(左右各5个) int gridCountX = 10; // Y轴网格数量 int gridCountY = 10; // 计算每个网格的宽度和高度 float gridSizeX = axisWidth / (float)gridCountX; float gridSizeY = axisHeight / (float)gridCountY; // 绘制横向网格(只向上) for (int i = 1; i <= gridCountY; i++) { int yPos = originY - (int)(i * gridSizeY); if (yPos < 0) continue; // 确保不超出顶部 g.DrawLine(gridPen, originX - axisWidth / 2, yPos, originX + axisWidth / 2, yPos); g.DrawString($"{i}", axisFont, textBrush, originX - 25, yPos - 8); } // 绘制纵向网格(左右各5个) for (int i = 1; i <= gridCountX / 2; i++) { // 右侧网格 int xPosRight = originX + (int)(i * gridSizeX); g.DrawLine(gridPen, xPosRight, originY, xPosRight, originY - axisHeight); g.DrawString($"{i}", axisFont, textBrush, xPosRight - 5, originY + 5); // 左侧网格 int xPosLeft = originX - (int)(i * gridSizeX); g.DrawLine(gridPen, xPosLeft, originY, xPosLeft, originY - axisHeight); g.DrawString($"-{i}", axisFont, textBrush, xPosLeft - 15, originY + 5); } // 绘制坐标轴标签 g.DrawString("X轴", axisFont, textBrush, originX + axisWidth / 2 - 20, originY + 20); g.DrawString("Y轴", axisFont, textBrush, originX - 30, originY - axisHeight); } // 修复后的数据点绘制(显示第一和第二象限) private void DrawDataPoints(Graphics g) { if (dataPoints.Count == 0) return; // 设置原点在左中位置 int originX = padding; int originY = drawingPanel.Height - padding; int axisWidth = drawingPanel.Width - padding * 2; int axisHeight = drawingPanel.Height - padding * 2; // 计算数据范围(X轴正负,Y轴正方向) float maxX = 1.0f, maxY = 1.0f, minX = -1.0f; foreach (var point in dataPoints) { if (Math.Abs(point.X) > maxX) maxX = Math.Abs(point.X); if (point.Y > maxY) maxY = point.Y; if (point.X < minX) minX = point.X; } // 确保最小值 maxX = Math.Max(maxX, 1.0f); maxY = Math.Max(maxY, 1.0f); // 计算缩放比例 float scaleX = axisWidth / (maxX - minX); // X轴范围从minX到maxX float scaleY = axisHeight / maxY; // 绘制数据点和连线 PointF? prevPoint = null; foreach (var point in dataPoints) { // 确保Y>=0 float validY = Math.Max(0, point.Y); // 坐标转换 float screenX = originX + (point.X - minX) * scaleX; float screenY = originY - validY * scaleY; // 只绘制上半部分的点 if (screenY < 0) continue; // 绘制数据点 g.FillEllipse(pointBrush, screenX - 3, screenY - 3, 6, 6); // 连接线 if (prevPoint != null) { g.DrawLine(dataPen, prevPoint.Value.X, prevPoint.Value.Y, screenX, screenY); } prevPoint = new PointF(screenX, screenY); // 调试输出 Debug.WriteLine($"点({point.X},{point.Y}) -> 屏幕({screenX},{screenY})"); } } // 添加调试信息 private void DrawDebugInfo(Graphics g) { g.DrawString($"数据点数量: {dataPoints.Count}", axisFont, Brushes.Blue, 10, 10); if (dataPoints.Count > 0) { var lastPoint = dataPoints.Last(); g.DrawString($"最新点: ({lastPoint.X:F2}, {lastPoint.Y:F2})", axisFont, Brushes.Blue, 10, 30); } } // 修改后的箭头绘制 private void DrawArrow(Graphics g, Point point, Direction direction) { Point[] arrowPoints; int size = 8; switch (direction) { case Direction.Up: arrowPoints = new Point[] { point, new Point(point.X - size, point.Y + size), new Point(point.X + size, point.Y + size) }; break; case Direction.Right: arrowPoints = new Point[] { point, new Point(point.X - size, point.Y - size), new Point(point.X - size, point.Y + size) }; break; default: return; } g.FillPolygon(Brushes.Black, arrowPoints); } private enum Direction { Up, Right, Left} // 打开串口 private void open_btn_Click(object sender, EventArgs e) { try { if (serialPort2.IsOpen == false) { serialPort2.PortName = port_cbb.Text; serialPort2.BaudRate = Convert.ToInt32(baud_cbb.Text); serialPort2.Open(); isopen = true; open_btn.Text = "关闭串口"; statusLabel.Text = $"已打开串口: {port_cbb.Text}@{baud_cbb.Text}"; // 添加串口数据接收处理 serialPort2.DataReceived += SerialPort2_DataReceived; } else { serialPort2.Close(); isopen = false; open_btn.Text = "打开串口"; statusLabel.Text = "串口已关闭"; // 移除串口数据接收处理 serialPort2.DataReceived -= SerialPort2_DataReceived; } } catch (Exception ex) { statusLabel.Text = $"串口操作失败: {ex.Message}"; } } // 串口数据接收事件 private void SerialPort2_DataReceived(object sender, SerialDataReceivedEventArgs e) { try { // 读取所有可用数据 int bytesToRead = serialPort2.BytesToRead; byte[] buffer = new byte[bytesToRead]; serialPort2.Read(buffer, 0, bytesToRead); // 将字节转换为字符串 string data = Encoding.ASCII.GetString(buffer); // 添加到缓冲区 serialBuffer.Append(data); // 处理缓冲区中的完整行 ProcessSerialBuffer(); } catch (Exception ex) { // 在UI线程显示错误 this.Invoke((MethodInvoker)delegate { statusLabel.Text = $"接收错误: {ex.Message}"; }); } } // 处理串口缓冲区中的数据 private void ProcessSerialBuffer() { // 检查是否有完整行 while (serialBuffer.ToString().Contains("\n")) { int newLineIndex = serialBuffer.ToString().IndexOf('\n'); string line = serialBuffer.ToString(0, newLineIndex).Trim(); serialBuffer.Remove(0, newLineIndex + 1); if (!string.IsNullOrEmpty(line)) { // 在UI线程处理数据 this.Invoke((MethodInvoker)delegate { ProcessIncomingData(line); }); } } } // 处理接收到的数据 private void ProcessIncomingData(string data) { // 更新状态栏显示原始数据 statusLabel.Text = $"接收: {data}"; try { // 示例数据格式: "X123.45,Y67.89" 或 "123.45,67.89" if (data.Contains(",")) { string[] parts = data.Split(','); if (parts.Length >= 2) { float x, y; // 尝试解析带前缀的格式 if (parts[0].StartsWith("X") || parts[0].StartsWith("x")) { if (!float.TryParse(parts[0].Substring(1), out x)) return; if (!float.TryParse(parts[1].Substring(1), out y)) return; } else // 直接数值格式 { if (!float.TryParse(parts[0], out x)) return; if (!float.TryParse(parts[1], out y)) return; } // 添加到数据点集合 dataPoints.Add(new PointF(x, y)); // 限制数据点数量 if (dataPoints.Count > 100) dataPoints.RemoveAt(0); // 重绘面板 drawingPanel.Invalidate(); // 更新状态 statusLabel.Text = $"点({x}, {y}) 已添加"; } } else { statusLabel.Text = $"无效数据格式: {data}"; } } catch (Exception ex) { statusLabel.Text = $"解析错误: {ex.Message}"; } } private void _11111111_Load(object sender, EventArgs e) { serialLoad(); // 初始化波特率下拉框 baud_cbb.Items.AddRange(new object[] { 9600, 19200, 38400, 57600, 115200 }); baud_cbb.SelectedIndex = 0; // 添加测试数据 AddTestData(0, 0); AddTestData(50, 50); AddTestData(-50, 30); } // 添加数据点 public void AddTestData(float x, float y) { dataPoints.Add(new PointF(x, y)); drawingPanel.Invalidate(); } private void serialLoad() { try { RegistryKey keyCom = Registry.LocalMachine.OpenSubKey(@"Hardware\DeviceMap\SerialComm"); if (keyCom != null) { string[] sSubKeys = keyCom.GetValueNames(); port_cbb.Items.Clear(); foreach (var sValue in sSubKeys) { string portName = (string)keyCom.GetValue(sValue); if (!string.IsNullOrEmpty(portName)) port_cbb.Items.Add(portName); } // 默认选择第一个可用端口 if (port_cbb.Items.Count > 0) port_cbb.SelectedIndex = 0; } } catch (Exception ex) { statusLabel.Text = $"加载串口失败: {ex.Message}"; } } // 清除数据按钮 private void btnClear_Click(object sender, EventArgs e) { dataPoints.Clear(); drawingPanel.Invalidate(); statusLabel.Text = "数据已清除"; } // 窗体关闭时关闭串口 protected override void OnFormClosing(FormClosingEventArgs e) { base.OnFormClosing(e); if (serialPort2.IsOpen) { serialPort2.Close(); } } // 其他事件处理(如标签点击事件) private void label2_Click(object sender, EventArgs e) { } private void label1_Click(object sender, EventArgs e) { } private void drawingPanel_Paint_1(object sender, PaintEventArgs e) { } } }根据我的代码整合
最新发布
06-19
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值