CH03_反射

第3章:反射


本章目标

  1. 掌握反射的原理

  2. 熟悉反射的基本运用

本章内容

反射是什么

C# 编译运行过程
  • 首先我们在VS点击编译的时候,就会将C#源代码编译成程序集

    • 程序集以可执行文件 (.exe) 或动态链接库文件 (.dll) 的形式实现

  • 程序集中包含有Microsoft 中间语言 (MSIL) 和必需的元数据。

    • 元数据存储以下信息:

      • 程序集的说明:标识(名称、版本、区域性、公钥)、导出的类型、该程序集所依赖的其他程序集、运行所需的安全权限。
      • 类型的说明:名称、可见性、基类和实现的接口、成员(方法、字段、属性、事件、嵌套的类型)。
      • 特性:修饰类型和成员的其他说明性元素。
  • 在执行时,实时 (JIT) 编译器将 MSIL 转换为本机代码

    • 运行 Microsoft 中间语言 (MSIL) 前,必须根据公共语言运行时将其编译为目标计算机基础结构的本机代码。

  • 运行代码

    • 公共语言运行时提供启用要发生的托管执行的基础结构以及执行期间可使用的服务

反射的工作原理

反射 来自 System.Reflection命名空间,它可以读取程序集中的元数据,利用元数据创建对象,从而实现各种功能。

提示:

区分 反射 与反编译,反射读取的是元数据,反编译读取的IL代码

反射的优缺点
  • 优点:提高了程序的灵活性和扩展性,降低耦合度
  • 缺点:由于反射多了一道程序,性能上相较于直接代码要慢

反射的使用

反射相关的类和命名空间

反射的命名空间:

using System.Reflection;

反射相关的类:

System.Type						   //类型
System.AppDomain				   //应用程序域
System.Activator				   //激活器
System.Reflection.Assembly			//程序集
System.Reflection.Module			//模块


System.Reflection.ConstructorInfo	//构造函数
System.Reflection.ParameterInfo		//方法参数
System.Reflection.MethodInfo		//方法
System.Reflection.PropertyInfo		//属性
System.Reflection.FieldInfo			//字段
System.Reflection.MemberInfo		//成员

Type类的应用
Type类中的基本属性

在这里插入图片描述

/// <summary>
/// 学生类
/// </summary>
class Student
{
    private int _num = 0;

    public string Phone = "15818704257";

    public string Name { get; set; }

    public string Address { get; set; }

    public Student()
    {
        //Console.WriteLine("Student 默认构造函数");
    }

    public Student(string name)
    {
        //Console.WriteLine($"Student 参数化构造函数:{name}");
    }

    public Student(string name,string phone,string address)
    {

    }

    public int PublicMethod()
    {
        return int.MinValue;
    }

    internal void InternalMethod()
    {

    }
    private void PrivateMethod()
    {

    }

    public void Show(int id)
    {
        Console.WriteLine("调用了Show()方法!"+id);
    }
}

class MyArray<T>
{

}

/// <summary>
/// USB接口
/// </summary>
interface IUsb
{

}

struct Teacher
{

}
/// <summary>
/// Type类的基本属性
/// </summary>
static void Fun1()
{
    Type t0 = typeof(MyArray<int>);
    Type t1= typeof(Student);
    Type t2 = typeof(IUsb);
    Type t3 = typeof(Teacher);
    Type t4 = typeof(string);

    Console.WriteLine("名称:"+t1.Name);
    Console.WriteLine("全名:"+t1.FullName);
    Console.WriteLine("命名空间:"+t1.Namespace);

    Console.WriteLine("是否是抽象的:"+t1.IsAbstract);
    Console.WriteLine("是否是公共的:" + t1.IsPublic);

    Console.WriteLine("是否是类:" + t1.IsClass);
    Console.WriteLine("是否是枚举:" + t1.IsEnum);
    Console.WriteLine("是否是接口:" + t1.IsInterface);

    Console.WriteLine("是否是嵌套定义的:" + t1.IsNested);
    Console.WriteLine("是否是值类型:" + t1.IsValueType);
    Console.WriteLine("是否是泛型类型:" + t1.IsGenericType);
}
using ClassLibrary1;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace CH03Demo
{
    internal class Program
    {
        static void Main(string[] args)
        {
            Fun11();

            Console.ReadLine();
        }
    }
}

