【从零开始入门unity游戏开发之——C#篇39】C#反射使用——Type 类、Assembly 类、Activator 类操作程序集

文章目录

  • 前言
  • 一、前置知识
    • 1、编译器
    • 2、程序集(`Assembly`)
    • 3、元数据(`Metadata`)
  • 二、反射
    • 1、反射的概念
    • 2、反射的作用
    • 3、反射的核心`Type` 类
      • 3.1 `Type` 类介绍
      • 3.2 不同方法获取 `Type`
      • 3.3 获取type类型所在的程序集的相关信息
    • 4、反射的常见用法
      • 4.1 获取 `Type`类型信息
      • 4.2 获取类的公共成员
      • 4.3 获取类的构造函数
      • 4.4 获取类的字段
      • 4.5 获取类的成员方法
      • 4.6 其他反射操作
    • 5、反射访问并操作私有(private)成员(包括字段、属性、方法等)
    • 6、总结
  • 三、关键类Assembly和Activator
    • 1、**反射中的关键类**
      • 1.1 `Type` 类(前面已经介绍过了)
      • 1.2 `Assembly` 类
      • 1.3 `Activator` 类
    • 2、**使用 `Activator` 类实例化对象**
      • 示例 1:无参构造函数
      • 示例 2:带参数的构造函数
    • 3、**使用 `Assembly` 类加载程序集**
      • 3.1 加载程序集:
        • (1)获取当前执行的程序集:
        • (2)从指定路径加载程序集:
      • 3.2 获取指定名称的类型
      • 3.3 获取所有类型:
      • 3.4 获取并调用类型中的方法:
    • 4、综合示例
  • 四、**总结**
  • 专栏推荐
  • 完结

前言

C# 反射 (Reflection) 是一种强大的机制,它允许程序在运行时动态地查看和操作程序的元数据。通过反射,我们可以在不事先知道类型信息的情况下,获取类型信息并操作类型中的成员(如类、方法、属性、字段等)。

一、前置知识

1、编译器

