02-C#.Net-反射-学习笔记

C#反射 优点: 1. 提高程序的灵活性与可扩展性,耦合度; 缺点: 1. 过多使用,会造成逻辑模糊,因为反射已经绕过的源码,看不到逻辑实现,会造成后期维护上的困扰 2. 性能的问题,使用反射处在解释的操作,主要应用在对灵活性和拓展性要求很高的系统框架上,普通程序不建议使用 小结:.Net应用程序由几个部分:‘程序集(Assembly)’、‘模块(Module)’、‘类型(... 阅读详情

一、反射基础概念

1.1 什么是反射?

反射(Reflection)是 C# 中的一项强大功能,来自 System.Reflection 命名空间。它允许程序在运行时动态地:

  • 读取程序集(DLL/EXE)的元数据(metadata)
  • 创建对象实例
  • 调用方法
  • 访问字段和属性

1.2 编译过程理解

高级语言(C#代码)
    ↓ 编译
DLL/EXE 文件
    ├── Metadata(元数据):记录了 DLL 中包含的类型、方法等信息
    └── IL(中间语言):编译后的中间代码,面向对象语言

反编译工具(如 ILSpy)也是利用同样的原理,把 dll 逆向还原成 C# 或 IL 代码。

1.3 反射的应用场景

  • 封装框架
  • 系统开发
  • MVC 框架(通过 URL 路由调用方法)
  • IOC 容器(依赖注入)
  • ORM 框架(对象关系映射)

二、反射创建对象

2.1 传统方式 vs 反射方式

传统方式:

IDBHelper dBHelper = new SqlServerHelper();
dBHelper.Query();

缺点:代码与具体类强耦合,切换实现需要修改代码并重新编译。

反射方式(五步走):

// 1. 动态加载 DLL(三种方式)
Assembly assembly = Assembly.LoadFrom("Business.DB.SqlServer.dll");  // DLL 名称
// Assembly assembly = Assembly.LoadFile(@"完整路径\Business.DB.SqlServer.dll");  // 全路径
// Assembly assembly = Assembly.Load("Business.DB.SqlServer");  // 不需要后缀

// 2. 获取类型(需要类的全名称,含命名空间)
Type type = assembly.GetType("Business.DB.SqlServer.SqlServerHelper");

// 3. 创建对象
object oInstance = Activator.CreateInstance(type);

// 4. 类型转换(推荐使用 as,转换失败返回 null 而不是抛异常)
IDBHelper helper = oInstance as IDBHelper;

// 5. 调用方法
helper.Query();

为什么不能直接用 oInstance.Query()?

C# 是强类型语言,编译时以左边声明的类型为准。oInstance 声明为 object,编译器不知道它有 Query 方法,所以编译不通过。

2.2 dynamic 关键字

// 使用 dynamic 可以避开编译器检查,运行时决定类型
dynamic dInstance = Activator.CreateInstance(type);
dInstance.Query();        // 正常
dInstance.NotExist();     // 编译通过,运行时报错

三、简单工厂模式 + 反射 + 配置文件

3.1 实现可配置的工厂

这是反射最核心的应用场景之一,也是 IOC 容器的雏形。

appsettings.json 中配置:

{
  "ReflictionConfig": "Business.DB.Orcale.OrcaleHelper,Business.DB.Orcale.dll"
}

工厂类读取配置,动态创建对象:

public class SimpleFactory
{
    public static IDBHelper CreateInstance()
    {
        string config = CustomConfigManager.GetConfig("ReflictionConfig");
        // 格式:Business.DB.SqlServer.SqlServerHelper,Business.DB.SqlServer.dll
        string typeName = config.Split(',')[0];
        string dllName  = config.Split(',')[1];

        Assembly assembly = Assembly.LoadFrom(dllName);
        Type type = assembly.GetType(typeName);
        object oInstance = Activator.CreateInstance(type);

        return oInstance as IDBHelper;
    }
}

3.2 优势

  • 依赖倒置原则:依赖于抽象(接口)而非具体实现
  • 可配置:切换数据库只需修改配置文件,不需要改代码、不需要重新编译
  • 可扩展:添加新功能只需实现接口、复制 DLL 到执行目录、修改配置文件,无需停止程序

四、反射的"黑科技"——破坏单例

反射可以访问私有构造函数,破坏单例模式:

// 正常单例使用
Singleton singleton1 = Singleton.GetInstance();
Singleton singleton2 = Singleton.GetInstance();
Console.WriteLine(object.ReferenceEquals(singleton1, singleton2));  // True

// 反射破坏单例(第二个参数 true 表示允许访问私有构造函数)
Assembly assembly = Assembly.LoadFrom("Business.DB.SqlServer.dll");
Type type = assembly.GetType("Business.DB.SqlServer.Singleton");
Singleton s1 = (Singleton)Activator.CreateInstance(type, true);
Singleton s2 = (Singleton)Activator.CreateInstance(type, true);
Console.WriteLine(object.ReferenceEquals(s1, s2));  // False - 单例被破坏!

关键点:反射可以无视访问修饰符(private、protected 等)。访问修饰符是编译器层面的约束,反射在运行时直接操作元数据,完全绕过编译器检查。


五、反射调用构造函数和方法

5.1 调用带参数的构造函数

Activator.CreateInstance 的第二个参数接收 object[],按参数类型严格匹配:

Assembly assembly = Assembly.LoadFrom("Business.DB.SqlServer.dll");
Type type = assembly.GetType("Business.DB.SqlServer.ReflectionTest");

// 无参构造
object noParaObject = Activator.CreateInstance(type);

// 有参构造(严格匹配参数类型,没有匹配的构造函数会抛异常)
object paraObject1 = Activator.CreateInstance(type, new object[] { 123 });          // ReflectionTest(int)
object paraObject2 = Activator.CreateInstance(type, new object[] { "张三" });       // ReflectionTest(string)
object paraObject3 = Activator.CreateInstance(type, new object[] { 234, "李四" });  // ReflectionTest(int, string)

5.2 反射调用方法

a. 调用无参方法
object oInstance = Activator.CreateInstance(type);
MethodInfo show1 = type.GetMethod("Show1");
show1.Invoke(oInstance, null);  // 或 new object[0]
b. 调用有参方法(处理重载)

重载方法同名,需要通过参数类型数组来区分:

// Show3(string name, int id)
MethodInfo show31 = type.GetMethod("Show3", new Type[] { typeof(string), typeof(int) });
show31.Invoke(oInstance, new object[] { "张三", 234 });

// Show3(int id)
MethodInfo show32 = type.GetMethod("Show3", new Type[] { typeof(int) });
show32.Invoke(oInstance, new object[] { 345 });
c. 调用私有方法
MethodInfo show4 = type.GetMethod("Show4", BindingFlags.NonPublic | BindingFlags.Instance);
show4.Invoke(oInstance, new object[] { "参数" });
d. 调用静态方法

静态方法调用时,第一个参数(实例)传 null:

MethodInfo show5 = type.GetMethod("Show5");
show5.Invoke(null, new object[] { "参数" });

5.3 调用泛型方法

泛型是"延迟声明",调用时才确定类型。需要先用 MakeGenericMethod 确定类型参数:

Type type = assembly.GetType("Business.DB.SqlServer.GenericMethod");
object oInstance = Activator.CreateInstance(type);

MethodInfo show = type.GetMethod("Show");
// 确定泛型类型参数
MethodInfo genericShow = show.MakeGenericMethod(new Type[] { typeof(int), typeof(string), typeof(DateTime) });
genericShow.Invoke(oInstance, new object[] { 123, "张三", DateTime.Now });

5.4 创建泛型类实例

泛型类的类型名称后面要加反引号和参数数量,如 GenericClass`3,然后用 MakeGenericType 确定类型:

// GenericClass<T, W, X> → "GenericClass`3"
Type type = assembly.GetType("Business.DB.SqlServer.GenericClass`3");
Type genericType = type.MakeGenericType(new Type[] { typeof(int), typeof(string), typeof(DateTime) });
object oInstance = Activator.CreateInstance(genericType);

MethodInfo show = genericType.GetMethod("Show");
show.Invoke(oInstance, new object[] { 123, "张三", DateTime.Now });

5.5 类和方法都有泛型参数

两者需要分别处理,先 MakeGenericType 再 MakeGenericMethod:

// GenericDouble<T> 类 + Show<W, X> 方法
Type type = assembly.GetType("Business.DB.SqlServer.GenericDouble`1");
Type genericType = type.MakeGenericType(new Type[] { typeof(int) });
object oInstance = Activator.CreateInstance(genericType);

MethodInfo show = genericType.GetMethod("Show");
MethodInfo genericMethod = show.MakeGenericMethod(new Type[] { typeof(string), typeof(DateTime) });
genericMethod.Invoke(oInstance, new object[] { 123, "张三", DateTime.Now });

六、反射操作属性和字段

6.1 传统方式

People people = new People();
people.Id = 134;
people.Name = "张三";
people.Age = 25;
Console.WriteLine($"Id={people.Id}, Name={people.Name}");

6.2 反射方式

Type type = typeof(People);
object pObject = Activator.CreateInstance(type);

// 设置属性值
foreach (var prop in type.GetProperties())
{
    if (prop.Name.Equals("Id"))   prop.SetValue(pObject, 134);
    if (prop.Name.Equals("Name")) prop.SetValue(pObject, "张三");
    if (prop.Name.Equals("Age"))  prop.SetValue(pObject, 25);
}

// 获取所有属性值(不需要写死属性名)
foreach (var prop in type.GetProperties())
{
    Console.WriteLine($"people.{prop.Name}={prop.GetValue(pObject)}");
}

// 操作字段
foreach (var field in type.GetFields())
{
    Console.WriteLine($"{field.Name}={field.GetValue(pObject)}");
}

6.3 反射取值的优势

实体类新增属性时,反射代码无需修改,程序更稳定。传统方式则必须修改代码、重新编译发布。


七、手写 ORM 框架(反射 + 泛型)

7.1 核心思想

通过反射 + 泛型实现通用的数据库查询方法,一个方法支持所有实体类型。

7.2 实现代码

public T Find<T>(int id) where T : BaseModel
{
    Type type = typeof(T);
    object oResult = Activator.CreateInstance(type);

    using (SqlConnection connection = new SqlConnection(ConnectionString))
    {
        connection.Open();

        // 反射动态生成 SQL:Select [Id],[Name],... from SysUser where id=1
        string sql = $"Select {string.Join(',', type.GetProperties().Select(c => $"[{c.Name}]"))} from {type.Name} where id={id}";

        SqlDataReader reader = new SqlCommand(sql, connection).ExecuteReader();
        if (reader.Read())
        {
            foreach (var prop in type.GetProperties())
            {
                // DBNull 处理:数据库空值转为 null
                prop.SetValue(oResult, reader[prop.Name] is DBNull ? null : reader[prop.Name]);
            }
        }
    }

    return (T)oResult;
}

7.3 使用示例

SqlServerHelper sqlServer = new SqlServerHelper();
SysCompany company = sqlServer.Find<SysCompany>(1);
SysUser user = sqlServer.Find<SysUser>(17);

前提条件:实体类属性名必须与数据库列名完全一致,且实体类继承 BaseModel(保证有 Id 字段)。

7.4 优化:泛型缓存

每次调用 Find<T> 都重新生成 SQL 是浪费的,同一个类型的 SQL 结构是固定的。利用泛型类的静态构造函数实现缓存:

public class ConstantSqlString<T>
{
    private static string FindSql = null;

    // 静态构造函数:每个泛型类型 T 只执行一次(CLR 保证)
    static ConstantSqlString()
    {
        Type type = typeof(T);
        FindSql = $"Select {string.Join(',', type.GetProperties().Select(c => $"[{c.Name}]"))} from {type.Name} where id=";
    }

    public static string GetFindSql(int id) => $"{FindSql}{id}";
}

使用:

string sql = ConstantSqlString<T>.GetFindSql(id);

原理:ConstantSqlString<SysUser> 和 ConstantSqlString<SysCompany> 是两个不同的类,各自的静态构造函数只执行一次,SQL 模板只生成一次,后续直接复用。


八、反射性能问题

8.1 性能测试结果

实测对比(循环 100 万次创建对象 + 调用方法):

方式耗时
普通 new~17 毫秒
反射(每次 LoadFrom)~6300 毫秒
反射(LoadFrom 缓存到循环外)~71 毫秒

8.2 性能优化建议

把 Assembly.LoadFrom 和 assembly.GetType 提到循环外,只执行一次,后续复用 Type 对象:

// 不推荐:每次都加载
for (int i = 0; i < 1_000_000; i++)
{
    Assembly assembly = Assembly.LoadFrom("Business.DB.SqlServer.dll");
    Type type = assembly.GetType("Business.DB.SqlServer.SqlServerHelper");
    object oInstance = Activator.CreateInstance(type);
}

// 推荐:缓存加载结果
Assembly assembly = Assembly.LoadFrom("Business.DB.SqlServer.dll");
Type dbHelperType = assembly.GetType("Business.DB.SqlServer.SqlServerHelper");
for (int i = 0; i < 1_000_000; i++)
{
    object oInstance = Activator.CreateInstance(dbHelperType);
    IDBHelper helper = (IDBHelper)oInstance;
    helper.Query();
}

结论:反射经过缓存优化后,性能损耗是可以接受的,实际项目中可以放心使用。


九、Emit 技术(动态生成代码)

9.1 什么是 Emit?

Emit 是反射的进阶能力,可以在程序运行时动态生成 dll、类、方法、字段等,来自 System.Reflection.Emit 命名空间。

  • 反射是"读":读取已有程序集的元数据并使用它。
  • Emit 是"写":在运行时动态生成新的程序集和代码。

生成步骤(建造者模式):

AssemblyBuilder → ModuleBuilder → TypeBuilder → FieldBuilder / MethodBuilder

9.2 基本使用

// 1. 创建程序集
AssemblyBuilder assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(
    new AssemblyName("DynamicAssemblyExample"),
    AssemblyBuilderAccess.RunAndCollect);

// 2. 创建模块
ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule("MyModal");

// 3. 创建类型
TypeBuilder typeBuilder = moduleBuilder.DefineType("MyDynamicType", TypeAttributes.Public);

// 4. 创建字段
FieldBuilder fieldBuilder = typeBuilder.DefineField("NumberField", typeof(int), FieldAttributes.Public);

// 5. 创建构造函数,用 IL 写逻辑
ConstructorBuilder ctor = typeBuilder.DefineConstructor(
    MethodAttributes.Public, CallingConventions.Standard, new Type[] { typeof(int) });
ILGenerator ctorIL = ctor.GetILGenerator();
ctorIL.Emit(OpCodes.Ldarg_0);  // 加载 this
ctorIL.Emit(OpCodes.Call, typeof(object).GetConstructor(Type.EmptyTypes));
ctorIL.Emit(OpCodes.Ldarg_0);  // 加载 this
ctorIL.Emit(OpCodes.Ldarg_1);  // 加载参数
ctorIL.Emit(OpCodes.Stfld, fieldBuilder);  // 赋值给字段
ctorIL.Emit(OpCodes.Ret);

// 6. 创建方法
MethodBuilder method = typeBuilder.DefineMethod(
    "ConsoleMethod", MethodAttributes.Public | MethodAttributes.Static, null, null);
ILGenerator methodIL = method.GetILGenerator();
methodIL.Emit(OpCodes.Ldstr, "欢迎来到高级班学习");
methodIL.Emit(OpCodes.Call, typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string) }));
methodIL.Emit(OpCodes.Ret);  // IL 方法最后必须有 Ret