提示:

FullName :获取该类型的完全限定名称,包括其命名空间,但不包括程序集 。

Type类的Assembly属性

在这里插入图片描述

/// <summary>
/// Type类的Assembly属性
/// </summary>
static void Fun2()
{

    Type type = typeof(Student);

    //程序集
    Assembly a1 = type.Assembly;

    Console.WriteLine("位置:" + a1.CodeBase);
    Console.WriteLine("全名:" + a1.FullName);

    Console.WriteLine("--------------------------------");

    Type t1 = typeof(Student);
    Type t2 = typeof(string);

    Console.WriteLine("全名:" + t1.FullName);
    Console.WriteLine("全名:" + t2.FullName);

    //查看程序集限定名
    Console.WriteLine(t1.AssemblyQualifiedName);
    Console.WriteLine(t2.AssemblyQualifiedName);

}
Type类对象获取构造函数

在这里插入图片描述

/// <summary>
/// 查看构造函数
/// </summary>
static void Fun3()
{
    Type t= typeof(Student);

    ConstructorInfo[] ciArray= t.GetConstructors();

    //遍历构造函数
    foreach (ConstructorInfo ci in ciArray)
    {
        Console.WriteLine("构造函数名:" + ci.Name);

        foreach (ParameterInfo item in ci.GetParameters())
        {
            Console.WriteLine("参数:{0},类型:{1}", item.Name, item.ParameterType);
        }
        Console.WriteLine("-------------------------------");
    }
}
Type类对象获取方法

在这里插入图片描述

/// <summary>
/// 查看当前实例的所有public方法
/// </summary>
static void Fun4()
{
    Type t = typeof(Student);

    MethodInfo[] miArray = t.GetMethods();

    //遍历构造函数
    foreach (MethodInfo mi in miArray)
    {
        Console.WriteLine("方法名:{0},返回类型:{1}",mi.Name,mi.ReturnType);

        foreach (ParameterInfo item in mi.GetParameters())
        {
            Console.WriteLine("参数:{0},类型:{1}" ,item.Name,item.ParameterType);
        }
        Console.WriteLine("-------------------------------");
    }
}
Type类对象获取属性

在这里插入图片描述

/// <summary>
/// 查看当前实例的所有public属性
/// </summary>
static void Fun5()
{
    Type t = typeof(Student);

    PropertyInfo[] miArray = t.GetProperties();

    //遍历
    foreach (PropertyInfo pi in miArray)
    {
        Console.WriteLine("属性名:{0},类型:{1}",pi.Name,pi.PropertyType);

        Console.WriteLine("-------------------------------");
    }
}
Type类对象获取字段

在这里插入图片描述

/// <summary>
/// 查看当前实例的所有public字段
/// </summary>
static void Fun6()
{
    Type t = typeof(Student);

    FieldInfo[] fiArray = t.GetFields();

    //遍历
    foreach (FieldInfo fi in fiArray)
    {
        Console.WriteLine("字段名:{0},类型:{1}", fi.Name, fi.FieldType);

        Console.WriteLine("-------------------------------");
    }
}
Type类对象获取成员

在这里插入图片描述

/// <summary>
/// 查看当前实例的所有public成员
/// </summary>
static void Fun7()
{
    Type t = Type.GetType("CH03Demo.Student"); //typeof(Student);

    MemberInfo[] miArray = t.GetMembers();
    
    //遍历
    foreach (MemberInfo mi in miArray)
    {
        Console.WriteLine("成员名:{0},类型:{1}", mi.Name, mi.MemberType);

        Console.WriteLine("-------------------------------");
    }
}
使用BindingFlags筛选成员

在这里插入图片描述

