c#中的Type类型

反射只要明白

创建对象

获取类成员

加载程序集

读写属性值

构造函数很少使用

Activator正是反射三大经典操作中提到的"创建对象" 的绝对主力。

复制代码
  public class UserInfo
  {
      public UserInfo()
      {
          MessageBox.Show("UserInfo的构造函数");
      }

      public int UserId { get; set; }
      public string UserName { get; set; }
      public int UserAge { get; set; }
  }

UserInfo User1=new UserInfo();  创建实例

//假设不直接创建
Type type=typeof(UserInfo); //获取类型的Type对象
UserInfo user2=Activator.CreateInstance<UserInfo>(); //创建一个UserInfo实例;
UserInfo user3=(UserInfo)Activator.CreateInstance(type);   //使用默认构造函数创建实例;



//带参数的构造函数
Type type=typeof(studentInfo);
object obj=Activator.CreateInstance(typeof(studentInfo),23);
studentInfo student2=(studentInfo)obj;
txtBox.Text += "studentInfo的Id为" + student2.Id;

//获取类成员



//读写属性值

//  Assembly ass = Assembly.LoadFile(@"D:\vs\c++\futoubang\QTVSTOOL\test_反射\test_反射\bin\Debug\Models3.dll");
  Assembly ass = Assembly.LoadFrom("Models3.dll");

  Type MenuInfoType=ass.GetType("Models3.MenuInfo");

   object menuInfo=  Activator.CreateInstance(MenuInfoType);  //创建实例

  MenuInfoType.GetProperty("MenuName").SetValue(menuInfo, "小凡");
  MenuInfoType.GetProperty("FrmName").SetValue(menuInfo, "页面名称");
  MenuInfoType.GetProperty("Remark").SetValue(menuInfo, "标记");

  var method = MenuInfoType.GetProperty("MenuName");
  var method2 = MenuInfoType.GetProperty("MenuName").GetValue(menuInfo);
  Console.WriteLine(method.Name);
  Console.WriteLine(method2.ToString());


  var IdProperty = MenuInfoType.GetProperty("MenuId");
  var IdProperty2 = MenuInfoType.GetProperty("MenuId").GetValue(menuInfo);

//加载程序集

Type 类是房子的"全套设计图纸" ,那么 System.Activator 就是拿着这张图纸帮你盖房子的"万能施工队"。

在平常写代码时,我们创建对象都是直接使用 new 关键字(比如 Student s = new Student();)。

但用 new 有一个硬性前提:你在敲代码(编译)的那一刻,必须确切地知道你要创建的类叫什么名字。

Activator 的强大之处在于:哪怕你在写代码时根本不知道具体的类名是什么(比如类名是以字符串的形式从配置文件里读取的),只要在程序运行的时候给它一张 Type 图纸,它就能当场给你 new 出一个真实的实例对象来。

问题:

而 Activator 的强大之处在于:哪怕你在写代码时根本不知道具体的类名是什么(比如类名是以字符串的形式从配置文件里读取的),只要在程序运行的时候给它一张 Type 图纸,它就能当场给你 new 出一个真实的实例对象来。 我不明白,你看利用Student s=new Student() 的时候,我们必须要用到Student这个类,而你说的Activator不知道具体的类名是什么就可以,但是我们在调用的时候使用的Activator.CreeateInstace(typeof(Student));这里面的参数,我们也必须使用到Student这个类啊,怎么能说不需要知道具体的类型是什么就可以呢?

Activator 真正的杀手锏,是配合 Type.GetType("类名的字符串") 来使用的。

想象这样一个真实场景:你正在开发一个游戏,玩家可以选择不同的武器(剑、弓)。你希望程序非常灵活,武器种类全写在外部的一个 config.txt 文本文件里。

让我们看看在这个场景下,Activator 是如何做到"代码里根本不写类名,也能造出对象"的:

复制代码
using System;

// 假设这些是你或者你的同事写的具体业务类
public class Sword 
{ 
    public Sword() { Console.WriteLine("🗡️ 生成了一把剑!"); } 
}

public class Bow 
{ 
    public Bow() { Console.WriteLine("🏹 生成了一把弓!"); } 
}



