主页 > 人工智能  > 

反射和特性

反射和特性
反射(Reflection)

反射是C#中强大的机制,允许程序在运行时动态获取类型信息、操作对象或调用方法,而无需在编译时明确直到类型的定义。

动态类型操作

通过Type类获取类型信息(如typeof()或obj.GetType()),检查继承关系(IsSubclassOf)、接口实现(IsAssignableFrom)等。

动态创建实例:Activator.CreateInstance支持通过构造函数参数甚至私有构造方法实例化对象。

调用方法和属性:通过MethodInfo.Invoke执行方法,PropertyInfo.SetValue设置属性值。

处理泛型:例如通过MakeGenericType创建泛型类实例,MakeGenericMethod调用泛型方法。

程序集操作

加载外部程序集:Assembly.LoadFrom或Assembly.LoadFile动态加载DLL。

遍历程序集的类型和成员:例如获取所有公共方法或私有字段。

性能与限制

反射虽灵活,但存在性能开销(因动态解析类型)和安全性风险(如访问私有成员破坏封装)。

适用场景:序列化、依赖注入、测试框架等需要动态行为的场景

使用方法

获取类型信息

通过Type类获取对象的类型元数据

Type type = typeof(int); // 通过类型名 Type type2 = myObj.GetType(); // 通过对象实例

动态创建对象

       使用Activator.CreateInstance创建实例

Type type = typeof(MyClass); object instance = Activator.CreateInstance(type); 访问成员

        获取属性、方法、字段信息

PropertyInfo[] props = type.GetProperties(); MethodInfo method = type.GetMethod("MyMethod");  动态调用方法

         通过反射调用方法

MethodInfo method = type.GetMethod("Add"); int result = (int)method.Invoke(instance, new object[] { 2, 3 }); 汇总使用场景

插件系统:动态加载程序集(DLL)并调用其功能。

序列化/反序列化:通过反射便利对象的属性生成JSON/XML。

ORM框架:将数据库记录映射到对象属性。

单元测试框架:自动发现并执行测试方法。

注意要点

反射操作通常比静态代码慢,需要慎重使用。

缓存Type或MethodInfo对象。

使用dynamic关键字(动态类型)。

改用表达树(Expression Trees)或源代码生成器(Souree Generators)。

反射官方文档

属性和反射 - C# | Microsoft Learn

特性(Attributes)

特性是为代码元素(类、方法、属性等)添加元数据的标记,这些元数据可通过反射在运行时读取,用于控制程序行为或提供额外信息。

内置常用类型

[AttributeUsage]  约束自定义特性的应用目标(如类、方法)和是否允许多次应用。 

[Obsolete]  标记方法或类已过时。  

[Obsolete("Use NewMethod instead", error: true)] public void OldMethod() { }

[Serializable]  标记类可序列化。 

[DllImport] 用于调用非托管代码。

 [Conditional] 条件编译(如调试代码): [Conditional("DEBUG")] public void Log(string message) { } 自定义特性 自定特性类 继承Attribute类并添加元数据 [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true)] public class AuthorAttribute : Attribute { public string Name { get; } public AuthorAttribute(string name) => Name = name; }

应用特性 将特性标记到目标代码元素

[Author("John")] [Author("Jane", Version = 2.0)] // 允许通过属性传递参数 public class MyClass { } 通过反射读取特性 在运行时获取特性信息 Type type = typeof(MyClass); var attributes = type.GetCustomAttributes(typeof(AuthorAttribute), false); foreach (AuthorAttribute attr in attributes) { Console.WriteLine($"作者: {attr.Name}"); } 汇总使用场景

验证逻辑:通过特性标记必填字段(类似[Required])。

Web路由:ASP.NET Core中[HttpGet]、[Route]等特性定义API端点。

权限控制:自定义[Authorize]特性限制访问权限。

文档生成:为Swagger等工具提供API描述信息([ApiExplorer])。

特性官方文档

属性和反射 - C# | Microsoft Learn

反射与特性的协同

两者结合可实现高度动态化的编程模式:

元数据驱动设计

特性提供结构化元数据(如[Required]验证标记),反射在运行时读取并执行逻辑(如自动验证字段)。

示例:ASP.NET MVC通过[HttpGet]等特性标记控制器方法,反射解析路由并调用对应方法。

动态代码生成与扩展

反射可动态生成类型(如Emit技术),特性则为生成的代码添加配置信息。

序列化库(如JSON.NET )利用特性控制序列化行为(如[JsonPropertyName]),反射遍历属性进行转换。

反射和特性优缺特点 技术优点缺点反射动态性高、支持通用代码(如插件系统)性能低、破坏封装、代码可读性差特性声明式编程、简化配置、增强元数据过度使用导致维护困难、兼容性依赖运行时版本 反射和特性使用方面 自动注册服务:通过扫描程序集中标记了`[Service]`特性的类,实现依赖注入。AOP(面向切面编程):通过特性标记需要拦截的方法,利用反射动态生成代理。 // 自定义特性标记Excel列索引 [AttributeUsage(AttributeTargets.Property)] public class ExcelColumnAttribute : Attribute { public int Index { get; } public ExcelColumnAttribute(int index) => Index = index; } public class Product { [ExcelColumn(0)] public string Name { get; set; } [ExcelColumn(1)] public decimal Price { get; set; } } // 反射读取特性并映射Excel数据 public static List<Product> ParseExcel(string filePath) { var products = new List<Product>(); var type = typeof(Product); foreach (var prop in type.GetProperties()) { var attr = prop.GetCustomAttribute<ExcelColumnAttribute>(); if (attr != null) { // 根据attr.Index读取Excel列并赋值 } } return products; }

反射和特性注意事项

安全性:反射可能绕过访问修饰符(如访问私有成员),需谨慎使用。

维护性:过度依赖反射会降低代码可读性,尽量通过接口或泛型替代。

性能敏感场景:避免在频繁执行的代码路径中使用反射。

标签:

反射和特性由讯客互联人工智能栏目发布,感谢您对讯客互联的认可,以及对我们原创作品以及文章的青睐,非常欢迎各位朋友分享到个人网站或者朋友圈,但转载请说明文章出处“反射和特性