/// <summary>
/// 使用绑定标志枚举筛选成员
/// </summary>
static void Fun8()
{
    Type t = Type.GetType("CH03Demo.Student"); //typeof(Student);

    //GetMembers 中传入 BindingFlags 相当于是对成员信息进行一个过滤
    //BindingFlags 不仅仅是GetMembers 专有,很多方法中都可以传入BindingFlags进行过滤

    //BindingFlags 是位标志枚举,可使用 | & ^ 等运算符, | 表示取并集,& 表示取交集,^ 表示取差集
    //BindingFlags.Public 表示公共成员
    //BindingFlags.NonPublic 表示非公共成员
    //BindingFlags.Instance 表示实例成员
    //BindingFlags.Static 表示静态成员
    MemberInfo[] miArray = t.GetMembers(BindingFlags.NonPublic | BindingFlags.Instance);

    //遍历
    foreach (MemberInfo mi in miArray)
    {
        Console.WriteLine("成员名:{0},类型:{1}", mi.Name, mi.MemberType);

        Console.WriteLine("-------------------------------");
    }
}

提示:

BindingFlags.Instance 和BindingFlags.Static :实例成员是相对于静态成员而言的,多数情况下我们都省略了BindingFlags 这个参数,少数需要筛选成员的时候,传入该参数

获取Type实例的方式
/// <summary>
/// 获取Type实例的方式
/// </summary>
static void Fun9()
{
    Student stu = new Student();

    //方式1:System.Type类的ComDefaultInterface特性
    Type t1 = typeof(Student);

    //方式2:System.Object中的GetType()方法
    Type t2 = stu.GetType();

    //方式3:System.Type中GetType()方法
    //想通程序集,传入FullName即可(命名空间+类名)
    Type t3 = Type.GetType("CH03Demo.Student");
    //不同程序集,则还需传入程序集名
    Type t4 = Type.GetType("ClassLibrary1.Class1,ClassLibrary1");


}
Activator类的应用
//Activator类主要用于创建对象的实例
Type type = typeof(UserInfo);
UserInfo userInfo=(UserInfo)Activator.CreateInstance(type);
Assembly类的应用
  • 对于程序集的限定名称使用小结
    • 程序集的显示名称,可通过Assembly.FullNameAssembly.GetName().FullName(即AssemblyName.FullName) 两种方式获取,这种获取的名称,一般是作为 Assembly.Load()的标准参数值
    • 类型的程序集限定名,可通过Type类中的AssemblyQualifiedName属性获取(通常作为Type.GetType()方法中的参数值), 相较于Assembly.FullName,名称格式上多了 Type.FullName 这一部分
  • Assembly类中的常用方法
    • Assembly.Load()方法接收一个String或AssemblyName类型作为参数,这个参数需要程序集的强名称
    • Assembly.LoadFrom() 根据程序集的文件名或路径,加载程序集;这个方法会加载此程序集引用的其他程序集
    • Assembly.LoadFile() 加载指定路径上的程序集文件内容,和上面方法的不同之处是这个方法不会加载此程序集引用的其他程序集

程序集的强名称:是程序集的FullName(具有名称,版本,语言,公钥标记);
程序集的弱命名:只有程序集名称而没有版本,语言和公钥标记;平常我们创建的一个类库,如果没有特殊操作都属于是是弱名称程序集
Load(“强名称程序集”)查找程序集的顺序:首先它会去全局程序集缓存查找,然后到应用程序的根目录查找,最后会到应用程序的私有路径查找。
Load(“弱名称程序集”)查找程序集的顺序:首先到应用程序的根目录查找,最后会到应用程序的私有路径查找。

 /// <summary>
 /// 程序集加载的3种方式
 /// </summary>
 static void Fun12()
 {
     //方式1:将ClassLibrary1.dll放在根目录下,传入程序集的简单名称,即可加载
     Assembly assembly1 = Assembly.Load("ClassLibrary1");

     //方式2:传入ClassLibrary1.dll的文件路径,会加载ClassLibrary1.dll依赖的程序集
     Assembly assembly2 = Assembly.LoadFrom("ClassLibrary1.dll");

     //方式3:传入ClassLibrary1.dll的文件路径,不会加载ClassLibrary1.dll依赖的程序集
     Assembly assembly3 = Assembly.LoadFile(AppDomain.CurrentDomain.BaseDirectory+ "ClassLibrary1.dll");
 }