public class Program
{
    public static void Main()
    {
        // 1. 模拟从外部(比如文本文件、数据库或网络)读取到的类名文本
        // 注意:在这个 Main 函数的代码逻辑里,我们根本不知道将来读到的会是什么
        string classNameFromConfig = "Sword"; 

        // 2. 极致动态:通过纯字符串名称,去程序集里"搜"这张图纸!
        // 这里完全没有用到 typeof(),也没有直接引用具体的类
        Type t = Type.GetType(classNameFromConfig);

        if (t != null)
        {
            // 3. 万能施工队干活:根据找出来的图纸,直接在内存里生成对象
            object myWeapon = Activator.CreateInstance(t);
        }
        else
        {
            Console.WriteLine("没找到这个类的图纸!");
        }
    }
}

为什么这样设计极其强大?

仔细看上面的 Main 函数代码,里面从头到尾都没有出现过 new Sword() 或者 typeof(Sword) 这几个字。

这意味着什么? 如果明天游戏更新了,你新增了一个 MagicWand(魔法杖)类。你完全不需要修改和重新编译 上面 Main 函数里的这段核心加载逻辑!你只需要把外部配置文件里的字符串改成 "MagicWand",运行时 Type.GetType 就会自动找到新图纸,Activator 就会自动造出新武器。

这就是我们在架构设计中常说的"解耦"。

总结一下:

  • typeof(X) + Activator:属于"半动态",你得先认识这个类。通常用于泛型或者比较基础的反射场景。

  • Type.GetType("字符串") + Activator:属于"完全动态",代码里不需要出现任何具体的类名。只要能搞到类名的名字(字符串),就能把对象造出来。这也是大部分现代 C# 框架(比如 ASP.NET Core 的依赖注入、各种插件系统)底层的核心基石。

梳理:

复制代码
**📦 [Type 对象] (当前代表 Student 类)
 │   
 ├── 属性: Name      -> "Student"         (总图纸叫什么名字) 
 ├── 属性: FullName  -> "System.Student"  (总图纸的全称) [cite: 6]
 ├── 属性: IsClass   -> true              (这是不是个房子?) [cite: 6]
 │
 └── 方法: GetProperties() ─────┐ (打开图纸,查看所有的门窗) 
                                │
                                ▼
              🚪 [PropertyInfo 数组] (包含 2 个 PropertyInfo 对象) 
               │
               ├─▶ [PropertyInfo 对象 1] (代表 Student.Name 属性)
               │    ├── 属性: Name         -> "Name"  (这扇门叫什么名字) [cite: 14]
               │    ├── 属性: CanRead      -> true    (这扇门能打开吗?get;) [cite: 15, 16]
               │    ├── 属性: CanWrite     -> true    (这扇门能锁上吗?set;) [cite: 16]
               │    │
               │    └── 属性: PropertyType -> 📦 [Type 对象] (代表 String 类!) 
               │                                👆 注意这里:无限套娃开始!
               │                                   PropertyInfo 会告诉你这个属性的数据类型,
               │                                   而数据类型本身又是一个 Type 对象!
               │
               └─▶ [PropertyInfo 对象 2] (代表 Student.Age 属性)
                    ├── 属性: Name         -> "Age" 
                    ├── 属性: CanRead      -> true [cite: 15, 16]
                    ├── 属性: CanWrite     -> true [cite: 16]
                    └── 属性: PropertyType -> 📦 [Type 对象] (代表 Int32 类)**

一、核心概念图

复制代码
 程序集 (Assembly)
   └── 模块 (Module)
         └── 类型 (Type)  ← 一切的起点
               ├── 字段     (FieldInfo)
               ├── 属性     (PropertyInfo)  ← 你说的 Properties
               ├── 方法     (MethodInfo)
               ├── 构造函数 (ConstructorInfo)
               └── 事件     (EventInfo)

二、获取 Type ------ 万事开头

所有的c#数据类型,本质全都是Type对象

int double string bool 、自定义类全都属于Type

层级关系:

2. 通俗比喻
  • Type = 物种分类表
  • int = 整数这个物种
  • string = 字符串这个物种
  • double = 小数这个物种

typeof(xxx) 就是查到这个物种的档案 ,档案统一都是 Type 格式。

3. 代码直观证明

csharp

运行

复制代码
// 全部返回 Type 对象
Type t1 = typeof(int);
Type t2 = typeof(double);
Type t3 = typeof(string);
Type t4 = typeof(bool);
Type t5 = typeof(object);

4. 两大核心大类区分
1)值类型(栈内存存放)

int、double、float、bool、char、struct特点:存真实数据,复制互不影响

2)引用类型(堆内存存放)

string、object、class、数组特点:存地址,多个变量可能指向同一份数据


