当前位置: 首页 > news >正文

反射和特性

反射(Reflection)

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

  1. 动态类型操作

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

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

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

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

  2. 程序集操作

    • 加载外部程序集:Assembly.LoadFromAssembly.LoadFile动态加载DLL。

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

  3. 性能与限制

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

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

使用方法
  • 获取类型信息

    通过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框架:将数据库记录映射到对象属性。

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

注意要点

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

  • 缓存TypeMethodInfo对象。

  • 使用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

反射与特性的协同

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

  1. 元数据驱动设计

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

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

  2. 动态代码生成与扩展

    • 反射可动态生成类型(如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;
    }
    

反射和特性注意事项

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

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

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

    相关文章:

  1. Annie导航2.0 新增加5个模版 开源免授权
  2. 当机器人遇见艺术:春晚机器人舞蹈,一场科技与艺术的完美邂逅
  3. Redis实现登录优化
  4. 阿里云前端自动化部署流程指南
  5. LayUi点击查看图片组件layer.photos()用法(图片放大预览后滚动鼠标缩放、底部显示自定义标题)
  6. 观察者模式
  7. uniapp中@input输入事件在修改值只有第一次有效的问题解决
  8. RocketMQ面试题:原理部分
  9. 组学数据分析实操系列 |(四) 富集气泡图的绘制
  10. 书籍翻页动画
  11. 系统学习算法:专题十一 floodfill算法
  12. 51c自动驾驶~合集51
  13. ubuntu22.04离线安装K8S
  14. 关于deep seek的本地化部署
  15. PHP 网络编程介绍
  16. 【信息系统项目管理师】第23章:组织通用管理 详解
  17. 字符串操作总结(C# and Lua)
  18. Langchain是什么,怎么使用
  19. ls命令的全面参数解析与详尽使用指南
  20. 计算机毕业设计Python考研院校推荐系统 考研分数线预测 考研推荐系统 考研可视化(代码+LW文档+PPT+讲解视频)
  21. 普京召开俄乌谈判筹备会议,拉夫罗夫、绍伊古等出席
  22. 新闻1+1丨城市,如何对青年更友好?
  23. 沧州低空经济起飞:飞行汽车开启千亿赛道,通用机场布局文旅体验
  24. 3年多来俄乌要首次直接对话?能谈得拢吗?
  25. 崔登荣任国家游泳队总教练
  26. 茅台1935今年动销达到预期,暂无赴港上市计划!茅台业绩会回应多个热点