Module类的应用
什么是模块

System.Reflection.Module类‌是C#中的一个重要类,它提供了有关程序集中模块的信息和功能。这个类的作用和使用方法在深入探讨模块类时会被详细讨论,通过一些示例代码来展示它的功能。在C#中,模块可以是一个源代码文件、一个编译后的文件(DLL或EXE)或者一个动态生成的程序集。每个模块都有自己的元数据和IL代码,而System.Reflection.Module类提供了访问和操作这些模块的能力。通过Module类,我们可以获取模块的元数据、类型信息、成员信息以及执行模块中的代码。

模块的属性

在这里插入图片描述

/// <summary>
/// 模块
/// </summary>
static void Fun13()
{
    //类型对象
    Type t1 = typeof(Student);
    Type t2 = typeof(string);

    //模块
    Module module1 = t1.Module;
    Module module2 = t2.Module;

    //基本属性
    Console.WriteLine("模块名:"+module1.Name);
    Console.WriteLine("完全限定名:" + module1.FullyQualifiedName);
    Console.WriteLine("程序集名:" + module1.Assembly.FullName);

    Console.WriteLine("-----------------------------");

    Console.WriteLine("模块名:" + module2.Name);
    Console.WriteLine("完全限定名:" + module2.FullyQualifiedName);
    Console.WriteLine("程序集名:" + module2.Assembly.FullName);
}
AppDomain类的应用

前提:

从.NET Core开始,不再支持运行时创建其他AppDomain(即仅可在.NET Framework下支持创建其他AppDomain)。

因此以下部分内容仅在.NET Framework上有效。

官方说明:.NET Framework 技术在 .NET 6 及更高版本上不可用

AppDomain应用程序域:一组程序集的逻辑容器,CLR创建的第一个AppDomain称为默认AppDomain,仅在进程终止时销毁。

一个AppDomain可以包含N个Assembly,一个Assembly可以包含N个Module,而一个Module可以包含N个Type.

在这里插入图片描述

/// <summary>
/// 应用程序域
/// </summary>
static void Fun14()
{
    //获取当前应用程序域中的所有程序集
    Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();

    foreach (Assembly assembly in assemblies)
    {
        Console.WriteLine(assembly.FullName);
    }
}
通过反射创建对象
/// <summary>
/// 反射:创建对象的3种方式
/// </summary>
static void Fun10()
{
    //类型对象
    Type t = typeof(Class1);

    #region 方式1:通过Invoke 执行构造函数

    //获取构造函数对象
    ConstructorInfo ci1 = t.GetConstructor(new Type[] { });
    ConstructorInfo ci2 = t.GetConstructor(new Type[] {typeof(int) });

    //调用构造函数创建实例
    object obj1= ci1.Invoke(new object[] { });
    object obj2 = ci2.Invoke(new object[] {15 });

    //类型装换
    Class1 c1=obj1 as Class1;
    Class1 c2 = obj2 as Class1;

    #endregion

    #region 方式2:通过Assembly 创建实例

    //程序集对象
    Assembly assembly = Assembly.Load("ClassLibrary1");

    //创建实例
    object obj3 = assembly.CreateInstance("ClassLibrary1.Class1",true);

    //类型转换
    Class1 c3= obj3 as Class1;

    #endregion

    #region 方式3:通过 Activator 创建实例

    //创建对象
    object obj4 = Activator.CreateInstance(t);
    object obj5 = Activator.CreateInstance("ClassLibrary1", "ClassLibrary1.Class1");

    //类型转换
    Class1 c4 = obj4 as Class1;
    Class1 c5 = obj5 as Class1;

    #endregion
}
通过反射获取对象成员

在这里插入图片描述