5. 最简单记忆口诀
  1. 只要是能定义变量的东西,都是 Type
  2. typeof(类型名) 统一返回 Type
  3. int/double 是值类型 Type,string/class 是引用类型 Type

6. 小判断练习
  • typeof(int) → Type ✅
  • typeof(string) → Type ✅
  • typeof(double) → Type ✅
  • typeof(自己写的Person类) → Type ✅

csharp

复制代码
 // 方式1:已知类型名(编译期已知)
 Type t1 = typeof(Person);
 ​
 // 方式2:从对象实例获取
 Person p = new Person();
 Type t2 = p.GetType();
 ​
 // 方式3:从字符串获取(运行时才知道类型名,跨程序集常用)
 Type t3 = Type.GetType("MyApp.Models.Person");
 ​
 // 三种方式拿到的是同一个 Type 对象
 Console.WriteLine(t1 == t2); // true

Type 对象本身有很多有用的属性:

csharp

复制代码
 Type t = typeof(Person);
 Console.WriteLine(t.Name);          // "Person"
 Console.WriteLine(t.FullName);      // "MyApp.Models.Person"
 Console.WriteLine(t.Namespace);     // "MyApp.Models"
 Console.WriteLine(t.IsClass);       // true
 Console.WriteLine(t.IsAbstract);    // false
 Console.WriteLine(t.BaseType);      // System.Object

三、Activator ------ 动态创建对象

Activator 是用来不用 new 关键字,在运行时创建对象的工具类。

复制代码
 public class Person
 {
     public string Name { get; set; }
     public int Age { get; set; }
 ​
     public Person() { }                          // 无参构造
     public Person(string name, int age)          // 有参构造
     {
         Name = name;
         Age = age;
     }
 }
 ​
 // ✅ 无参构造 - 最简单
 Person p1 = (Person)Activator.CreateInstance(typeof(Person));
 ​
 // ✅ 有参构造 - 传参数
 Person p2 = (Person)Activator.CreateInstance(typeof(Person), "张三", 25);
 ​
 // ✅ 泛型版本(更安全,不需要强转)
 Person p3 = Activator.CreateInstance<Person>();
 ​
 // ✅ 只有类型名字符串时(插件系统常用)
 Type t = Type.GetType("MyApp.Models.Person");
 object p4 = Activator.CreateInstance(t);

什么时候用 Activator? 当你在编译期不知道要创建什么类型时,比如:插件加载、依赖注入容器、ORM框架、工厂模式。

四、Properties / PropertyInfo ------ 操作属性

这是你最迷糊的部分,我详细讲。

4.1 获取属性列表

csharp

复制代码
 Type t = typeof(Person);
 ​
 // 获取所有 public 属性(最常用)
 PropertyInfo[] props = t.GetProperties();
 ​
 // 获取单个属性(按名字)
 PropertyInfo nameProp = t.GetProperty("Name");
 ​
 // 获取非public属性需要指定 BindingFlags
 PropertyInfo[] allProps = t.GetProperties(
     BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance
 );
4.2 PropertyInfo 的核心成员

csharp

复制代码
 PropertyInfo prop = typeof(Person).GetProperty("Name");
 ​
 prop.Name          // "Name"         属性名
 prop.PropertyType  // typeof(string) 属性的类型 ← 这是你说的 PropertyType
 prop.CanRead       // true           是否有 get
 prop.CanWrite      // true           是否有 set
 prop.DeclaringType // typeof(Person) 声明这个属性的类
4.3 PropertyType 是什么?

PropertyType 就是这个属性值的类型 ,它本身也是一个 Type 对象:

csharp

复制代码
 public class Person
 {
     public string Name { get; set; }    // PropertyType = typeof(string)
     public int Age { get; set; }        // PropertyType = typeof(int)
     public Address Home { get; set; }   // PropertyType = typeof(Address)
     public List<string> Tags { get; set; } // PropertyType = typeof(List<string>)
 }
 ​
 foreach (var prop in typeof(Person).GetProperties())
 {
     Console.WriteLine($"{prop.Name} 的类型是: {prop.PropertyType.Name}");
 }
 // 输出:
 // Name 的类型是: String
 // Age 的类型是: Int32
 // Home 的类型是: Address
 // Tags 的类型是: List`1
4.4 读写属性值(GetValue / SetValue)

csharp

复制代码
 Person person = new Person { Name = "张三", Age = 25 };
 PropertyInfo nameProp = typeof(Person).GetProperty("Name");
 ​
 // 读取值
 object value = nameProp.GetValue(person);
 Console.WriteLine(value); // "张三"
 ​
 // 写入值
 nameProp.SetValue(person, "李四");