// 7. 创建类型并使用
Type dynamicType = typeBuilder.CreateType();
object instance = Activator.CreateInstance(dynamicType, new object[] { 123456 });
MethodInfo consoleMethod = dynamicType.GetMethod("ConsoleMethod");
consoleMethod.Invoke(instance, null);

9.3 特点

  • 动态性强:可在运行时定义业务逻辑
  • 性能极高:生成的代码和手写代码一样快
  • 学习成本高:需要了解 IL 指令
  • 应用场景:动态代理、AOP 切面编程、高性能序列化等

十、反射核心知识点总结

10.1 加载程序集的三种方式

方法参数说明
LoadFromDLL 名称(需要后缀)最常用,支持相对路径,自动解析依赖
LoadFile完整路径(需要后缀)必须绝对路径,不自动解析依赖
LoadDLL 名称(不需要后缀)从 GAC 或应用程序目录加载

10.2 BindingFlags 常用组合

BindingFlags.Public | BindingFlags.Instance    // 公共实例成员
BindingFlags.NonPublic | BindingFlags.Instance  // 私有实例成员
BindingFlags.Public | BindingFlags.Static       // 公共静态成员
BindingFlags.NonPublic | BindingFlags.Static    // 私有静态成员

10.3 typeof(T) vs obj.GetType()

  • typeof(T):编译时操作,T 必须是已知类型名称
  • obj.GetType():运行时操作,返回对象实际运行时类型