/// <summary>
/// 反射:获取 方法、属性、字段
/// </summary>
static void Fun11()
{
    //类型对象
    Type t = typeof(Student);

    //目标实体
    object obj= Activator.CreateInstance(t);

    #region 反射:获取方法

    //获取方法对象
    MethodInfo mi= t.GetMethod("Show");

    //执行方法
    mi.Invoke(obj, new object[] {25 });

    //Invoke 调用静态方法,对象可以为null ,形如 
    //methodInfo.Invoke(null, new object[] { "hello" })

    #endregion

    #region 反射:获取属性

    //获取属性对象
    PropertyInfo pi = t.GetProperty("Name");
    pi.SetValue(obj, "张三");

    //调用属性
    string name= pi.GetValue(obj) as string;
    Console.WriteLine("姓名:"+name);

    #endregion

    #region 反射:获取字段

    //获取属性对象
    FieldInfo fi = t.GetField("Phone");
    fi.SetValue(obj, "13523983345");

    //调用字段
    string phone = fi.GetValue(obj) as string;
    Console.WriteLine("电话:" + phone);

    #endregion
}

反射的应用

数据库辅助类反射
常规情况下:编写固定DBHelper类
using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CH03Demo
{
    internal class DBHelper
    {
        private static readonly string _connectionString = "server=.;database=test;uid=sa;pwd=sa";

        /// <summary>
        /// 执行增删改
        /// </summary>
        /// <param name="sql"></param>
        /// <returns></returns>
        public int ExecuteNonQuery(string sql,params SqlParameter[] parameters)
        {
            //略
            return 0;
        }
        /// <summary>
        /// 执行查询
        /// </summary>
        /// <param name="sql"></param>
        /// <returns></returns>
        public DataTable ExecuteTable(string sql,params SqlParameter[] parameters)
        {
            //略
            return null;
        }
    }
}

反射+配置文件动态实现

1.创建一个接口

using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Data.Common;

namespace CH03Demo
{
    /// <summary>
    /// 数据访问接口
    /// </summary>
    internal interface IDBHelper
    {
        /// <summary>
        /// 执行增删改
        /// </summary>
        /// <param name="sql"></param>
        /// <returns></returns>
        int ExecuteNonQuery(string sql, params DbParameter[] parameters);

        /// <summary>
        /// 执行查询
        /// </summary>
        /// <param name="sql"></param>
        /// <returns></returns>
        DataTable ExecuteTable(string sql, params DbParameter[] parameters);
    }
}

2.实现接口

using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CH03Demo
{
    /// <summary>
    /// sqlserver 数据库的数据访问类
    /// </summary>
    internal class SqlServerDBHelper : IDBHelper
    {
        public int ExecuteNonQuery(string sql, params DbParameter[] parameters)
        {
            //代码略
            return 0 ;
        }

        public DataTable ExecuteTable(string sql, params DbParameter[] parameters)
        {
            //代码略
            return null;
        }
    }
}

3.增加配置文件

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <startup> 
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" />
    </startup>
	<appSettings>
		<add key="DBType" value="SqlServer"/>
	</appSettings>
</configuration>

4.过反射+配置文件 调用 数据库执行语句的方法

/// <summary>
/// 通过反射创建数据辅助类对象
/// </summary>
static void Fun15()
{
    string fullName = ConfigurationManager.AppSettings["DBType"].ToString();

    IDBHelper dbHelper = (IDBHelper)Assembly.Load("DBHelper").CreateInstance(fullName);

    var data1 = dbHelper.ExecuteNonQuery("delete from student where studentNo=@studentNo", new SqlParameter("@studentNo", "GCKJ101"));
    var data2 = dbHelper.ExecuteTable("select * from student");

    Console.WriteLine(data1);
    Console.WriteLine(data2.Rows.Count);
}

目录结构:

在这里插入图片描述

本章总结

课后作业

1.通过反射查看int类 Type基本信息
2.通过反射调用int类的实例方法: CompareTo
3.通过反射调用int类的静态方法: Parse

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/919216.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

HAL_UARTEx_ReceiveToIdle_DMA和HAL_UART_Receive_DMA的区别

功能 HAL_UART_Receive_DMA 仅仅是开启的串口的DMA接收&#xff0c;若是想使用空闲中断 DMA接收则需要开启串口的空闲中断&#xff1b; 而HAL_UARTEx_ReceiveToIdle_DMA函数中则包含了开启串口空闲中断&#xff1b; HAL_UART_Receive_DMA 的接收类型是HAL_UART_RECEPTION_ST…