//person是实例化对象
 Console.WriteLine(person.Name); // "李四"
4.5 实战:通用"对象转字典"

csharp

复制代码
 // 这种代码在框架里极其常见!
 public static Dictionary<string, object> ToDictionary(object obj)
 {
     var dict = new Dictionary<string, object>();
     foreach (var prop in obj.GetType().GetProperties())
     {
         dict[prop.Name] = prop.GetValue(obj);
     }
     return dict;
 }
 ​
 var person = new Person { Name = "张三", Age = 25 };
 var dict = ToDictionary(person);
 // { "Name": "张三", "Age": 25 }

五、MethodInfo ------ 动态调用方法

csharp

复制代码
 public class Calculator
 {
     public int Add(int a, int b) => a + b;
     private int Secret() => 42;
 }
 ​
 Type t = typeof(Calculator);
 object calc = Activator.CreateInstance(t);
 ​
 // 获取并调用 public 方法
 MethodInfo addMethod = t.GetMethod("Add");
 object result = addMethod.Invoke(calc, new object[] { 3, 5 });
 Console.WriteLine(result); // 8
 ​
 // 获取并调用 private 方法(需要 BindingFlags)
 MethodInfo secretMethod = t.GetMethod("Secret",
     BindingFlags.NonPublic | BindingFlags.Instance);
 object secret = secretMethod.Invoke(calc, null);
 Console.WriteLine(secret); // 42

new Type[] {} 写入参数就为 new type[]{ "XXX","XXX" };

1. 语法拆解:它到底是个啥?

  • Type[]:代表这是一个专门用来存放 Type 对象(图纸)的数组

  • new ... { }:这是 C# 里创建并初始化数组的语法。

  • { } 里面是空的:这意味着你创建了一个长度为 0 的空数组,里面什么元素都没有。

所以,new Type[] { } 的字面意思就是:"给我一个空的类型数组"。

2. 核心原理:为什么 GetMethod 非要你传一个空数组?

这里涉及到一个 C# 中非常重要的面向对象概念:方法重载(Overload)

在一个类里面,是可以允许存在多个同名 的方法的,只要它们的参数不同就行。比如,你的 Student 类里可能同时存在三个叫 Show 的方法:

  1. public void Show() (什么参数都不带)

  2. public void Show(int age) (带一个整数参数)

  3. public void Show(string name, int age) (带一个字符串和一个整数参数)

现在,你对反射机制说:"去给我把 Show 方法的说明书拿过来!" 程序就会很懵:"大哥,这里有三个 Show,你要我拿哪一个?"

为了防止程序找错,GetMethod 的第二个参数就是让你明确指定该方法的参数列表类型

配合上面提到的三个 Show 方法,我们来看看如何精准获取它们:

情况 A:获取无参的 Show() 这就是你截图里的情况。你传一个空数组 ,等于是告诉程序:"给我找那个不需要任何参数Show 方法。"

// 找 public void Show() MethodInfo m1 = type.GetMethod("Show", new Type[] { });

情况 B:获取带一个参数的 Show(int age) 你需要传一个只包含 int 图纸的数组。

// 找 public void Show(int age)

MethodInfo m2 = type.GetMethod("Show", new Type[] { typeof(int) });

情况 C:获取带两个参数的 Show(string name, int age) 你需要按顺序传入参数的图纸。

// 找 public void Show(string name, int age)

MethodInfo m3 = type.GetMethod("Show", new Type[] { typeof(string), typeof(int) });