IDBHelper helper = new SqlServerHelper();
typeof(IDBHelper)   // → IDBHelper(接口类型)
helper.GetType()    // → SqlServerHelper(实际运行时类型)

10.4 反射的优缺点

优点:

  • 动态性:运行时决定行为
  • 灵活性:解耦具体实现
  • 可扩展性:无需修改代码即可扩展功能
  • 强大性:可访问私有成员

缺点:

  • 性能开销:比直接调用慢(可通过缓存优化)
  • 类型安全:编译时无法检查
  • 代码可读性:相对复杂

十一、实际应用场景

11.1 MVC 框架路由

URL: http://localhost/Home/Index
      ↓
通过反射:
1. 根据 "Home" 创建 HomeController 实例
2. 根据 "Index" 调用 Index 方法

11.2 IOC 容器

// 配置:接口 → 实现类映射
container.Register<IDBHelper, SqlServerHelper>();

// 使用:自动创建实例(底层是反射)
IDBHelper helper = container.Resolve<IDBHelper>();

11.3 ORM 框架

// 一个方法支持所有实体类型
var user = dbContext.Find<SysUser>(1);
var company = dbContext.Find<SysCompany>(1);

附录:常用 API 速查

Assembly 类

Assembly.LoadFrom(string)       // 加载程序集
assembly.GetType(string)        // 获取类型
assembly.GetTypes()             // 获取所有类型
assembly.GetModules()           // 获取所有模块