MyBlog(三) -- APP的应用

文章目录 前言一、APP是什么?二、创建APP三、使用APP1. 注册app2. 添加路由3. 运行过程4. 完善视图函数5. 结果展示 总结 前言 前面我们已经学习了如何创建一个新的项目,并且配置好了项目的启动文件,成功将项目启动! 那么接下来我们的主要任务就是需要完善这个项目中应该包含…

tdengine学习笔记-整体架构及docker安装

官方文档&#xff1a;用 Docker 快速体验 TDengine | TDengine 文档 | 涛思数据 整体架构 TDENGINE是分布式&#xff0c;高可靠&#xff0c;支持水平扩展的架构设计 TDengine分布式架构的逻辑结构图如下 一个完整的 TDengine 系统是运行在一到多个物理节点上的&#xff0c;包含…

【支持向量机(SVM)】:相关概念及API使用

文章目录 1 SVM相关概念1.1 SVM引入1.1.1 SVM思想1.1.2 SVM分类1.1.3 线性可分、线性和非线性的区分 1.2 SVM概念1.3 支持向量概念1.4 软间隔和硬间隔1.5 惩罚系数C1.6 核函数 2 SVM API使用2.1 LinearSVC API 说明2.2 鸢尾花数据集案例2.3 惩罚参数C的影响 1 SVM相关概念 1.1…

git 基础之 merge 和 rebase 的比较

在团队软件开发过程中&#xff0c;代码合并是一个基本且频繁执行的任务。 Git 提供了多种合并代码的策略&#xff0c;其中最常用的是 merge 和 rebase。 尽管二者的终极目标是相同的——整合代码变更——它们的方法和推荐的使用场景却有所区别。本文将详细介绍和比较这两种策…

sagemaker中使用pytorch框架的DLC训练和部署cifar图像分类任务

参考资料 https://github.com/aws/amazon-sagemaker-examples/blob/main/sagemaker-python-sdk/pytorch_cnn_cifar10/pytorch_local_mode_cifar10.ipynbhttps://sagemaker.readthedocs.io/en/stable/frameworks/pytorch/using_pytorch.html 获取训练数据 # s3://zhaojiew-sa…

jmeter常用配置元件介绍总结之配置元件

系列文章目录 1.windows、linux安装jmeter及设置中文显示 2.jmeter常用配置元件介绍总结之安装插件 3.jmeter常用配置元件介绍总结之线程组 4.jmeter常用配置元件介绍总结之函数助手 5.jmeter常用配置元件介绍总结之取样器 6.jmeter常用配置元件介绍总结之jsr223执行pytho…

vite+vue3+ts编译vue组件后,编译产物中d.ts文件为空

一、前言 使用vue3vitets实现一个UI组件库&#xff0c;为了生成类型文件便于其他项目引用该组件库。根据推荐使用了vite-plugin-dts插件进行ts文件的生成 二、版本 组件版本vue ^3.5.12 vite ^5.4.10 vite-plugin-dts ^4.3.0 typescript ~5.6.2 三、问题描述 使用vitevi…

红外相机和RGB相机外参标定 - 无需标定板方案

1. 动机 在之前的文章中红外相机和RGB相机标定&#xff1a;实现两种模态数据融合_红外相机标定-CSDN博客 &#xff0c;介绍了如何利用标定板实现外参标定&#xff1b;但实测下来发现2个问题&#xff1a; &#xff08;1&#xff09;红外标定板尺寸问题&#xff0c;由于标定板小…

柔性仿人手指全覆盖磁皮肤,具备接触觉和运动觉的双模态感知能力

人体精细触觉和本体运动觉依赖于相同类型的感受器&#xff0c;这些感受器位于肌肉、肌腱、关节和皮肤中&#xff0c;负责感知轻触、挠痒、细微压力、形状变化、肌肉张力、肌腱拉伸和关节位置变化等信息。因此方斌教授团队着手于具有高精度、小尺寸、可定制等优势的磁触觉传感器…