进阶小贴士(C# 老鸟写法)

在实际开发中,每次要找无参方法时都写 new Type[] { } 显得有点啰嗦,而且每次都会在内存里产生一个新的空数组对象。

微软为了方便大家,提供了一个专门的简写属性:Type.EmptyTypes 。它等价于 new Type[] { }

所以,你截图里的代码在现代 C# 中,通常会写成这样,更加优雅和专业:

MethodInfo mshow = type.GetMethod("Show", Type.EmptyTypes);

为什么偏偏是 object[](对象数组)?

在平常写代码时,如果你调用 Show(int age),你直接传一个数字 18 进去就行了。那为什么在反射(Invoke)里,非得把参数塞进一个麻烦的 object[] 数组里呢?

答案在于反射的"万能性"。 当微软底层的程序员在编写 Invoke 这个方法时,他们根本不知道你未来会用它去调用什么方法:

  • 也许你的方法需要传入一个 (int)

  • 也许你的方法需要传入一个 (string, bool)

  • 也许你的方法需要传入你自己写的 (Student, Teacher)

因为 C# 中所有的类型(无论是数字、字符串还是你自定义的类)最终都继承自最基础的基类------System.Object 。所以,设计一个 object[](对象数组)就相当于准备了一个"万能快递箱"。不管你要传什么类型的参数,统统可以打包进这个箱子里,然后统一交给 Invoke 运送过去。

组装"万能快递箱"的三条铁律

要想成功通过 parameters 传递参数而不报错(不抛出截图里的那些 Exception),你在组装这个 object[] 数组时必须严格遵守三条规矩:

铁律 1:数量必须绝对对齐

方法要求几个参数,你的数组里就必须装几个元素。

无参数方法: 如果方法是 Show(),不需要任何材料,你可以直接传 null ,或者传一个空数组 new object[0]

  • 多参数方法: 哪怕参数再多,也要全部放进同一个数组里。
铁律 2:顺序必须绝对一致

数组中元素的排列顺序,必须与原方法定义的参数顺序一模一样

  • 如果原方法是:public void Show(string name, int age)

  • 你的数组必须是:new object[] { "张三", 20 } (先放字符串,再放整数)。

  • 如果你写成 new object[] { 20, "张三" },程序在运行时就会崩溃报错。

铁律 3:类型必须兼容(底层装箱)

虽然你建的是一个 object[],但你往里面塞的具体东西,必须是方法能接受的类型。

  • 当你写 new object[] { 18 } 时,C# 底层其实做了一个动作叫做"装箱(Boxing)",也就是把整数 18 悄悄包装成了一个 object 对象塞进数组里。当 Invoke 执行时,它又会把这个包装拆开,拿出 18 喂给你的目标方法。

💻 直观对比总结

复制代码
// 场景 1:目标方法不需要参数 -> public void SayHello()
MethodInfo m1 = type.GetMethod("SayHello", Type.EmptyTypes);
// 直接传 null 作为 parameters
m1.Invoke(myStudent, null); 


// 场景 2:目标方法需要 1 个参数 -> public void SetAge(int age)
MethodInfo m2 = type.GetMethod("SetAge", new Type[] { typeof(int) });
// 建一个长度为 1 的 object 数组
m2.Invoke(myStudent, new object[] { 25 }); 


// 场景 3:目标方法需要 3 个不同类型的参数 -> public void UpdateInfo(string name, int age, bool isMale)
MethodInfo m3 = type.GetMethod("UpdateInfo", new Type[] { typeof(string), typeof(int), typeof(bool) });
// 建一个长度为 3 的 object 数组,严格按照 (string, int, bool) 的顺序塞入数据
m3.Invoke(myStudent, new object[] { "李四", 22, true });

静态成员方法调用

MethodInfo staticShow=type.GetMethod("ShowInfo",new Type[]{});

staticShow.Invoke(null,null)

静态方法没有实例,第一个参数传递null即可。//静态方法调用,第一个参数null;

六、FieldInfo ------ 操作字段

csharp

复制代码
 public class Config
 {
     private string _connectionString = "默认值";
 }
 ​
 Type t = typeof(Config);
 object config = Activator.CreateInstance(t);
 ​
 FieldInfo field = t.GetField("_connectionString",
     BindingFlags.NonPublic | BindingFlags.Instance);
 ​
 // 读取私有字段
 Console.WriteLine(field.GetValue(config)); // "默认值"
 ​
 // 修改私有字段(反射可以突破访问限制!)
 field.SetValue(config, "新的连接字符串");

七、ConstructorInfo ------ 精确控制构造函数

csharp

复制代码
 Type t = typeof(Person);
 ​
 // 获取有参构造 (string, int)
 ConstructorInfo ctor = t.GetConstructor(new Type[] { typeof(string), typeof(int) });
 ​
 // 调用构造函数
 Person p = (Person)ctor.Invoke(new object[] { "张三", 25 });

八、Attribute(特性)的反射读取

这是反射最常见的实际用途之一:

csharp

复制代码
 // 自定义特性
 [AttributeUsage(AttributeTargets.Property)]
 public class DisplayNameAttribute : Attribute
 {
     public string Name { get; }
     public DisplayNameAttribute(string name) => Name = name;
 }
 ​
 public class Person
 {
     [DisplayName("姓名")]
     public string Name { get; set; }
 ​
     [DisplayName("年龄")]
     public int Age { get; set; }
 }
 ​
 // 运行时读取特性
 foreach (var prop in typeof(Person).GetProperties())
 {
     var attr = prop.GetCustomAttribute<DisplayNameAttribute>();
     if (attr != null)
     {
         Console.WriteLine($"属性 {prop.Name} 的显示名是: {attr.Name}");
     }
 }
 // 属性 Name 的显示名是: 姓名
 // 属性 Age 的显示名是: 年龄

九、BindingFlags 速查

很多 Get* 方法都需要 BindingFlags 来控制搜索范围:

Flag 含义
Public 公开成员
NonPublic 私有/保护成员
Instance 实例成员
Static 静态成员
DeclaredOnly 只查本类,不查父类

csharp

复制代码
 // 获取所有实例成员(包括私有)
 BindingFlags flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instanc

十、完整综合示例

csharp

复制代码
 using System;
 using System.Reflection;
 ​
 public class Person
 {
     public string Name { get; set; }
     public int Age { get; set; }
     private string _secret = "私密信息";
 ​
     public Person() { }
     public Person(string name, int age) { Name = name; Age = age; }
 ​
     public string Greet() => $"你好,我是{Name}";
 }
 ​
 class Program
 {
     static void Main()
     {
         // 1. 获取 Type
         Type type = typeof(Person);
 ​
         // 2. 动态创建对象
         Person p = (Person)Activator.CreateInstance(type, "张三", 30);
 ​
         // 3. 遍历属性
         foreach (PropertyInfo prop in type.GetProperties())
         {
             Console.WriteLine($"[属性] {prop.Name} " +
                               $"类型:{prop.PropertyType.Name} " +
                               $"值:{prop.GetValue(p)}");
         }
 ​
         // 4. 动态调用方法
         MethodInfo greet = type.GetMethod("Greet");
         Console.WriteLine(greet.Invoke(p, null));
 ​
         // 5. 读取私有字段
         FieldInfo secret = type.GetField("_secret",
             BindingFlags.NonPublic | BindingFlags.Instance);
         Console.WriteLine(secret.GetValue(p));
     }
 }
 ​
 // 输出:
 // [属性] Name 类型:String 值:张三
 // [属性] Age  类型:Int32  值:30
 // 你好,我是张三
 // 私密信息

总结:关系梳理

复制代码
 typeof(X) 或 obj.GetType()
         ↓
       Type  ──────────────────────────── 反射入口
       ├── GetProperties() → PropertyInfo[]
       │       ├── .Name          属性名
       │       ├── .PropertyType  值的类型(也是Type)
       │       ├── .GetValue(obj) 读值
       │       └── .SetValue(obj) 写值
       ├── GetMethods()    → MethodInfo[]
       │       └── .Invoke(obj, args[])
       ├── GetFields()     → FieldInfo[]
       └── GetConstructors() → ConstructorInfo[]
 ​
 Activator.CreateInstance(type)
         ↑
      动态 new 对象,不需要在编译期知道类型

你迷糊的核心点:

  • Type = 类型的"身份证",描述这个类长什么样

  • PropertyInfo = 某一个属性的"描述卡"

  • PropertyType = 这个属性存的值是什么类型(是 Type 对象)

  • Activator = 动态 new 对象的工具

相关推荐
Captaincc3 小时前
来自 Codex 官方团队的分享:如何把 Codex 用到极致
前端·vibecoding
见叶之秋3 小时前
C++基础入门指南
开发语言·c++
计算机安禾3 小时前
【c++面向对象编程】第42篇:模板特化与偏特化:为特定类型定制实现
开发语言·c++·算法
qq_401700413 小时前
Qt 项目中使用 QSS 的全面总结
开发语言·qt
玖釉-4 小时前
C++ 中的循环语句详解:while、do...while、for、嵌套循环与循环控制
开发语言·c++·算法
lichenyang4534 小时前
鸿蒙聊天 Demo 练习 05:新增登录功能,实现登录态保存与页面访问控制
前端
XMYX-04 小时前
37 - Go env 环境变量:配置管理与运行时控制
开发语言·golang
还有多久拿退休金4 小时前
我用 Three.js 造了个 3D 漫步世界,角色走路像喝醉了——以及我是怎么修好的
前端·vue.js
SZLSDH4 小时前
场景适配论 | 数字孪生IOC建设中渲染技术与智能体能力的协同逻辑
前端·数据库·ai·数字孪生·数据可视化·智能体