Type 类

type.GetConstructors()          // 获取构造函数
type.GetMethods()               // 获取方法
type.GetProperties()            // 获取属性
type.GetFields()                // 获取字段
type.GetMethod(name, types)     // 获取指定重载方法
type.MakeGenericType(types)     // 构造泛型类型

Activator 类

Activator.CreateInstance(type)              // 创建实例(无参)
Activator.CreateInstance(type, args)        // 创建实例(有参)
Activator.CreateInstance(type, true)        // 访问私有构造

MethodInfo 类

method.Invoke(instance, parameters)         // 调用方法
method.MakeGenericMethod(types)             // 构造泛型方法

PropertyInfo / FieldInfo 类

prop.GetValue(instance)                     // 获取属性值
prop.SetValue(instance, value)              // 设置属性值
field.GetValue(instance)                    // 获取字段值
field.SetValue(instance, value)             // 设置字段值
C# 反射详解 反射是C#中的一个强大特性,允许程序在检查和操作类型和对象的信息。通过反射,你可以获取类型的等信息,并可以动态创建对象、调用方法或访问属性,甚至可以实现某些框架或库的核心功能。 阅读详情

相关推荐

C#学习笔记(下)

经本人搜集网上资料后整合而成的C#学习笔记,知识点很全面,前面某些很基础的内容绝大部分人都已经在学C/C++的时候学过了,所以基本一笔带过,其它地方都尽量写的很详细。由于篇幅过长所以分成上下篇,内容可能随时会更新,若有不足之处还请大佬多多指出,感谢大家的阅读。上篇:C#学习笔记(上)参考:特性(Attribute)是一种用于在程序运行时传递各种元素(如类、方法、枚举、方法参数等)的行为信息的声明性代码,提供了一种将元数据或声明性信息与代码(程序集、类型、方法、属性等)相关联的方法。元数据(metadata)