【摘要】正点原子--Makefile--学习笔记

目录 一、Makefile 基础1、Makefile引入2、Makefile初次编写 二、Makefile语法1、Makefile规则格式2、Makefile第一次升级 一、Makefile 基础 1、Makefile引入 2、Makefile初次编写 二、Makefile语法 1、Makefile规则格式 2、Makefile第一次升级

【WPF】Prism学习(八)

Prism Dependency Injection 1.处理解析错误 1.1. 处理解析错误&#xff1a; 这个特性是在Prism 8中引入的&#xff0c;如果你的应用目标是早期版本&#xff0c;则不适用。 1.2. 异常发生的原因&#xff1a; 开发者可能会遇到多种原因导致的异常&#xff0c;常见的错误包括…

第8章硬件维护-8.2 可维护性和可靠性验收

8.2 可维护性和可靠性验收 可维护性和可靠性验收非常重要&#xff0c;硬件维护工程师在后端发现问题后&#xff0c;总结成可维护性和可靠性需求&#xff0c;在产品立项的时候与新特性一起进行需求分析&#xff0c;然后经过设计、开发和测试环节&#xff0c;在产品中落地。这些需…

Java 岗面试八股文及答案整理(2024最新版)

春招&#xff0c;秋招&#xff0c;社招&#xff0c;我们 Java 程序员的面试之路&#xff0c;是挺难的&#xff0c;过了 HR&#xff0c;还得被技术面&#xff0c;小刀在去各个厂面试的时候&#xff0c;经常是通宵睡不着觉&#xff0c;头发都脱了一大把&#xff0c;还好最终侥幸能…

sglang 部署Qwen2VL7B,大模型部署,速度测试,深度学习

sglang 项目github仓库&#xff1a; https://github.com/sgl-project/sglang 项目说明书&#xff1a; https://sgl-project.github.io/start/install.html 资讯&#xff1a; https://github.com/sgl-project/sgl-learning-materials?tabreadme-ov-file#the-first-sglang…

Debezium日常分享系列之:Debezium3版本Debezium connector for JDBC

Debezium日常分享系列之&#xff1a;Debezium3版本Debezium connector for JDBC 概述JDBC连接器的工作原理消费复杂的Debezium变更事件至少一次的传递多个任务数据和列类型映射主键处理删除模式幂等写入模式演化引用和大小写敏感性连接空闲超时数据类型映射部署Debezium JDBC连…

Java项目实战II基于微信小程序的科创微应用平台(开发文档+数据库+源码)

目录 一、前言 二、技术介绍 三、系统实现 四、文档参考 五、核心代码 六、源码获取 全栈码农以及毕业设计实战开发&#xff0c;CSDN平台Java领域新星创作者&#xff0c;专注于大学生项目实战开发、讲解和毕业答疑辅导。获取源码联系方式请查看文末 一、前言 随着科技的…

C++ Primer习题集----题目+答案版

具体源码请见&#xff1a;Cprimer习题上半部分资源-CSDN文库 目录 第一章 开始 练习1.1 编写程序&#xff0c;在标准输出上打印Hello.world 练习1.2 我们的程序使用加法运算符来将两个数相加。编写程序使用乘法运算符*&#xff0c;来打印两个数的积。 练习1.4 编译一个包…

Zookeeper的简单使用Centos环境下

目录 前言 一、ZOokeeper是什么&#xff1f; 二、安装Zookeeper 1.进入官网下载 2.解压到服务器 3.配置文件 三.使用Zookeeper 3.1启动相关指令 3.2其他指令 3.3ACL权限 总结 前言 记录下安装zookeeper的一次经历 一、ZOokeeper是什么&#xff1f; ZooKeeper是一…

【Linux】————多线程(概念及控制)

作者主页&#xff1a; 作者主页 本篇博客专栏&#xff1a;Linux 创作时间 &#xff1a;2024年11月19日 再谈地址空间&#xff1a; OS对内存进行管理不是根据字节为单位&#xff0c;以字节为单位效率过低&#xff0c;是以内存块为单位的&#xff0c;一个内存块的大小一般为4…