编译器是将源语言程序(如 C#、Java、C 等)翻译为目标语言程序(如机器代码或伪机器代码)的工具。源代码经过编译器的处理后,可以生成可执行文件 (.exe) 或库文件 (.dll) ,供程序运行时使用。

2、程序集(Assembly

程序集是经过编译器编译得到的中间产物,可以是一个库文件 (.dll) 或可执行文件 (.exe)。它是 .NET 程序中的代码集合,包含了类型、方法、属性等元数据,是程序执行的基础。

程序集就是我们写的一个代码集合,我们现在写的所有代码,最终都会被编译器翻译为一个程序集供别人使用。比如一个代码库文件(dll)或者一个可执行文件(exe)

我们新建一个C#项目,运行一次后,系统就会自动在bin目录里生成对应的程序集文件
在这里插入图片描述

3、元数据(Metadata

在C#中,元数据(Metadata)指的是描述程序及其组成部分(如类、方法、属性、字段等)的信息。它是关于代码的“数据”,但并不是实际执行的代码。可以将元数据视为程序代码的“数据字典”,它提供了有关类型、成员和引用等的信息,使得程序在运行时可以进行动态操作。

元数据是随代码一起编译成程序集(Assembly)的一部分,并且可以在运行时通过反射机制进行访问。

元数据是指有关程序结构和组成部分的描述信息,它不仅有助于程序的运行时类型检查,还为反射、动态加载等功能提供了支持。在C#中,元数据通常存储在程序集文件中,并可以通过反射机制访问和操作。

二、反射

1、反射的概念

反射允许程序在运行时查看其他程序集或自身的元数据,动态获取类型信息并对其进行操作。例如,通过反射可以查看类的构造函数、方法、字段、属性等,甚至可以在运行时动态创建对象并调用方法。

2、反射的作用

  • 程序运行时获取类型信息:反射可以帮助我们动态获取类、方法、字段等的元数据信息。
  • 动态操作对象:反射使得我们可以动态实例化对象,调用方法,修改字段值等。
  • 增强灵活性:反射使得代码更加灵活,尤其在插件机制、依赖注入等场景下尤为重要。

3、反射的核心Type

3.1 Type 类介绍

Type 类是反射的基础,它提供了关于类的所有信息,例如类的名称、构造函数、方法、字段、属性等。它是访问元数据的主要方式。

3.2 不同方法获取 Type

  • 通过对象的 GetType() 方法获取:

    int a = 42;
    Type type = a.GetType();
    Console.WriteLine(type);  // 输出: System.Int32
    
  • 通过 typeof 关键字获取:

    Type type = typeof(int);
    Console.WriteLine(type);  // 输出: System.Int32
    
  • 通过类的全名获取:

    Type type = Type.GetType("System.Int32");
    Console.WriteLine(type);  // 输出: System.Int32
    

    其实就是命名空间.类名
    在这里插入图片描述

3.3 获取type类型所在的程序集的相关信息

Console.WriteLine(type.Assembly);

打印

System.Private.CoreLib, Version=9.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e
  • System.Private.CoreLib 是程序集的名称。(通常是 .exe 或 .dll 文件的名称)
  • Version=9.0.0.0 是程序集的版本。
  • Culture=neutral 表示它是通用区域设置的。(如果是通用语言程序集,则为 neutral)。
  • PublicKeyToken=7cec85d7bea7798e 是公共密钥标识符。(用于区分同名的不同程序集版本)。

4、反射的常见用法

为了方便测试反射的常见用法,这里我先新增一个简单的类,里面包含基本的构造函数、方法、字段、属性。

ps:这里只是测试探究,实际开发肯定不需要通过反射来操作自己的类。

class Test
{private int i = 1;public int j = 2;public int k { get; set; }public string str = "向宇的客栈";public Test() { }public Test(int i){this.i = i;}public Test(int i, string str) : this(i){this.str = str;}public void Log(){Console.WriteLine("学习C#");}
}

4.1 获取 Type类型信息

Type t = typeof(Test);// 获取类型信息

4.2 获取类的公共成员

使用 GetMembers() 方法获取类中的所有公共成员:

MemberInfo[] infos = t.GetMembers();
foreach (var info in infos)
{Console.WriteLine(info);
}

打印结果
在这里插入图片描述

可以看到,除了万物之父(object)中的方法,打印出来的都是我们前面Test类中定义的公共成员信息(构造函数、方法、字段、属性)。

4.3 获取类的构造函数

  • 获取所有构造函数:
ConstructorInfo[] ctors = t.GetConstructors();
foreach (var ctor in ctors)
{Console.WriteLine(ctor);
}

结果
在这里插入图片描述

  • 获取无参构造函数并调用:
ConstructorInfo ctor = t.GetConstructor(Type.EmptyTypes);
Test obj = (Test)ctor.Invoke(null);
Console.WriteLine(obj);
  • 获取有参构造函数并调用:
ConstructorInfo ctor = t.GetConstructor(new Type[] { typeof(int), typeof(string) });
Test obj = (Test)ctor.Invoke(new object[] { 10, "Hello" });
Console.WriteLine(obj);

4.4 获取类的字段

  • 获取所有公共字段:
FieldInfo[] fieldInfos = t.GetFields();
foreach (var field in fieldInfos)
{Console.WriteLine(field);
}

结果
在这里插入图片描述

  • 获取指定字段:
FieldInfo fieldInfo = t.GetField("j");
Console.WriteLine(fieldInfo);

结果
在这里插入图片描述

  • 使用反射获取和设置字段的值:
FieldInfo fieldInfo = t.GetField("j");
Test test = new Test();
test.j = 99;
fieldInfo.SetValue(test, 100);
Console.WriteLine(fieldInfo.GetValue(test));  // 输出: 100

4.5 获取类的成员方法

  • 获取所有公共方法(记得引入using System.Reflection;反射命名空间):
using System.Reflection;MethodInfo[] methods = t.GetMethods();
foreach (var method in methods)
{Console.WriteLine(method);
}
  • 获取指定方法并调用:
MethodInfo method = t.GetMethod("ToString");
object result = method.Invoke(test, null);
Console.WriteLine(result);
  • 对于方法重载,需要提供方法的参数类型:
MethodInfo method = t.GetMethod("Substring", new Type[] { typeof(int), typeof(int) });
object result = method.Invoke("Hello, World!", new object[] { 7, 5 });
Console.WriteLine(result);  // 输出: World

4.6 其他反射操作

  • 枚举
    获取枚举类型的名称:

    Enum.GetEnumName(typeof(DayOfWeek), 1);  // 输出: Monday
    
  • 事件
    获取类的事件:

    EventInfo eventInfo = t.GetEvent("MyEvent");
    Console.WriteLine(eventInfo);
    
  • 接口
    获取类实现的接口:

    Type[] interfaces = t.GetInterfaces();
    foreach (var iface in interfaces)
    {Console.WriteLine(iface);
    }
    
  • 属性
    获取类的属性:

    PropertyInfo[] properties = t.GetProperties();
    foreach (var property in properties)
    {Console.WriteLine(property);
    }
    

5、反射访问并操作私有(private)成员(包括字段、属性、方法等)

在默认情况下,反射是可以访问私有成员的,但你必须明确告诉 .NET 你要访问它们。具体来说,你需要使用 BindingFlags 来指定访问私有成员。

例如,默认情况下,反射会忽略私有字段和方法,但你可以通过显式地指定 BindingFlags.NonPublicBindingFlags.Instance 来让反射能够访问这些私有成员。

示例

// 创建 MyClass 的实例
MyClass myObject = new MyClass();// 获取 MyClass 类型的信息
Type type = typeof(MyClass);// 使用反射访问私有字段 secretValue
FieldInfo fieldInfo = type.GetField("secretValue", BindingFlags.NonPublic | BindingFlags.Instance);
if (fieldInfo != null)
{// 获取字段的值var value = fieldInfo.GetValue(myObject);Console.WriteLine("Private Field 'secretValue' Value: " + value);
}// 使用反射访问私有方法 PrintSecret
MethodInfo methodInfo = type.GetMethod("PrintSecret", BindingFlags.NonPublic | BindingFlags.Instance);
if (methodInfo != null)
{// 调用私有方法methodInfo.Invoke(myObject, null);
}

这种机制虽然强大,但应谨慎使用,避免破坏封装性,尤其是在生产环境中。这种做法通常用于调试、测试、动态代理等特殊场景。

6、总结

C# 中的反射为程序提供了强大的动态能力,通过 Type 类及其提供的方法,我们可以在运行时获取类型的元数据,动态创建对象,调用方法,甚至修改字段值。

虽然反射提供了灵活性,但是反射的性能较差,因为它是动态查找和操作的。如果频繁使用反射,可能会影响程序性能,尤其是在处理大量数据时。因此应该在合适的场合使用反射,并考虑到性能和可维护性。

三、关键类Assembly和Activator

反射(Reflection)是 C# 中一个非常强大的机制,它允许在运行时访问和操作程序中的类型信息。通过反射,程序可以在运行时动态地获取类、方法、属性等信息,并实例化对象、调用方法、访问字段等。下面是对 AssemblyActivator 这两个关键类的详细介绍和相关用法。

1、反射中的关键类

1.1 Type 类(前面已经介绍过了)

Type 类提供了对类型信息的访问,它是所有类型的元数据的基础。通过 Type 对象,你可以获取类的构造函数、属性、字段、方法等信息。

1.2 Assembly

Assembly 类用于加载和操作程序集。程序集包含了类、接口、枚举等信息,反射可以用来加载程序集,并且在程序运行时查找类型和操作它们。

1.3 Activator

Activator 类位于 System 命名空间下,提供了一组静态方法来创建类型的实例。它常用于在运行时通过反射动态创建对象,特别是在我们事先不知道具体类型的情况下。例如,依赖注入、插件加载、对象池等场景中,可以使用 Activator 来动态实例化对象。

2、使用 Activator 类实例化对象

Activator 提供了几种创建对象的方法,最常用的是 CreateInstance,它可以用来根据 Type 对象动态创建实例。

示例 1:无参构造函数

假设有一个类 Test,它有一个无参构造函数。你可以使用 Activator.CreateInstance 来创建该类的实例。

using System;public class Test
{public string str = "Hello, World!";
}class Program
{static void Main(){// 获取 Test 类的 Type 对象Type testType = typeof(Test);// 使用 Activator 创建对象实例Test testobj = Activator.CreateInstance(testType) as Test;// 输出结果Console.WriteLine(testobj.str);  // Output: Hello, World!}
}

示例 2:带参数的构造函数

如果类有带参数的构造函数,可以使用 Activator.CreateInstance 方法传递参数来创建实例。

using System;public class Test
{public int j;public string str;// 构造函数public Test(int j, string str){this.j = j;this.str = str;}
}class Program
{static void Main(){Type testType = typeof(Test);// 使用带参数的构造函数Test testobj1 = Activator.CreateInstance(testType, 99, "Hello") as Test;Console.WriteLine(testobj1.j);  // Output: 99Console.WriteLine(testobj1.str);  // Output: HelloTest testobj2 = Activator.CreateInstance(testType, 55, "World") as Test;Console.WriteLine(testobj2.j);  // Output: 55Console.WriteLine(testobj2.str);  // Output: World}
}

3、使用 Assembly 类加载程序集

前面我们一直都是对当前程序的操作,实际开发肯定是操作外部程序集。Assembly 类使得我们可以在运行时加载、查询、获取外部程序集的类型信息等。

常用方法:

  • GetExecutingAssembly():获取当前执行的程序集。
  • LoadFrom(string path):从指定路径加载程序集。
  • GetTypes():获取程序集中的所有类型。
  • GetType(string typeName):获取指定名称的类型。
  • GetManifestResourceNames():获取程序集中的所有嵌入式资源名称。

3.1 加载程序集:

(1)获取当前执行的程序集:
Assembly assembly = Assembly.GetExecutingAssembly();
Console.WriteLine("当前程序集: " + assembly.FullName);
(2)从指定路径加载程序集:
Assembly assembly = Assembly.LoadFrom("path/to/your/assembly.dll");
Console.WriteLine("加载程序集: " + assembly.FullName);

3.2 获取指定名称的类型

Assembly assembly = Assembly.LoadFrom("path/to/your/assembly.dll");
Type type = assembly.GetType("Namespace.ClassName"); // 获取程序集中的某个类型
Console.WriteLine("类型名称: " + type.FullName);

3.3 获取所有类型:

Assembly assembly = Assembly.LoadFrom("path/to/your/assembly.dll");
Type[] types = assembly.GetTypes();
foreach (Type t in types)
{Console.WriteLine(t.FullName); // 输出程序集中的所有类型
}

3.4 获取并调用类型中的方法:

其实就是结合前面Type知识配合使用

Assembly assembly = Assembly.LoadFrom("path/to/your/assembly.dll");
Type type = assembly.GetType("Namespace.ClassName");
MethodInfo methodInfo = type.GetMethod("MethodName");
object result = methodInfo.Invoke(null, null); // 调用静态方法
Console.WriteLine(result);

4、综合示例

我这里项目的程序集文件路径为:C:\Users\zw\Desktop\C#\bin\Debug\net9.0\C#.dll
在这里插入图片描述
程序集文件里主要的代码是,我自定义了一个Test类
在这里插入图片描述

代码

using System;
using System.Reflection;class Program
{static void Main(){// 加载程序集(因为是反斜杠,所以加个@不希望它转义)Assembly assembly = Assembly.LoadFrom(@"C:\Users\zw\Desktop\C#\bin\Debug\net9.0\C#.dll");// 获取程序集中的所有类型Type[] types = assembly.GetTypes();foreach (var type in types){Console.WriteLine(type.Name);}// 获取程序集中的一个具体类型Type testType = assembly.GetType("Test");// 使用反射实例化对象object myClassObj = Activator.CreateInstance(testType);// 获取并调用方法MethodInfo method = testType.GetMethod("Log");method.Invoke(myClassObj, null);// 获取指定字段并打印值FieldInfo field1 = testType.GetField("str");Console.WriteLine(field1.GetValue(myClassObj));// 获取指定字段,先修改值,在打印值FieldInfo field2 = testType.GetField("j");field2.SetValue(myClassObj, 100);Console.WriteLine(field2.GetValue(myClassObj));}
}

结果,程序集里的方法被执行,字段也被打印了(Program类和E_Days枚举是定义的其他两个测试数据,不用管即可)
在这里插入图片描述

四、总结

  • Type:提供关于类、接口、枚举等类型的信息。
  • Assembly:用于加载程序集,可以获取程序集中的所有类型和类型成员信息。
  • Activator:用于在运行时动态创建对象实例,支持无参数和带参数构造函数。
  • 反射虽然非常强大,但会影响性能,因此在需要时使用,避免过度依赖。

专栏推荐

地址
【从零开始入门unity游戏开发之——C#篇】
【从零开始入门unity游戏开发之——unity篇】
【制作100个Unity游戏】
【推荐100个unity插件】
【实现100个unity特效】
【unity框架开发】

完结

赠人玫瑰,手有余香!如果文章内容对你有所帮助,请不要吝啬你的点赞评论和关注,你的每一次支持都是我不断创作的最大动力。当然如果你发现了文章中存在错误或者有更好的解决方法,也欢迎评论私信告诉我哦!

好了,我是向宇,https://xiangyu.blog.csdn.net

一位在小公司默默奋斗的开发者,闲暇之余,边学习边记录分享,站在巨人的肩膀上,通过学习前辈们的经验总是会给我很多帮助和启发!如果你遇到任何问题,也欢迎你评论私信或者加群找我, 虽然有些问题我也不一定会,但是我会查阅各方资料,争取给出最好的建议,希望可以帮助更多想学编程的人,共勉~
在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

使用JMeter对Linux生产服务器进行压力测试

安装 JMeter wget https://downloads.apache.org/jmeter/binaries/apache-jmeter-5.4.1.tgz tar -xzf apache-jmeter-5.4.1.tgz cd apache-jmeter-5.4.1创建 JMeter 脚本 设置中文 选择Options—>Choose Language—>选择其他语言(例如:Chinese&am…

STM32-笔记20-测量按键按下时间

1、按键按下的时间-思路 我们先检测下降沿信号,检测到以后,在回调函数里切换成检测上升沿信号,当两个信号都检测到的时候,这段时间就是按键按下的时间,如图所示:>N*(ARR1)CCRx的值 N是在这段时间内&…

CPT203 Software Engineering 软件工程 Pt.2 敏捷方法和需求工程(中英双语)

文章目录 3. Aglie methods(敏捷方法)3.1 Aglie methods(敏捷方法)3.1.1 特点3.1.2 优点3.1.3 缺点3.1.4 原则3.1.5 计划驱动与敏捷方法的对比 3.2 Scrum3.2.1 Scrum roles3.2.2 Scrum Activities and Artifacts3.2.2.1 Product B…

攻防靶场(29):目录权限和文件权限 ICMP

目录 1. 侦查 1.1 收集目标网络信息:IP地址 1.2 主动扫描:扫描IP地址段 1.3 搜索目标网站 2. 初始访问 2.1 利用面向公众的应用 3. 权限提升 3.1 有效账户:本地账户 3.2 滥用特权控制机制:Sudo和Sudo缓存 靶场下载地址&#xff1a…

Spring自动化创建脚本-解放繁琐的初始化配置!!!(自动化SSM整合)

一、实现功能(原创,转载请告知) 1.自动配置pom配置文件 2.自动识别数据库及数据表,创建Entity、Dao、Service、Controller等 3.自动创建database.properties、mybatis-config.xml等数据库文件 4.自动创建spring-dao.xml spring-mvc.xml …

【二】arcgis JavaScript api 实现加载不同坐标系的底图和三维服务

提示:如果是天地图底图参考这篇文章 【一】arcgis JavaScript api 实现加载不同坐标系的底图和三维服务_arcgis js api 调用三维地图服务-CSDN博客 需求: 前端开发实现底图(wkid:3857,web墨卡托)&#x…

HTML——46.制作课程表

<!DOCTYPE html> <html><head><meta charset"UTF-8"><title>课程表</title></head><body><h3>课程表</h3><table border"1" cellspacing"0"><tr><th colspan"…

ARM64 Windows 10 IoT工控主板运行x86程序效率测试

ARM上的 Windows 10 IoT 企业版支持仿真 x86 应用程序&#xff0c;而 ARM上的 Windows 11 IoT 企业版则支持仿真 x86 和 x64 应用程序。英创推出的名片尺寸ARM64工控主板ESM8400&#xff0c;可预装正版Windows 10 IoT企业版操作系统&#xff0c;x86程序可无需修改而直接在ESM84…

小程序组件 —— 23 组件案例 - 轮播图图片添加

上一节实现了轮播图的最外层结构&#xff0c;但是没有通过轮播图来渲染图片&#xff0c;这一节我们先讲一下小程序中怎么来渲染图片&#xff0c;讲解完之后会通过轮播图来展示图片&#xff1b; 在微信小程序中&#xff0c;如果需要渲染图片&#xff0c;需要使用 image 组件&am…

阿克曼(Ackmann)函数

时间限制&#xff1a;C/C 1000MS&#xff0c;其他语言 2000MS 内存限制&#xff1a;C/C 256MB&#xff0c;其他语言 512MB 难度&#xff1a;中等 分数&#xff1a;100 OI排行榜得分&#xff1a;12(0.1*分数2*难度) 描述 阿克曼(Ackmann)函数A(m&#xff0c;n)中&#xff0c;m&…

自动驾驶新纪元:城区NOA功能如何成为智能驾驶技术的分水岭

目录 一、NOA 的定义 二、NOA 的主要特点 导航集成 场景覆盖 智能决策 高级感知能力 驾驶员参与 三、NOA 的优势 四、NOA的衡量指标 定性评价指标 安全性评价指标定义 可靠性评价指标定义 舒适性评价指标定义 通行效率评价指标 定量评价指标 五、代表厂商的实测…

石岩路边理发好去处

周末带娃去罗租公园玩&#xff0c;罗租公园旁边就是百佳华和如意豪庭小区&#xff0c;发现如意豪庭小区对面挺多路边理发摊点 理发摊点聚焦在这里的原因是刚好前面城管来了暂时避避&#xff0c;例如还有一个阿姨剪到一半就跟着过来。这里的城管只是拍了一处没有摊位的地方&…

STM32-笔记24-智能开关垃圾桶盖

一、模块及接线 二&#xff0c;项目目的 以下几个事件触发时&#xff0c;自动开盖&#xff0c;并伴随蜂鸣器短响一声&#xff0c;同时 LED 灯闪烁一下&#xff0c;2秒后自动关盖&#xff1a; 检测到有人靠近检测到有震动按下按键 KEY1 实验框图如下&#xff1a; 三、项目前期…

从零开始开发纯血鸿蒙应用之UI封装

从零开始开发纯血鸿蒙应用 一、题引二、UI 组成三、UI 封装原则四、实现 lib_comps1、封装 UI 样式1.1、attributeModifier 属性1.2、自定义AttributeModifier<T>类 2、封装 UI 组件 五、总结 一、题引 在开始正文前&#xff0c;为了大家能够从本篇博文中&#xff0c;汲…

使用ArcGIS Pro自带的Notebook计算多个遥感指数

在之前的分享中&#xff0c;我们介绍了如何使用ArcPy将GEE下载的遥感影像转为单波段文件。基于前面创建的单波段文件&#xff0c;我们可以一次性计算多种遥感指数&#xff0c;例如NDVI、EVI、NDSI等。我这里直接在ArcGIS Pro中自带的Notebook进行的运行。如下图所示&#xff0c…

超大规模分类(一):噪声对比估计(Noise Contrastive Estimation, NCE)

NCE损失对应的论文为《A fast and simple algorithm for training neural probabilistic language models》&#xff0c;发表于2012年的ICML会议。 背景 在2012年&#xff0c;语言模型一般采用n-gram的方法&#xff0c;统计单词/上下文间的共现关系&#xff0c;比神经概率语言…

275-增强型多功能数据采集卡PCIe-6251-EX

产品特点&#xff1a; 高速高精度数据采集&#xff0c;16bit10MSPS&#xff0c;32路单端/16路差分高速高精度任意波形发生&#xff0c;14bit165MHz&#xff0c;2路完全独立完全可编程的I/O端口&#xff0c;33个完全可编程的量程选择&#xff0c;0~5V/0~10V/5V/10VPCIe通信接口…

Llama 3 后训练(三)

目录 4. 后训练 4.1 建模 图表解读 4.1.1 聊天对话格式 4.1.2 奖励建模 4.1.3 监督微调&#xff08;Supervised Finetuning&#xff09; 4.1.4 直接偏好优化&#xff08;Direct Preference Optimization&#xff09; 4.1.5 模型平均&#xff08;Model Averaging&#x…

机器人C++开源库The Robotics Library (RL)使用手册(四)

建立自己的机器人3D模型和运动学模型 这里以国产机器人天机TR8为例,使用最普遍的DH运动学模型,结合RL所需的描述文件,进行生成。 最终,需要的有两个文件,一个是.wrl三维模型描述文件;一个是.xml运动学模型描述文件。 1、通过STEP/STP三维文件生成wrl三维文件 机器人的…

Go+chromedp实现Web UI自动化测试

1.为什么使用go进行UI自动化测试&#xff1f; 速度&#xff1a;Go速度很快&#xff0c;这在运行包含数百个UI测试的测试套件时是一个巨大的优势 并发性&#xff1a;可以利用Go的内置并发性(goroutines)来并行化测试执行 简单&#xff1a;Go的简约语法允许您编写可读且可维护…