m0_75104457的博客 890

C#反射详解

目录 反射定义反射(C# 编程指南) 使用场景 形象说明 反射的用途 反射用到的主要类 System.Type类用法 实例应用 System.Reflection.Assembly类的用法 反射定义反射(C# 编程指南)   反射提供了封装程序集、模块和类型的对象(Type类型)。可以使用反射动态创建类型的实例,将类型绑定到现有对象,或从现有对象获取类型并调用其方法或访问其字段和属性。如果代码中使用了特性,可以利用反射对它们进行访问。 使用场景 需要访问程序元数据的特性。 检查..

潘达小新 5776

2021-05-23 .NET高级班 02-反射

原理图 /// <summary> /// 1 dll-IL-metadata-反射 /// 2 反射加载dll,读取module、类、方法 /// 3 反射创建对象,反射+简单工厂+配置文件 ,破坏单例 创建泛型 /// 反射反射程序员的快乐 /// 反射是无处不在,MVC AOP IOC ORM Attribute /// IL:中间语言,标准的面向对象语言,但是不太好阅读 /// metadata:元数据, 数据清单,只是

愚公智库 52万+

C#反射学习笔记

AppDomain(应用程序域):一个进程中可以有很多个应用程序域,创建的一个控制台项目是一个进程,运行的代码是在进程默认的应用程序域中在执行,一个应用程序域中可以有多个程序集。:参数是程序集的强名称或者简单名称,只能在程序的输出目录中检索,通常是bin文件夹。加载目标程序集时会加载依赖的程序集。通过具体的路径加载程序集,不会加载依赖程序集。通过具体的路径加载程序集,会加载依赖程序集。元数据:包含程序集信息(引用的其他程序集等)、模块信息、这个是下面反射获取的类的具体信息。

Mo_Chang的博客 1089

.NET c#反射

一.反射的定义 反射提供了封装程序集、模块和类型的对象(Type类型)。可以使用反射动态创建类型的实例,将类型绑定到现有对象,或从现有对象获取类型并调用其方法或访问其字段和属性。 反射可以实现从对象的外部来了解对象(或程序集)内部结构的功能,哪怕你不知道这个对象(或程序集)是个什么东西,另外.NET中的反射还可以运态创建出对象并执行它其中的方法。 二.反射的命名空间 System.Reflecti...

qq_43434300的博客 236

详解C#反射(Reflection)

详解C#反射的概念和用法

ellis1970的博客 2090

详解(C#) .NET反射中的BindingFlags以及常用的BindingFlags使用方式

@[toc](详解(C#) .NET反射中的BindingFlags以及常用的BindingFlags使用方式) 使用 .NET 的反射 API 时,通常会要求我们传入一个BindingFlags参数用于指定反射查找的范围。不过如果对反射不熟的话,第一次写反射很容易写错导致找不到需要的类型成员。 本文介绍BindingFlags中的各个枚举标记的含义、用途,以及常用的组合使用方式。 所有的BindingFlags 默认值 // 默认值 Default 查找 这些标记用于反射的时候查找类型成员: // 表示

天富儿的博客 6177

2.1 量子精密测量:SERF原子陀螺仪中的核自旋-电子自旋强耦合机制

本文深入解析了SERF原子陀螺仪中核自旋-电子自旋强耦合机制的核心原理与应用。通过量子精密测量技术,SERF陀螺仪实现了超高精度的惯性导航,其独特的磁场自补偿和拉莫尔进动特性使其在弱磁场环境下表现出色。文章还探讨了关键技术突破和前沿进展,展示了量子精密测量在惯性导航领域的巨大潜力。

kotlin6android的博客 210

详谈C#反射及应用

反射 什么是元数据?什么是反射? 程序数用来处理数据的,文本和特性都是数据,而程序本身(类的定义和BLC中的类)这些也是数据。 有关程序及其类型的数据被称为元数据,他们保存在程序集中。 程序在运行时,可以查看其他程序集或其本身元数据。一个运行的程序查看本身的元数据或其他程序集的元数据的行为称为反射。 Type 使用 Type 类进行反射,使用特性给类型添加元数据 对于程序中用到的每个类型,CLR 都会创建一个包含这个类型信息的 Type 对象。 程序中每用到一个类型都会关联到独立的 Type 类的对象

菜鸟厚非 2万+

英飞凌TC3xx DSADC旋变软解码实战:从示波器波形到VX1000数据,手把手教你避坑

本文详细介绍了英飞凌TC3xx系列微控制器的DSADC模块在电机旋变软解码中的实战应用。从示波器波形分析到VX1000数据采集,提供了一套完整的调试方法论,帮助工程师快速定位和解决常见问题,提升解码精度和系统性能。

weixin_30598225的博客 517

KiCad自动布线实战:FreeRouting插件安装与使用指南

在PCB设计流程中,布线环节往往占据大量重复性工作,尤其对于中小型双面板,成百上千条飞线的手动连接既繁琐又易出错。自动布线技术通过算法在给定设计规则和元件布局的基础上自动规划走线路径,能显著提升布线效率。FreeRouting作为一款开源自动布线器,与KiCad通过DSN/SES标准中间格式无缝配合,让工程师将精力集中于关键信号和布局优化,而将常规网络交给工具处理。本文从自动布线的原理与边界出发,讲解了FreeRouting的安装、DSN导出、参数设置、自动布线及结果回传的完整流程,并结合实际案例展示了在S

weixin_32025789的博客 277

C# 属性的反射介绍

C# 属性的反射为开发者提供了一种强大的工具,使得代码能够在运行时动态地检查和操作对象的属性。通过反射,我们可以实现很多灵活的功能,如动态配置、序列化和反序列化以及插件扩展机制等。然而,反射也会带来一定的性能开销,因为它涉及到在运行时解析类型和成员信息,所以在使用反射时需要权衡利弊,根据具体的应用场景合理使用。希望通过本文的介绍,你对 C# 属性的反射有了更深入的理解,并能在实际开发中灵活运用这一强大的特性。

zsnandzmn的博客 1568

计算机视觉之ResNet

RestNet是2015年由微软团队提出的,在当时获得分类任务,目标检测,图像分割第一名。该论文的四位作者何恺明、张祥雨、任少卿和孙剑如今在人工智能领域里都是响当当的名字,当时他们都是微软亚研的一员。实验结果显示,残差网络更容易优化,并且加深网络层数有助于提高正确率。在ImageNet上使用152层的残差网络(VGG net的8倍深度,但残差网络复杂度更低)。对这些网络使用集成方法实现了3.75%的错误率。获得了ILSVRC 2015竞赛的第一名。原文链接这是一篇计算机视觉领域的经典论文。

十年以上架构设计经验,专注于软件架构和人工智能领域,对机器视觉、NLP、音视频等领域都有涉猎 2万+

.Net C# 反射 总结

前言 2020了,时光不等人啊。一想到 【20后的小朋友看90后的大叔,就跟90后看60后是一样的】,心里不由的产生一股悲哀与恐惧。于是总会不断的问自己,时光带来的是什么?带走的又是什么? 最可怕的就是: 时光带走的 是那个热爱生活的自己,带来的,是无尽的怨与恨 。 终将成为的样子,不可以是那些曾经最讨厌的人 的样子,不可以。 希望时光给与大家的,是愈发明亮的眼睛,既看过幽暗的夜,也看过清澈的天。...

wf824284257的博客 877

DSP(数字信号处理器)技术概要

数字信号处理器(digital signal processor,DSP)是一种用于数字信号处理的可编程微处理器,它的诞生与快速发展,使各种数字信号处理算送得以实时实现,为数字信号处理的研究和应用打开了新局面,提供了低成本的实际工作环境和应用平台,推动了新的理论和应用领域的发展。目前,DSP技术在通信、航空、航天。雷达、工业控制、医疗、网络及家用电器等各个领域都得到了广泛应用。 1.1 DSP系统和芯片的结构特点1.1.1 DSP系统的基本结构通过传感数将非电物理量转换为模拟电信号,预处理一般包括放大器和滤

m0_46582485的博客 2万+

Android以太网开关流程分析

Android以太网开关流程分析 一、引言   在Android 以太网服务启动流程中我们启动了EthernetService(ES),NetworkManagementService(NMS)等服务,其中ES作为Binder的服务端,向客户端EthernetManger提供了调用接口的引用。因此,应用可以通过EthernetManger来访问以太网的相关接口。本篇文章将从APP调用以太网的使能和关闭的接口流程作为切入点来分析,以太网框架中,上层app是如何将指令传递到底层。图1-1所示为以太网使能和关闭

franc521的博客 6112

.NET/C# 使用反射注册事件

使用反射,我们可以很容易地在运行时调用一些编译时无法确定的属性、方法等。那么如何注册事件呢? 本文将介绍如何使用反射注册事件。 这里写自定义目录标题不使用反射使用反射安全地使用反射参考资料 不使用反射 例如,我们希望反射的类型是这样的: public class Walterlv { public event EventHandler BlogPublished; } 那么只需要使用如...

walterlv - 吕毅 2301

深入LSM6DSL的FIFO连续模式:基于STM32和MEMS库的数据流高效处理指南

本文深入探讨了LSM6DSL的FIFO连续模式,结合STM32硬件平台和ST官方MEMS库,提供了高效的数据流处理方案。通过优化I2C通信时序、中断驱动设计以及动态ODR调整,实现低功耗数据采集与处理,显著提升嵌入式传感器应用的性能和续航能力。

weixin_30387799的博客 347

.net 反射

说明:原文中的代码为vb.net,我本人比较熟悉c#,所以在翻译的过程中,把vb.net代码替换成了c#代码,所以译文中的代码和原文中的代码会稍有出入,但这并不会影响你阅读。何谓反射?反射就是在运行的时候发现对象的相关信息。根据这些信息可以动态的执行对象的方法以及获取对象的属性所储存的值。使用.NET Framework编写的代码是自动反射的,或者说是自我描述的。之所以可以反射,是通过

pengdean的专栏 2872

SAP使用XCO框架创建RAP所有对象

通过XCO框架自动生成SAP ABAP开发对象。

DeveloperMrMeng的博客 545

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

【C# 】反射,调用.dll文件里面的方法

C# 反射朝夕教育vip班个人笔记文章介绍开源资源连接泛型方法的声明与调用 文章介绍 学习笔记,基于朝夕教育VIP班课程 文章主要讲了:泛型约束, 文章写的不好,自己看 开源资源连接 源码地址,推荐直接看源码 泛型方法的声明与调用 ...

Liaiblog 3347

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

学习C#中的反射

在C#编程中,反射(Reflection)是一项强大且灵活的技术,它允许程序在运行时动态地获取类型信息、创建对象实例、调用方法、访问字段和属性等。这种机制极大地增强了程序的动态性和可扩展性,使得开发者能够在编译时未知的情况下进行各种操作。本文将为初级程序员介绍C#中的反射技术,包括其用法和使用场景。

huaqianzkh的专栏 1371

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

C#学习,反射

程序是用来处理数据的,但是程序本身也是由数据组成的,有关程序及其类型的数据,元数据(Metadata),保存在程序集之中,程序在运行中,可以查看其他的程序集和自身的Metadata,一个运行的程序查看本身的元数据或其他程序集的元数据的行为称为反射。对于程序的类型,CLR都会创建一个包含这个类型的Type对象,程序中每遇到一个类型都会关联到独立的Type的对象,不管创建的类有多少实例,只有一个Type类的对象会关联到这些所有的实例。

qq_52485934的博客 1174

C#反射是什么?

//反射是.NET中的重要机制,通过反射,可以在运行时获得.NET中每一个类型 //(包括类、结构、委托、接口和枚举等)的成员,包括方法、属性、事件,以及构造函数等。 //有了反射,即可对每一个类型了如指掌,如果获得了构造函数的信息,即可直接创建对象 class Program { //反射可以看到类的属性和方法,设置和获取属性值,调用方法 // ...

qq_45195669的博客 1648
上一篇: 01-C#.Net-泛型-学习笔记
下一篇: 01-C#.Net-泛型-面试题
似水明俊德
博客等级 码龄8年 247粉丝 276原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值